Textpattern PHP Cross Reference Content Management Systems

Source: /textpattern/include/txp_list.php - 612 lines - 18310 bytes - Summary - Text - Print

   1  <?php
   2  /*
   3      This is Textpattern
   4      Copyright 2005 by Dean Allen
   5       All rights reserved.
   6  
   7      Use of this software indicates acceptance of the Textpattern license agreement
   8  
   9  $HeadURL: https://textpattern.googlecode.com/svn/releases/4.5.4/source/textpattern/include/txp_list.php $
  10  $LastChangedRevision: 4089 $
  11  
  12  */
  13  
  14      if (!defined('txpinterface')) die('txpinterface is undefined.');
  15  
  16      if ($event == 'list') {
  17          global $statuses, $all_cats, $all_authors, $all_sections;
  18  
  19          require_privs('article');
  20  
  21          $statuses = array(
  22              STATUS_DRAFT   => gTxt('draft'),
  23              STATUS_HIDDEN  => gTxt('hidden'),
  24              STATUS_PENDING => gTxt('pending'),
  25              STATUS_LIVE    => gTxt('live'),
  26              STATUS_STICKY  => gTxt('sticky'),
  27          );
  28  
  29          $all_cats = getTree('root', 'article');
  30          $all_authors = the_privileged('article.edit.own');
  31          $all_sections = safe_column('name', 'txp_section', "name != 'default'");
  32  
  33          $available_steps = array(
  34              'list_list'          => false,
  35              'list_change_pageby' => true,
  36              'list_multi_edit'    => true,
  37          );
  38  
  39          if ($step && bouncer($step, $available_steps)) {
  40              $step();
  41          } else {
  42              list_list();
  43          }
  44      }
  45  
  46  //--------------------------------------------------------------
  47  
  48  	function list_list($message = '', $post = '')
  49      {
  50          global $statuses, $comments_disabled_after, $step, $txp_user, $article_list_pageby, $event;
  51  
  52          pagetop(gTxt('tab_list'), $message);
  53  
  54          extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
  55          if ($sort === '') $sort = get_pref('article_sort_column', 'posted');
  56          if ($dir === '') $dir = get_pref('article_sort_dir', 'desc');
  57          $dir = ($dir == 'asc') ? 'asc' : 'desc';
  58  
  59          $sesutats = array_flip($statuses);
  60  
  61          switch ($sort)
  62          {
  63              case 'id':
  64                  $sort_sql = 'ID '.$dir;
  65              break;
  66  
  67              case 'title':
  68                  $sort_sql = 'Title '.$dir.', Posted desc';
  69              break;
  70  
  71              case 'expires':
  72                  $sort_sql = 'Expires '.$dir;
  73              break;
  74  
  75              case 'section':
  76                  $sort_sql = 'Section '.$dir.', Posted desc';
  77              break;
  78  
  79              case 'category1':
  80                  $sort_sql = 'Category1 '.$dir.', Posted desc';
  81              break;
  82  
  83              case 'category2':
  84                  $sort_sql = 'Category2 '.$dir.', Posted desc';
  85              break;
  86  
  87              case 'status':
  88                  $sort_sql = 'Status '.$dir.', Posted desc';
  89              break;
  90  
  91              case 'author':
  92                  $sort_sql = 'AuthorID '.$dir.', Posted desc';
  93              break;
  94  
  95              case 'comments':
  96                  $sort_sql = 'comments_count '.$dir.', Posted desc';
  97              break;
  98  
  99              case 'lastmod':
 100                  $sort_sql = 'LastMod '.$dir.', Posted desc';
 101              break;
 102  
 103              default:
 104                  $sort = 'posted';
 105                  $sort_sql = 'Posted '.$dir;
 106              break;
 107          }
 108  
 109          set_pref('article_sort_column', $sort, 'list', 2, '', 0, PREF_PRIVATE);
 110          set_pref('article_sort_dir', $dir, 'list', 2, '', 0, PREF_PRIVATE);
 111  
 112          $switch_dir = ($dir == 'desc') ? 'asc' : 'desc';
 113  
 114          $criteria = 1;
 115  
 116          if ($search_method and $crit != '')
 117          {
 118              $verbatim = preg_match('/^"(.*)"$/', $crit, $m);
 119              $crit_escaped = doSlash($verbatim ? $m[1] : str_replace(array('\\','%','_','\''), array('\\\\','\\%','\\_', '\\\''), $crit));
 120              $critsql = $verbatim ?
 121                  array(
 122                      'id'         => "ID in ('" .join("','", do_list($crit_escaped)). "')",
 123                      'title_body_excerpt' => "Title = '$crit_escaped' or Body = '$crit_escaped' or Excerpt = '$crit_escaped'",
 124                      'section'    => "Section = '$crit_escaped'",
 125                      'keywords'   => "FIND_IN_SET('".$crit_escaped."',Keywords)",
 126                      'categories' => "Category1 = '$crit_escaped' or Category2 = '$crit_escaped'",
 127                      'status'     => "Status = '".(@$sesutats[gTxt($crit_escaped)])."'",
 128                      'author'     => "AuthorID = '$crit_escaped'",
 129                      'article_image' => "Image in ('" .join("','", do_list($crit_escaped)). "')",
 130                      'posted'     => "Posted = '$crit_escaped'",
 131                      'lastmod'    => "LastMod = '$crit_escaped'"
 132                  ) : array(
 133                      'id'         => "ID in ('" .join("','", do_list($crit_escaped)). "')",
 134                      'title_body_excerpt' => "Title like '%$crit_escaped%' or Body like '%$crit_escaped%' or Excerpt like '%$crit_escaped%'",
 135                      'section'    => "Section like '%$crit_escaped%'",
 136                      'keywords'   => "FIND_IN_SET('".$crit_escaped."',Keywords)",
 137                      'categories' => "Category1 like '%$crit_escaped%' or Category2 like '%$crit_escaped%'",
 138                      'status'     => "Status = '".(@$sesutats[gTxt($crit_escaped)])."'",
 139                      'author'     => "AuthorID like '%$crit_escaped%'",
 140                      'article_image' => "Image in ('" .join("','", do_list($crit_escaped)). "')",
 141                      'posted'     => "Posted like '$crit_escaped%'",
 142                      'lastmod'    => "LastMod like '$crit_escaped%'"
 143                  );
 144  
 145              if (array_key_exists($search_method, $critsql))
 146              {
 147                  $criteria = $critsql[$search_method];
 148                  $limit = 500;
 149              }
 150  
 151              else
 152              {
 153                  $search_method = '';
 154                  $crit = '';
 155              }
 156          }
 157  
 158          else
 159          {
 160              $search_method = '';
 161              $crit = '';
 162          }
 163  
 164          $criteria .= callback_event('admin_criteria', 'list_list', 0, $criteria);
 165  
 166          $total = safe_count('textpattern', "$criteria");
 167  
 168          echo '<h1 class="txp-heading">'.gTxt('tab_list').'</h1>';
 169          echo '<div id="'.$event.'_control" class="txp-control-panel">';
 170  
 171          if ($total < 1)
 172          {
 173              if ($criteria != 1)
 174              {
 175                  echo n.list_search_form($crit, $search_method).
 176                      n.graf(gTxt('no_results_found'), ' class="indicator"').'</div>';
 177              }
 178  
 179              else
 180              {
 181                  echo graf(gTxt('no_articles_recorded'), ' class="indicator"').'</div>';
 182              }
 183  
 184              return;
 185          }
 186  
 187          $limit = max($article_list_pageby, 15);
 188  
 189          list($page, $offset, $numPages) = pager($total, $limit, $page);
 190  
 191          echo n.list_search_form($crit, $search_method).'</div>';
 192  
 193          $rs = safe_rows_start('*, unix_timestamp(Posted) as posted, unix_timestamp(LastMod) as lastmod, unix_timestamp(Expires) as expires', 'textpattern',
 194              "$criteria order by $sort_sql limit $offset, $limit"
 195          );
 196  
 197          if ($rs)
 198          {
 199              $show_authors = !has_single_author('textpattern', 'AuthorID');
 200  
 201              $total_comments = array();
 202  
 203              // fetch true comment count, not the public comment count
 204              // maybe we should have another row in the db?
 205              $rs2 = safe_rows_start('parentid, count(*) as num', 'txp_discuss', "1 group by parentid order by parentid");
 206  
 207              if ($rs2)
 208              {
 209                  while ($a = nextRow($rs2))
 210                  {
 211                      $pid = $a['parentid'];
 212                      $num = $a['num'];
 213  
 214                      $total_comments[$pid] = $num;
 215                  }
 216              }
 217  
 218              echo n.'<div id="'.$event.'_container" class="txp-container">';
 219              echo n.n.'<form name="longform" id="articles_form" class="multi_edit_form" method="post" action="index.php">'.
 220  
 221                  n.'<div class="txp-listtables">'.
 222                  n.startTable('', '', 'txp-list').
 223                  n.'<thead>'.
 224                  n.tr(
 225                      n.hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' title="'.gTxt('toggle_all_selected').'" class="multi-edit"').
 226                      n.column_head('ID', 'id', 'list', true, $switch_dir, $crit, $search_method, (('id' == $sort) ? "$dir " : '').'id actions').
 227                      column_head('title', 'title', 'list', true, $switch_dir, $crit, $search_method, (('title' == $sort) ? "$dir " : '').'title').
 228                      column_head('posted', 'posted', 'list', true, $switch_dir, $crit, $search_method, (('posted' == $sort) ? "$dir " : '').'date posted created').
 229                      column_head('article_modified', 'lastmod', 'list', true, $switch_dir, $crit, $search_method, (('lastmod' == $sort) ? "$dir " : '').'articles_detail date modified').
 230                      column_head('expires', 'expires', 'list', true, $switch_dir, $crit, $search_method, (('expires' == $sort) ? "$dir " : '').'articles_detail date expires').
 231                      column_head('section', 'section', 'list', true, $switch_dir, $crit, $search_method, (('section' == $sort) ? "$dir " : '').'section').
 232                      column_head('category1', 'category1', 'list', true, $switch_dir, $crit, $search_method, (('category1' == $sort) ? "$dir " : '').'articles_detail category category1').
 233                      column_head('category2', 'category2', 'list', true, $switch_dir, $crit, $search_method, (('category2' == $sort) ? "$dir " : '').'articles_detail category category2').
 234                      column_head('status', 'status', 'list', true, $switch_dir, $crit, $search_method, (('status' == $sort) ? "$dir " : '').'status').
 235                      ($show_authors ? column_head('author', 'author', 'list', true, $switch_dir, $crit, $search_method, (('author' == $sort) ? "$dir " : '').'author') : '').
 236                      column_head('comments', 'comments', 'list', true, $switch_dir, $crit, $search_method, (('comments' == $sort) ? "$dir " : '').'articles_detail comments')
 237                  ).
 238                  n.'</thead>';
 239  
 240              include_once txpath.'/publish/taghandlers.php';
 241  
 242              echo '<tbody>';
 243  
 244              $validator = new Validator();
 245  
 246              while ($a = nextRow($rs))
 247              {
 248                  extract($a);
 249  
 250                  if (empty($Title))
 251                  {
 252                      $Title = '<em>'.eLink('article', 'edit', 'ID', $ID, gTxt('untitled')).'</em>';
 253                  }
 254  
 255                  else
 256                  {
 257                      $Title = eLink('article', 'edit', 'ID', $ID, $Title);
 258                  }
 259  
 260                  // Valid section and categories?
 261                  $validator->setConstraints(array(new SectionConstraint($Section)));
 262                  $vs = $validator->validate() ? '' : ' error';
 263  
 264                  $validator->setConstraints(array(new CategoryConstraint($Category1, array('type' => 'article'))));
 265                  $vc[1] = $validator->validate() ? '' : ' error';
 266  
 267                  $validator->setConstraints(array(new CategoryConstraint($Category2, array('type' => 'article'))));
 268                  $vc[2] = $validator->validate() ? '' : ' error';
 269  
 270                  $Category1 = ($Category1) ? '<span title="'.txpspecialchars(fetch_category_title($Category1)).'">'.$Category1.'</span>' : '';
 271                  $Category2 = ($Category2) ? '<span title="'.txpspecialchars(fetch_category_title($Category2)).'">'.$Category2.'</span>' : '';
 272  
 273                  if ($Status != STATUS_LIVE and $Status != STATUS_STICKY)
 274                  {
 275                      $view_url = '?txpreview='.intval($ID).'.'.time();
 276                  }
 277                  else
 278                  {
 279                      $view_url = permlinkurl($a);
 280                  }
 281  
 282                  $Status = !empty($Status) ? $statuses[$Status] : '';
 283  
 284                  $comments = '(0)';
 285  
 286                  if (isset($total_comments[$ID]) and $total_comments[$ID] > 0)
 287                  {
 288                      $comments = href('('.$total_comments[$ID].')', 'index.php?event=discuss'.a.'step=list'.a.'search_method=parent'.a.'crit='.$ID, ' title="'.gTxt('manage').'"');
 289                  }
 290  
 291                  $comment_status = ($Annotate) ? gTxt('on') : gTxt('off');
 292  
 293                  if ($comments_disabled_after)
 294                  {
 295                      $lifespan = $comments_disabled_after * 86400;
 296                      $time_since = time() - $posted;
 297  
 298                      if ($time_since > $lifespan)
 299                      {
 300                          $comment_status = gTxt('expired');
 301                      }
 302                  }
 303  
 304                  $comments = n.'<span class="comments-status">'.$comment_status.'</span> <span class="comments-manage">'.$comments.'</span>';
 305  
 306                  echo n.n.tr(
 307  
 308                      n.td((
 309                          (  ($a['Status'] >= STATUS_LIVE and has_privs('article.edit.published'))
 310                          or ($a['Status'] >= STATUS_LIVE and $AuthorID == $txp_user
 311                                                   and has_privs('article.edit.own.published'))
 312                          or ($a['Status'] < STATUS_LIVE and has_privs('article.edit'))
 313                          or ($a['Status'] < STATUS_LIVE and $AuthorID == $txp_user and has_privs('article.edit.own'))
 314                          )
 315                          ? fInput('checkbox', 'selected[]', $ID, 'checkbox')
 316                          : '&#160;'
 317                      ), '', 'multi-edit').
 318  
 319                      n.td(eLink('article', 'edit', 'ID', $ID, $ID) .sp. '<span class="articles_detail">[<a href="'.$view_url.'">'.gTxt('view').'</a>]</span>', '', 'id').
 320  
 321                      td($Title, '', 'title').
 322  
 323                      td(
 324                          gTime($posted), '', ($posted < time() ? '' : 'unpublished ').'date posted created'
 325                      ).
 326  
 327                      td(
 328                          gTime($lastmod), '', "articles_detail date modified"
 329                      ).
 330  
 331                      td(
 332                          ($expires ? gTime($expires) : ''), '' ,'articles_detail date expires'
 333                      ).
 334  
 335                      td(
 336                          '<span title="'.txpspecialchars(fetch_section_title($Section)).'">'.$Section.'</span>'
 337                      , '', 'section'.$vs).
 338  
 339                      td($Category1, '', "articles_detail category category1".$vc[1]).
 340                      td($Category2, '', "articles_detail category category2".$vc[2]).
 341                      td('<a href="'.$view_url.'" title="'.gTxt('view').'">'.$Status.'</a>', '', 'status').
 342  
 343                      ($show_authors ? td(
 344                          '<span title="'.txpspecialchars(get_author_name($AuthorID)).'">'.txpspecialchars($AuthorID).'</span>'
 345                          , '', 'author'
 346                      ) : '').
 347  
 348                      td($comments, '', "articles_detail comments")
 349                  );
 350              }
 351  
 352              echo '</tbody>',
 353                  n, endTable(),
 354                  n, '</div>',
 355                  n, list_multiedit_form($page, $sort, $dir, $crit, $search_method),
 356                  n, tInput(),
 357                  n, '</form>',
 358                  n, graf(
 359                      toggle_box('articles_detail'),
 360                      ' class="detail-toggle"'
 361                  ),
 362                  n, '<div id="'.$event.'_navigation" class="txp-navigation">',
 363                  n, nav_form('list', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit),
 364                  n, pageby_form('list', $article_list_pageby),
 365                  n, '</div>',
 366                  n, '</div>';
 367          }
 368      }
 369  
 370  // -------------------------------------------------------------
 371  	function list_change_pageby()
 372      {
 373          event_change_pageby('article');
 374          list_list();
 375      }
 376  
 377  // -------------------------------------------------------------
 378  
 379  	function list_search_form($crit, $method)
 380      {
 381          $methods =    array(
 382              'id'                 => gTxt('ID'),
 383              'title_body_excerpt' => gTxt('title_body_excerpt'),
 384              'section'            => gTxt('section'),
 385              'categories'         => gTxt('categories'),
 386              'keywords'           => gTxt('keywords'),
 387              'status'             => gTxt('status'),
 388              'author'             => gTxt('author'),
 389              'article_image'      => gTxt('article_image'),
 390              'posted'             => gTxt('posted'),
 391              'lastmod'            => gTxt('article_modified')
 392          );
 393  
 394          return search_form('list', 'list', $crit, $methods, $method, 'title_body_excerpt');
 395      }
 396  
 397  // -------------------------------------------------------------
 398  
 399  	function list_multiedit_form($page, $sort, $dir, $crit, $search_method)
 400      {
 401          global $statuses, $all_cats, $all_authors, $all_sections;
 402  
 403          if ($all_cats) {
 404              $category1 = treeSelectInput('Category1', $all_cats, '');
 405              $category2 = treeSelectInput('Category2', $all_cats, '');
 406          }
 407          else
 408          {
 409              $category1 = $category2 = '';
 410          }
 411  
 412          $sections = $all_sections ? selectInput('Section', $all_sections, '', true) : '';
 413          $comments = onoffRadio('Annotate', get_pref('comments_on_default'));
 414          $status = selectInput('Status', $statuses, '', true);
 415          $authors = $all_authors ? selectInput('AuthorID', $all_authors, '', true) : '';
 416  
 417          $methods = array(
 418              'changesection'   => array('label' => gTxt('changesection'), 'html' => $sections),
 419              'changecategory1' => array('label' => gTxt('changecategory1'), 'html' => $category1),
 420              'changecategory2' => array('label' => gTxt('changecategory2'), 'html' => $category2),
 421              'changestatus'    => array('label' => gTxt('changestatus'), 'html' => $status),
 422              'changecomments'  => array('label' => gTxt('changecomments'), 'html' => $comments),
 423              'changeauthor'    => array('label' => gTxt('changeauthor'), 'html' => $authors),
 424              'delete'          => gTxt('delete'),
 425          );
 426  
 427          if (!$all_cats)
 428          {
 429              unset($methods['changecategory1'], $methods['changecategory2']);
 430          }
 431  
 432          if (has_single_author('textpattern', 'AuthorID'))
 433          {
 434              unset($methods['changeauthor']);
 435          }
 436  
 437          if(!has_privs('article.delete.own') && !has_privs('article.delete'))
 438          {
 439              unset($methods['delete']);
 440          }
 441  
 442          return multi_edit($methods, 'list', 'list_multi_edit', $page, $sort, $dir, $crit, $search_method);
 443      }
 444  
 445  // -------------------------------------------------------------
 446  
 447  	function list_multi_edit()
 448      {
 449          global $txp_user, $statuses, $all_cats, $all_authors, $all_sections;
 450  
 451          // Empty entry to permit clearing the categories
 452          $categories = array('');
 453  
 454          foreach ($all_cats as $row) {
 455              $categories[] = $row['name'];
 456          }
 457  
 458          $selected = ps('selected');
 459  
 460          if (!$selected or !is_array($selected))
 461          {
 462              return list_list();
 463          }
 464  
 465          $selected = array_map('assert_int', $selected);
 466          $method   = ps('edit_method');
 467          $changed  = false;
 468          $ids      = array();
 469          $key      = '';
 470  
 471          if ($method == 'delete')
 472          {
 473              if (!has_privs('article.delete'))
 474              {
 475                  $allowed = array();
 476  
 477                  if (has_privs('article.delete.own'))
 478                  {
 479                      $allowed = safe_column_num('ID', 'textpattern', 'ID in('.join(',',$selected).') and AuthorID=\''.doSlash($txp_user).'\'');
 480                  }
 481  
 482                  $selected = $allowed;
 483              }
 484  
 485              foreach ($selected as $id)
 486              {
 487                  if (safe_delete('textpattern', "ID = $id"))
 488                  {
 489                      $ids[] = $id;
 490                  }
 491              }
 492  
 493              $changed = join(', ', $ids);
 494  
 495              if ($changed)
 496              {
 497                  safe_update('txp_discuss', "visible = ".MODERATE, "parentid in($changed)");
 498                  callback_event('articles_deleted', '', 0, $ids);
 499              }
 500          }
 501  
 502          else
 503          {
 504              $selected = safe_rows('ID, AuthorID, Status', 'textpattern',
 505                                        'ID in ('. implode(',',$selected) .')');
 506  
 507              $allowed = array();
 508              foreach ($selected as $item)
 509              {
 510                  if ( ($item['Status'] >= STATUS_LIVE and has_privs('article.edit.published'))
 511                    or ($item['Status'] >= STATUS_LIVE and $item['AuthorID'] == $txp_user and has_privs('article.edit.own.published'))
 512                    or ($item['Status'] < STATUS_LIVE and has_privs('article.edit'))
 513                    or ($item['Status'] < STATUS_LIVE and $item['AuthorID'] == $txp_user and has_privs('article.edit.own')))
 514                  {
 515                      $allowed[] = $item['ID'];
 516                  }
 517              }
 518  
 519              $selected = $allowed;
 520              unset($allowed);
 521  
 522              switch ($method)
 523              {
 524                  // change author
 525                  case 'changeauthor':
 526                      $val = has_privs('article.edit') ? ps('AuthorID') : '';
 527                      if (in_array($val, $all_authors))
 528                      {
 529                          $key = 'AuthorID';
 530                      }
 531                  break;
 532  
 533                  // change category1
 534                  case 'changecategory1':
 535                      $val = ps('Category1');
 536                      if (in_array($val, $categories))
 537                      {
 538                          $key = 'Category1';
 539                      }
 540                  break;
 541  
 542                  // change category2
 543                  case 'changecategory2':
 544                      $val = ps('Category2');
 545                      if (in_array($val, $categories))
 546                      {
 547                          $key = 'Category2';
 548                      }
 549                  break;
 550  
 551                  // change comments
 552                  case 'changecomments':
 553                      $key = 'Annotate';
 554                      $val = (int) ps('Annotate');
 555                  break;
 556  
 557                  // change section
 558                  case 'changesection':
 559                      $val = ps('Section');
 560                      if (in_array($val, $all_sections))
 561                      {
 562                          $key = 'Section';
 563                      }
 564                  break;
 565  
 566                  // change status
 567                  case 'changestatus':
 568                      $val = (int) ps('Status');
 569                      if (array_key_exists($val, $statuses))
 570                      {
 571                          $key = 'Status';
 572                      }
 573  
 574                      if (!has_privs('article.publish') && $val >= STATUS_LIVE)
 575                      {
 576                          $val = STATUS_PENDING;
 577                      }
 578                  break;
 579  
 580                  default:
 581                      $key = '';
 582                      $val = '';
 583                  break;
 584              }
 585  
 586              if ($selected and $key)
 587              {
 588                  foreach ($selected as $id)
 589                  {
 590                      if (safe_update('textpattern', "$key = '".doSlash($val)."'", "ID = $id"))
 591                      {
 592                          $ids[] = $id;
 593                      }
 594                  }
 595  
 596                  $changed = join(', ', $ids);
 597              }
 598          }
 599  
 600          if ($changed)
 601          {
 602              update_lastmod();
 603  
 604              return list_list(
 605                  messenger('article', $changed, (($method == 'delete') ? 'deleted' : 'modified' ))
 606              );
 607          }
 608  
 609          return list_list();
 610      }
 611  
 612  ?>

title

Description

title

Description

title

Description

title

title

Body