Textpattern PHP Cross Reference Content Management Systems

Source: /textpattern/include/txp_image.php - 1054 lines - 34985 bytes - Summary - Text - Print

Description: Images panel.

   1  <?php
   2  
   3  /*
   4   * Textpattern Content Management System
   5   * http://textpattern.com
   6   *
   7   * Copyright (C) 2005 Dean Allen
   8   * Copyright (C) 2016 The Textpattern Development Team
   9   *
  10   * This file is part of Textpattern.
  11   *
  12   * Textpattern is free software; you can redistribute it and/or
  13   * modify it under the terms of the GNU General Public License
  14   * as published by the Free Software Foundation, version 2.
  15   *
  16   * Textpattern is distributed in the hope that it will be useful,
  17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19   * GNU General Public License for more details.
  20   *
  21   * You should have received a copy of the GNU General Public License
  22   * along with Textpattern. If not, see <http://www.gnu.org/licenses/>.
  23   */
  24  
  25  /**
  26   * Images panel.
  27   *
  28   * @package Admin\Image
  29   */
  30  
  31  use Textpattern\Validator\CategoryConstraint;
  32  use Textpattern\Validator\Validator;
  33  use Textpattern\Search\Filter;
  34  
  35  if (!defined('txpinterface')) {
  36      die('txpinterface is undefined.');
  37  }
  38  
  39  global $extensions;
  40  $extensions = get_safe_image_types();
  41  
  42  include txpath.'/lib/class.thumb.php';
  43  
  44  if ($event == 'image') {
  45      require_privs('image');
  46  
  47      global $all_image_cats, $all_image_authors;
  48      $all_image_cats = getTree('root', 'image');
  49      $all_image_authors = the_privileged('image.edit.own');
  50  
  51      $available_steps = array(
  52          'image_list'          => false,
  53          'image_edit'          => false,
  54          'image_insert'        => true,
  55          'image_replace'       => true,
  56          'image_save'          => true,
  57          'thumbnail_insert'    => true,
  58          'image_change_pageby' => true,
  59          'thumbnail_create'    => true,
  60          'thumbnail_delete'    => true,
  61          'image_multi_edit'    => true,
  62      );
  63  
  64      if ($step && bouncer($step, $available_steps)) {
  65          $step();
  66      } else {
  67          image_list();
  68      }
  69  }
  70  
  71  /**
  72   * The main panel listing all images.
  73   *
  74   * @param string|array $message The activity message
  75   */
  76  
  77  function image_list($message = '')
  78  {
  79      global $txpcfg, $extensions, $img_dir, $file_max_upload_size, $image_list_pageby, $txp_user, $event;
  80  
  81      pagetop(gTxt('tab_image'), $message);
  82  
  83      extract($txpcfg);
  84      extract(gpsa(array(
  85          'page',
  86          'sort',
  87          'dir',
  88          'crit',
  89          'search_method',
  90      )));
  91  
  92      if ($sort === '') {
  93          $sort = get_pref('image_sort_column', 'id');
  94      } else {
  95          if (!in_array($sort, array('name', 'thumbnail', 'category', 'date', 'author'))) {
  96              $sort = 'id';
  97          }
  98  
  99          set_pref('image_sort_column', $sort, 'image', 2, '', 0, PREF_PRIVATE);
 100      }
 101  
 102      if ($dir === '') {
 103          $dir = get_pref('image_sort_dir', 'desc');
 104      } else {
 105          $dir = ($dir == 'asc') ? "asc" : "desc";
 106          set_pref('image_sort_dir', $dir, 'image', 2, '', 0, PREF_PRIVATE);
 107      }
 108  
 109      switch ($sort) {
 110          case 'name':
 111              $sort_sql = "txp_image.name $dir";
 112              break;
 113          case 'thumbnail':
 114              $sort_sql = "txp_image.thumbnail $dir, txp_image.id ASC";
 115              break;
 116          case 'category':
 117              $sort_sql = "txp_category.title $dir, txp_image.id ASC";
 118              break;
 119          case 'date':
 120              $sort_sql = "txp_image.date $dir, txp_image.id ASC";
 121              break;
 122          case 'author':
 123              $sort_sql = "txp_users.RealName $dir, txp_image.id ASC";
 124              break;
 125          default:
 126              $sort = 'id';
 127              $sort_sql = "txp_image.id $dir";
 128              break;
 129      }
 130  
 131      $switch_dir = ($dir == 'desc') ? 'asc' : 'desc';
 132  
 133      $search = new Filter($event,
 134          array(
 135              'id' => array(
 136                  'column' => 'txp_image.id',
 137                  'label'  => gTxt('ID'),
 138                  'type'   => 'integer',
 139              ),
 140              'name' => array(
 141                  'column' => 'txp_image.name',
 142                  'label'  => gTxt('name'),
 143              ),
 144              'alt' => array(
 145                  'column' => 'txp_image.alt',
 146                  'label'  => gTxt('alt_text'),
 147              ),
 148              'caption' => array(
 149                  'column' => 'txp_image.caption',
 150                  'label'  => gTxt('caption'),
 151              ),
 152              'category' => array(
 153                  'column' => array('txp_image.category', 'txp_category.title'),
 154                  'label'  => gTxt('image_category'),
 155              ),
 156              'ext' => array(
 157                  'column' => 'txp_image.ext',
 158                  'label'  => gTxt('extension'),
 159              ),
 160              'author' => array(
 161                  'column' => array('txp_image.author', 'txp_users.RealName'),
 162                  'label'  => gTxt('author'),
 163              ),
 164              'thumbnail' => array(
 165                  'column' => array('txp_image.thumbnail'),
 166                  'label'  => gTxt('thumbnail'),
 167                  'type'   => 'boolean',
 168              ),
 169          )
 170      );
 171  
 172      $alias_yes = '1, Yes';
 173      $alias_no = '0, No';
 174      $search->setAliases('thumbnail', array($alias_no, $alias_yes));
 175  
 176      list($criteria, $crit, $search_method) = $search->getFilter(array(
 177              'id' => array('can_list' => true),
 178          ));
 179  
 180      $search_render_options = array(
 181          'placeholder' => 'search_images',
 182      );
 183  
 184      $sql_from =
 185          safe_pfx_j('txp_image')."
 186          LEFT JOIN ".safe_pfx_j('txp_category')." ON txp_category.name = txp_image.category AND txp_category.type = 'image'
 187          LEFT JOIN ".safe_pfx_j('txp_users')." ON txp_users.name = txp_image.author";
 188  
 189      if ($criteria === 1) {
 190          $total = getCount('txp_image', $criteria);
 191      } else {
 192          $total = getThing("SELECT COUNT(*) FROM $sql_from WHERE $criteria");
 193      }
 194  
 195      echo n.'<div class="txp-layout">'.
 196          n.tag(
 197              hed(gTxt('tab_image'), 1, array('class' => 'txp-heading')),
 198              'div', array('class' => 'txp-layout-4col-alt')
 199          );
 200  
 201      $searchBlock =
 202          n.tag(
 203              $search->renderForm('image_list', $search_render_options),
 204              'div', array(
 205                  'class' => 'txp-layout-4col-3span',
 206                  'id'    => $event.'_control',
 207              )
 208          );
 209  
 210      $createBlock = array();
 211  
 212      if (!is_dir(IMPATH) or !is_writeable(IMPATH)) {
 213          $createBlock[] =
 214              graf(
 215                  span(null, array('class' => 'ui-icon ui-icon-alert')).' '.
 216                  gTxt('img_dir_not_writeable', array('{imgdir}' => IMPATH)),
 217                  array('class' => 'alert-block warning')
 218              );
 219      } elseif (has_privs('image.edit.own')) {
 220          $createBlock[] =
 221              n.tag(
 222                  n.upload_form('upload_image', 'upload_image', 'image_insert', 'image', '', $file_max_upload_size, '', '', ''),
 223                  'div', array('class' => 'txp-control-panel')
 224              );
 225      }
 226  
 227      $contentBlockStart = n.tag_start('div', array(
 228              'class' => 'txp-layout-1col',
 229              'id'    => $event.'_container',
 230          ));
 231  
 232      $createBlock = implode(n, $createBlock);
 233  
 234      if ($total < 1) {
 235          if ($criteria != 1) {
 236              echo $searchBlock.
 237                  $contentBlockStart.
 238                  $createBlock.
 239                  graf(
 240                      span(null, array('class' => 'ui-icon ui-icon-info')).' '.
 241                      gTxt('no_results_found'),
 242                      array('class' => 'alert-block information')
 243                  );
 244          } else {
 245              echo $contentBlockStart.
 246                  $createBlock.
 247                  graf(
 248                      span(null, array('class' => 'ui-icon ui-icon-info')).' '.
 249                      gTxt('no_images_recorded'),
 250                      array('class' => 'alert-block information')
 251                  );
 252          }
 253  
 254          echo n.tag_end('div'). // End of .txp-layout-1col.
 255              n.'</div>'; // End of .txp-layout.
 256  
 257          return;
 258      }
 259  
 260      $limit = max($image_list_pageby, 15);
 261  
 262      list($page, $offset, $numPages) = pager($total, $limit, $page);
 263  
 264      echo $searchBlock.$contentBlockStart.$createBlock;
 265  
 266      $rs = safe_query(
 267          "SELECT
 268              txp_image.id,
 269              txp_image.name,
 270              txp_image.category,
 271              txp_image.ext,
 272              txp_image.w,
 273              txp_image.h,
 274              txp_image.alt,
 275              txp_image.caption,
 276              UNIX_TIMESTAMP(txp_image.date) AS uDate,
 277              txp_image.author,
 278              txp_image.thumbnail,
 279              txp_image.thumb_w,
 280              txp_image.thumb_h,
 281              txp_users.RealName AS realname,
 282              txp_category.Title AS category_title
 283          FROM $sql_from WHERE $criteria ORDER BY $sort_sql LIMIT $offset, $limit"
 284      );
 285  
 286      echo pluggable_ui('image_ui', 'extend_controls', '', $rs);
 287  
 288      if ($rs && numRows($rs)) {
 289          $show_authors = !has_single_author('txp_image');
 290  
 291          echo n.tag(
 292                  toggle_box('images_detail'), 'div', array('class' => 'txp-list-options')).
 293              n.tag_start('form', array(
 294                  'class'  => 'multi_edit_form',
 295                  'id'     => 'images_form',
 296                  'name'   => 'longform',
 297                  'method' => 'post',
 298                  'action' => 'index.php',
 299              )).
 300              n.tag_start('div', array('class' => 'txp-listtables')).
 301              n.tag_start('table', array('class' => 'txp-list')).
 302              n.tag_start('thead').
 303              tr(
 304                  hCell(
 305                      fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'),
 306                          '', ' class="txp-list-col-multi-edit" scope="col" title="'.gTxt('toggle_all_selected').'"'
 307                  ).
 308                  column_head(
 309                      'ID', 'id', 'image', true, $switch_dir, $crit, $search_method,
 310                          (('id' == $sort) ? "$dir " : '').'txp-list-col-id'
 311                  ).
 312                  column_head(
 313                      'name', 'name', 'image', true, $switch_dir, $crit, $search_method,
 314                          (('name' == $sort) ? "$dir " : '').'txp-list-col-name'
 315                  ).
 316                  column_head(
 317                      'date', 'date', 'image', true, $switch_dir, $crit, $search_method,
 318                          (('date' == $sort) ? "$dir " : '').'txp-list-col-created date images_detail'
 319                  ).
 320                  column_head(
 321                      'thumbnail', 'thumbnail', 'image', true, $switch_dir, $crit, $search_method,
 322                          (('thumbnail' == $sort) ? "$dir " : '').'txp-list-col-thumbnail'
 323                  ).
 324                  hCell(
 325                      gTxt('tags'), '', ' class="txp-list-col-tag-build images_detail" scope="col"'
 326                  ).
 327                  column_head(
 328                      'image_category', 'category', 'image', true, $switch_dir, $crit, $search_method,
 329                          (('category' == $sort) ? "$dir " : '').'txp-list-col-category category'
 330                  ).
 331                  (
 332                      $show_authors
 333                      ? column_head('author', 'author', 'image', true, $switch_dir, $crit, $search_method,
 334                          (('author' == $sort) ? "$dir " : '').'txp-list-col-author name')
 335                      : ''
 336                  )
 337              ).
 338              n.tag_end('thead').
 339              n.tag_start('tbody');
 340  
 341          $validator = new Validator();
 342  
 343          while ($a = nextRow($rs)) {
 344              extract($a);
 345  
 346              $edit_url = array(
 347                  'event'         => 'image',
 348                  'step'          => 'image_edit',
 349                  'id'            => $id,
 350                  'sort'          => $sort,
 351                  'dir'           => $dir,
 352                  'page'          => $page,
 353                  'search_method' => $search_method,
 354                  'crit'          => $crit,
 355              );
 356  
 357              $name = empty($name) ? gTxt('unnamed') : txpspecialchars($name);
 358  
 359              if ($thumbnail) {
 360                  if ($ext != '.swf') {
 361                      $thumbnail = '<img class="content-image" src="'.imagesrcurl($id, $ext, true)."?$uDate".'" alt="" '.
 362                          "title='$id$ext ($w &#215; $h)'".
 363                          ($thumb_w ? " width='$thumb_w' height='$thumb_h'" : '').' />';
 364                      $thumbexists = 1;
 365                  } else {
 366                      $thumbnail = '';
 367                      $thumbexists = '';
 368                  }
 369              } else {
 370                  $thumbnail = gTxt('no');
 371                  $thumbexists = '';
 372              }
 373  
 374              if ($ext != '.swf') {
 375                  $tagName = 'image';
 376                  $tag_url = array(
 377                      'id'      => $id,
 378                      'ext'     => $ext,
 379                      'w'       => $w,
 380                      'h'       => $h,
 381                      'alt'     => urlencode($alt),
 382                      'caption' => urlencode($caption),
 383                      'step'    => 'build',
 384                  );
 385  
 386                  $tagbuilder = popTag($tagName, 'Textile', array('type' => 'textile') + $tag_url).
 387                      sp.span('&#124;', array('role' => 'separator')).
 388                      sp.popTag($tagName, 'Textpattern', array('type' => 'textpattern') + $tag_url).
 389                      sp.span('&#124;', array('role' => 'separator')).
 390                      sp.popTag($tagName, 'HTML', array('type' => 'html') + $tag_url);
 391              } else {
 392                  $tagbuilder = sp;
 393              }
 394  
 395              $validator->setConstraints(array(new CategoryConstraint($category, array('type' => 'image'))));
 396              $vc = $validator->validate() ? '' : ' error';
 397  
 398              if ($category) {
 399                  $category = span(txpspecialchars($category_title), array('title' => $category));
 400              }
 401  
 402              $can_edit = has_privs('image.edit') || ($author === $txp_user && has_privs('image.edit.own'));
 403  
 404              echo tr(
 405                  td(
 406                      $can_edit ? fInput('checkbox', 'selected[]', $id) : '&#160;', '', 'txp-list-col-multi-edit'
 407                  ).
 408                  hCell(
 409                      ($can_edit ? href($id, $edit_url, array('title' => gTxt('edit'))) : $id).
 410                      span(
 411                          sp.span('&#124;', array('role' => 'separator')).
 412                          sp.href(gTxt('view'), imagesrcurl($id, $ext)),
 413                          array('class' => 'txp-option-link images_detail')
 414                      ), '', array(
 415                          'class' => 'txp-list-col-id',
 416                          'scope' => 'row',
 417                      )
 418                  ).
 419                  td(
 420                      ($can_edit ? href($name, $edit_url, ' title="'.gTxt('edit').'"') : $name), '', 'txp-list-col-name'
 421                  ).
 422                  td(
 423                      gTime($uDate), '', 'txp-list-col-created date images_detail'
 424                  ).
 425                  td(
 426                      pluggable_ui('image_ui', 'thumbnail', ($can_edit ? href($thumbnail, $edit_url) : $thumbnail), $a), '', 'txp-list-col-thumbnail'.($thumbexists ? ' has-thumbnail' : '')
 427                  ).
 428                  td(
 429                      $tagbuilder, '', 'txp-list-col-tag-build images_detail'
 430                  ).
 431                  td(
 432                      $category, '', 'txp-list-col-category category'.$vc
 433                  ).
 434                  (
 435                      $show_authors
 436                      ? td(span(txpspecialchars($realname), array('title' => $author)), '', 'txp-list-col-author name')
 437                      : ''
 438                  )
 439              );
 440          }
 441  
 442          echo
 443              n.tag_end('tbody').
 444              n.tag_end('table').
 445              n.tag_end('div'). // End of .txp-listtables.
 446              image_multiedit_form($page, $sort, $dir, $crit, $search_method).
 447              tInput().
 448              n.tag_end('form').
 449              n.tag_start('div', array(
 450                  'class' => 'txp-navigation',
 451                  'id'    => $event.'_navigation',
 452              )).
 453              pageby_form('image', $image_list_pageby).
 454              nav_form('image', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit).
 455              n.tag_end('div');
 456      }
 457  
 458      echo n.tag_end('div'). // End of .txp-layout-1col.
 459          n.tag(
 460          null,
 461          'div', array(
 462              'class'      => 'txp-tagbuilder-content',
 463              'id'         => 'tagbuild_links',
 464              'aria-label' => gTxt('tagbuilder'),
 465              'title'      => gTxt('tagbuilder'),
 466          )).
 467          n.'</div>'; // End of .txp-layout.
 468  }
 469  
 470  // -------------------------------------------------------------
 471  
 472  function image_multiedit_form($page, $sort, $dir, $crit, $search_method)
 473  {
 474      global $all_image_cats, $all_image_authors;
 475  
 476      $categories = $all_image_cats ? treeSelectInput('category', $all_image_cats, '') : '';
 477      $authors = $all_image_authors ? selectInput('author', $all_image_authors, '', true) : '';
 478  
 479      $methods = array(
 480          'changecategory' => array('label' => gTxt('changecategory'), 'html' => $categories),
 481          'changeauthor'   => array('label' => gTxt('changeauthor'), 'html' => $authors),
 482          'delete'         => gTxt('delete'),
 483      );
 484  
 485      if (!$categories) {
 486          unset($methods['changecategory']);
 487      }
 488  
 489      if (has_single_author('txp_image') || !has_privs('image.edit')) {
 490          unset($methods['changeauthor']);
 491      }
 492  
 493      if (!has_privs('image.delete.own') && !has_privs('image.delete')) {
 494          unset($methods['delete']);
 495      }
 496  
 497      return multi_edit($methods, 'image', 'image_multi_edit', $page, $sort, $dir, $crit, $search_method);
 498  }
 499  
 500  // -------------------------------------------------------------
 501  
 502  function image_multi_edit()
 503  {
 504      global $txp_user, $all_image_cats, $all_image_authors;
 505  
 506      // Empty entry to permit clearing the category.
 507      $categories = array('');
 508  
 509      foreach ($all_image_cats as $row) {
 510          $categories[] = $row['name'];
 511      }
 512  
 513      $selected = ps('selected');
 514  
 515      if (!$selected or !is_array($selected)) {
 516          return image_list();
 517      }
 518  
 519      $selected = array_map('assert_int', $selected);
 520      $method = ps('edit_method');
 521      $changed = array();
 522      $key = '';
 523  
 524      switch ($method) {
 525          case 'delete':
 526              return image_delete($selected);
 527              break;
 528          case 'changecategory':
 529              $val = ps('category');
 530              if (in_array($val, $categories)) {
 531                  $key = 'category';
 532              }
 533              break;
 534          case 'changeauthor':
 535              $val = ps('author');
 536              if (has_privs('image.edit') && in_array($val, $all_image_authors)) {
 537                  $key = 'author';
 538              }
 539              break;
 540          default:
 541              $key = '';
 542              $val = '';
 543              break;
 544      }
 545  
 546      if (!has_privs('image.edit')) {
 547          if (has_privs('image.edit.own')) {
 548              $selected = safe_column("id", 'txp_image', "id IN (".join(',', $selected).") AND author = '".doSlash($txp_user)."'");
 549          } else {
 550              $selected = array();
 551          }
 552      }
 553  
 554      if ($selected and $key) {
 555          foreach ($selected as $id) {
 556              if (safe_update('txp_image', "$key = '".doSlash($val)."'", "id = $id")) {
 557                  $changed[] = $id;
 558              }
 559          }
 560      }
 561  
 562      if ($changed) {
 563          update_lastmod('image_updated', $changed);
 564  
 565          return image_list(gTxt('image_updated', array('{name}' => join(', ', $changed))));
 566      }
 567  
 568      return image_list();
 569  }
 570  
 571  /**
 572   * Renders and outputs the image editor panel.
 573   *
 574   * @param string|array $message The activity message
 575   * @param int          $id      The image ID
 576   */
 577  
 578  function image_edit($message = '', $id = '')
 579  {
 580      global $prefs, $file_max_upload_size, $txp_user, $event, $all_image_cats;
 581  
 582      if (!$id) {
 583          $id = gps('id');
 584      }
 585  
 586      $id = assert_int($id);
 587      $rs = safe_row("*, UNIX_TIMESTAMP(date) AS uDate", 'txp_image', "id = $id");
 588  
 589      if ($rs) {
 590          extract($rs);
 591  
 592          if (!has_privs('image.edit') && !($author === $txp_user && has_privs('image.edit.own'))) {
 593              image_list(gTxt('restricted_area'));
 594  
 595              return;
 596          }
 597  
 598          pagetop(gTxt('edit_image'), $message);
 599  
 600          extract(gpsa(array(
 601              'page',
 602              'sort',
 603              'dir',
 604              'crit',
 605              'search_method'
 606          )));
 607  
 608          if ($ext != '.swf') {
 609              $aspect = ($h == $w) ? ' square' : (($h > $w) ? ' portrait' : ' landscape');
 610              $img_info = $id.$ext.' ('.$w.' &#215; '.$h.')';
 611              $img = '<div class="fullsize-image"><img class="content-image" src="'.imagesrcurl($id, $ext)."?$uDate".'" alt="'.$img_info.'" title="'.$img_info.'" /></div>';
 612          } else {
 613              $img = $aspect = '';
 614          }
 615  
 616          if ($thumbnail and ($ext != '.swf')) {
 617              $thumb_info = $id.'t'.$ext.' ('.$thumb_w.' &#215; '.$thumb_h.')';
 618              $thumb = '<img class="content-image" src="'.imagesrcurl($id, $ext, true)."?$uDate".'" alt="'.$thumb_info.'" title="'.$thumb_info.'" />';
 619          } else {
 620              $thumb = '';
 621  
 622              if ($thumb_w == 0) {
 623                  $thumb_w = get_pref('thumb_w', 0);
 624              }
 625  
 626              if ($thumb_h == 0) {
 627                  $thumb_h = get_pref('thumb_h', 0);
 628              }
 629          }
 630  
 631          $imageBlock = array();
 632          $thumbBlock = array();
 633  
 634          $imageBlock[] = pluggable_ui(
 635                  'image_ui',
 636                  'image_edit',
 637                  upload_form('replace_image', 'replace_image_form', 'image_replace', 'image', $id, $file_max_upload_size, 'image-upload', ' image-replace'),
 638                  $rs
 639              );
 640  
 641          $imageBlock[] = pluggable_ui(
 642                  'image_ui',
 643                  'fullsize_image',
 644                  $img,
 645                  $rs
 646              );
 647  
 648          $thumbBlock[] = hed(gTxt('create_thumbnail').popHelp('create_thumbnail'), 3);
 649  
 650          $thumbBlock[] = pluggable_ui(
 651              'image_ui',
 652              'thumbnail_edit',
 653              upload_form('upload_thumbnail', 'upload_thumbnail', 'thumbnail_insert', 'image', $id, $file_max_upload_size, 'thumbnail-upload', ' thumbnail-upload'),
 654              $rs
 655          );
 656  
 657          $thumbBlock[] = (check_gd($ext))
 658              ? pluggable_ui(
 659                  'image_ui',
 660                  'thumbnail_create',
 661                  form(
 662                      graf(
 663                              n.'<label for="width">'.gTxt('thumb_width').'</label>'.
 664                              fInput('text', 'width', @$thumb_w, 'input-xsmall', '', '', INPUT_XSMALL, '', 'width').
 665                              n.'<label for="height">'.gTxt('thumb_height').'</label>'.
 666                              fInput('text', 'height', @$thumb_h, 'input-xsmall', '', '', INPUT_XSMALL, '', 'height').
 667                              n.'<label for="crop">'.gTxt('keep_square_pixels').'</label>'.
 668                              checkbox('crop', 1, @$prefs['thumb_crop'], '', 'crop').
 669                              fInput('submit', '', gTxt('create')), ' class="edit-alter-thumbnail"').
 670                      hInput('id', $id).
 671                      eInput('image').
 672                      sInput('thumbnail_create').
 673                      hInput('sort', $sort).
 674                      hInput('dir', $dir).
 675                      hInput('page', $page).
 676                      hInput('search_method', $search_method).
 677                      hInput('crit', $crit), '', '', 'post', '', '', 'thumbnail_alter_form'),
 678                  $rs
 679              )
 680              : '';
 681  
 682          $thumbBlock[] = pluggable_ui(
 683              'image_ui',
 684              'thumbnail_image',
 685              '<div class="thumbnail-image">'.
 686              (($thumbnail)
 687                  ? $thumb.n.dLink('image', 'thumbnail_delete', 'id', $id, '', '', '', '', array($page, $sort, $dir, $crit, $search_method))
 688                  : '').
 689              '</div>',
 690              $rs
 691          );
 692  
 693          echo n.'<div class="txp-layout">'.
 694              n.tag(
 695                  hed(gTxt('edit_image'), 1, array('class' => 'txp-heading')),
 696                  'div', array('class' => 'txp-layout-1col')
 697              ).
 698              n.tag(
 699                  form(
 700                      wrapGroup(
 701                          'image-details',
 702                          inputLabel(
 703                              'id',
 704                              $id,
 705                              'id', '', array('class' => 'txp-form-field edit-image-id')
 706                          ).
 707                          inputLabel(
 708                              'image_name',
 709                              fInput('text', 'name', $name, '', '', '', INPUT_REGULAR, '', 'image_name'),
 710                              'image_name', '', array('class' => 'txp-form-field edit-image-name')
 711                          ).
 712                          inputLabel(
 713                              'image_category',
 714                              event_category_popup('image', $category, 'image_category').
 715                              n.eLink('category', 'list', '', '', gTxt('edit'), '', '', '', 'txp-option-link'),
 716                              'image_category', '', array('class' => 'txp-form-field edit-image-category')
 717                          ).
 718                          inputLabel(
 719                              'image_alt_text',
 720                              fInput('text', 'alt', $alt, '', '', '', INPUT_REGULAR, '', 'image_alt_text'),
 721                              'alt_text', '', array('class' => 'txp-form-field edit-image-alt-text')
 722                          ).
 723                          inputLabel(
 724                              'image_caption',
 725                              '<textarea id="image_caption" name="caption" cols="'.INPUT_LARGE.'" rows="'.TEXTAREA_HEIGHT_SMALL.'">'.htmlspecialchars($caption, ENT_NOQUOTES).'</textarea>',
 726                              'caption', '', array('class' => 'txp-form-field txp-form-field-textarea edit-image-caption')
 727                          ).
 728                          pluggable_ui('image_ui', 'extend_detail_form', '', $rs).
 729                          hInput('id', $id).
 730                          eInput('image').
 731                          sInput('image_save').
 732                          hInput('sort', $sort).
 733                          hInput('dir', $dir).
 734                          hInput('page', $page).
 735                          hInput('search_method', $search_method).
 736                          hInput('crit', $crit),
 737                          'image_details'
 738                      ).
 739                      graf(fInput('submit', '', gTxt('save'), 'publish'), array('class' => 'txp-save')),
 740                      '', '', 'post', '', '', 'image_details_form'),
 741                  'div', array('class' => 'txp-layout-4col-alt')
 742              ).
 743              n.tag(
 744                  n.implode(n, $imageBlock).
 745                  n.'<hr />'.
 746                  n.tag(implode(n, $thumbBlock), 'section', array('class' => 'thumbnail-alter')),
 747                  'div', array('class' => 'txp-layout-4col-3span')
 748              ).
 749              n.'</div>'; // End of .txp-layout.
 750      }
 751  }
 752  
 753  // -------------------------------------------------------------
 754  
 755  function image_insert()
 756  {
 757      global $txpcfg, $extensions, $txp_user;
 758  
 759      if (!has_privs('image.edit.own')) {
 760          image_list(gTxt('restricted_area'));
 761  
 762          return;
 763      }
 764  
 765      extract($txpcfg);
 766  
 767      $meta = gpsa(array('caption', 'alt', 'category'));
 768  
 769      $img_result = image_data($_FILES['thefile'], $meta);
 770  
 771      if (is_array($img_result)) {
 772          list($message, $id) = $img_result;
 773  
 774          return image_edit($message, $id);
 775      } else {
 776          return image_list(array($img_result, E_ERROR));
 777      }
 778  }
 779  
 780  // -------------------------------------------------------------
 781  
 782  function image_replace()
 783  {
 784      global $txpcfg, $extensions, $txp_user;
 785      extract($txpcfg);
 786  
 787      $id = assert_int(gps('id'));
 788      $rs = safe_row("*", 'txp_image', "id = $id");
 789  
 790      if (!has_privs('image.edit') && !($rs['author'] === $txp_user && has_privs('image.edit.own'))) {
 791          image_list(gTxt('restricted_area'));
 792  
 793          return;
 794      }
 795  
 796      if ($rs) {
 797          $meta = array('category' => $rs['category'], 'caption' => $rs['caption'], 'alt' => $rs['alt']);
 798      } else {
 799          $meta = '';
 800      }
 801  
 802      $img_result = image_data($_FILES['thefile'], $meta, $id);
 803  
 804      if (is_array($img_result)) {
 805          list($message, $id) = $img_result;
 806  
 807          return image_edit($message, $id);
 808      } else {
 809          return image_edit(array($img_result, E_ERROR), $id);
 810      }
 811  }
 812  
 813  // -------------------------------------------------------------
 814  
 815  function thumbnail_insert()
 816  {
 817      global $txpcfg, $extensions, $txp_user, $img_dir, $path_to_site;
 818      extract($txpcfg);
 819      $id = assert_int(gps('id'));
 820      $author = fetch('author', 'txp_image', 'id', $id);
 821  
 822      if (!has_privs('image.edit') && !($author === $txp_user && has_privs('image.edit.own'))) {
 823          image_list(gTxt('restricted_area'));
 824  
 825          return;
 826      }
 827  
 828      $file = $_FILES['thefile']['tmp_name'];
 829      $name = $_FILES['thefile']['name'];
 830      $file = get_uploaded_file($file);
 831  
 832      if (empty($file)) {
 833          image_edit(array(upload_get_errormsg(UPLOAD_ERR_NO_FILE), E_ERROR), $id);
 834  
 835          return;
 836      }
 837  
 838      list($w, $h, $extension) = getimagesize($file);
 839  
 840      if (($file !== false) && @$extensions[$extension]) {
 841          $ext = $extensions[$extension];
 842          $newpath = IMPATH.$id.'t'.$ext;
 843  
 844          if (shift_uploaded_file($file, $newpath) == false) {
 845              image_edit(array($newpath.sp.gTxt('upload_dir_perms'), E_ERROR), $id);
 846          } else {
 847              chmod($newpath, 0644);
 848              safe_update('txp_image', "thumbnail = 1, thumb_w = $w, thumb_h = $h, date = NOW()", "id = $id");
 849  
 850              $message = gTxt('image_uploaded', array('{name}' => $name));
 851              update_lastmod('thumbnail_created', compact('id', 'w', 'h'));
 852  
 853              image_edit($message, $id);
 854          }
 855      } else {
 856          if ($file === false) {
 857              image_edit(array(upload_get_errormsg($_FILES['thefile']['error']), E_ERROR), $id);
 858          } else {
 859              image_edit(array(gTxt('only_graphic_files_allowed'), E_ERROR), $id);
 860          }
 861      }
 862  }
 863  
 864  // -------------------------------------------------------------
 865  
 866  function image_save()
 867  {
 868      global $txp_user;
 869  
 870      $varray = array_map('assert_string', gpsa(array('id', 'name', 'category', 'caption', 'alt')));
 871      extract(doSlash($varray));
 872      $id = $varray['id'] = assert_int($id);
 873      $author = fetch('author', 'txp_image', 'id', $id);
 874  
 875      if (!has_privs('image.edit') && !($author === $txp_user && has_privs('image.edit.own'))) {
 876          image_list(gTxt('restricted_area'));
 877  
 878          return;
 879      }
 880  
 881      $constraints = array(
 882          'category' => new CategoryConstraint(gps('category'), array('type' => 'image')),
 883      );
 884      callback_event_ref('image_ui', 'validate_save', 0, $varray, $constraints);
 885      $validator = new Validator($constraints);
 886  
 887      if ($validator->validate() && safe_update(
 888          'txp_image',
 889          "name    = '$name',
 890          category = '$category',
 891          alt      = '$alt',
 892          caption  = '$caption'",
 893          "id = $id"
 894      )) {
 895          $message = gTxt('image_updated', array('{name}' => doStrip($name)));
 896          update_lastmod('image_saved', compact('id', 'name', 'category', 'alt', 'caption'));
 897      } else {
 898          $message = array(gTxt('image_save_failed'), E_ERROR);
 899      }
 900  
 901      image_list($message);
 902  }
 903  
 904  // -------------------------------------------------------------
 905  
 906  function image_delete($ids = array())
 907  {
 908      global $txp_user, $event;
 909  
 910      $ids = $ids ? array_map('assert_int', $ids) : array(assert_int(ps('id')));
 911      $message = '';
 912  
 913      if (!has_privs('image.delete')) {
 914          if (has_privs('image.delete.own')) {
 915              $ids = safe_column("id", 'txp_image', "id IN (".join(',', $ids).") AND author = '".doSlash($txp_user)."'");
 916          } else {
 917              $ids = array();
 918          }
 919      }
 920  
 921      if (!empty($ids)) {
 922          $fail = array();
 923          $rs   = safe_rows_start("id, ext", 'txp_image', "id IN (".join(',', $ids).")");
 924  
 925          if ($rs) {
 926              while ($a = nextRow($rs)) {
 927                  extract($a);
 928  
 929                  // Notify plugins of pending deletion, pass image's $id.
 930                  callback_event('image_deleted', $event, false, $id);
 931  
 932                  $rsd = safe_delete('txp_image', "id = $id");
 933                  $ul = false;
 934  
 935                  if (is_file(IMPATH.$id.$ext)) {
 936                      $ul = unlink(IMPATH.$id.$ext);
 937                  }
 938  
 939                  if (is_file(IMPATH.$id.'t'.$ext)) {
 940                      $ult = unlink(IMPATH.$id.'t'.$ext);
 941                  }
 942  
 943                  if (!$rsd or !$ul) {
 944                      $fail[] = $id;
 945                  }
 946              }
 947  
 948              if ($fail) {
 949                  $message = array(gTxt('image_delete_failed', array('{name}' => join(', ', $fail))), E_ERROR);
 950              } else {
 951                  update_lastmod('image_deleted', compact('id'));
 952                  $message = gTxt('image_deleted', array('{name}' => join(', ', $ids)));
 953              }
 954          }
 955      }
 956  
 957      image_list($message);
 958  }
 959  
 960  // -------------------------------------------------------------
 961  
 962  function image_change_pageby()
 963  {
 964      event_change_pageby('image');
 965      image_list();
 966  }
 967  
 968  // -------------------------------------------------------------
 969  
 970  function thumbnail_create()
 971  {
 972      global $prefs, $txp_user;
 973  
 974      extract(doSlash(gpsa(array('id', 'width', 'height'))));
 975      $id = assert_int($id);
 976      $author = fetch('author', 'txp_image', 'id', $id);
 977  
 978      if (!has_privs('image.edit') && !($author === $txp_user && has_privs('image.edit.own'))) {
 979          image_list(gTxt('restricted_area'));
 980  
 981          return;
 982      }
 983  
 984      $width = (int) $width;
 985      $height = (int) $height;
 986  
 987      if ($width == 0) {
 988          $width = '';
 989      }
 990  
 991      if ($height == 0) {
 992          $height = '';
 993      }
 994  
 995      $crop = gps('crop');
 996  
 997      $prefs['thumb_w'] = $width;
 998      $prefs['thumb_h'] = $height;
 999      $prefs['thumb_crop'] = $crop;
1000  
1001      // Hidden prefs.
1002      set_pref('thumb_w', $width, 'image', 2);
1003      set_pref('thumb_h', $height, 'image', 2);
1004      set_pref('thumb_crop', $crop, 'image', 2);
1005  
1006      if ($width === '' && $height === '') {
1007          image_edit(array(gTxt('invalid_width_or_height'), E_ERROR), $id);
1008  
1009          return;
1010      }
1011  
1012      $t = new txp_thumb($id);
1013      $t->crop = ($crop == '1');
1014      $t->hint = '0';
1015      $t->width = $width;
1016      $t->height = $height;
1017  
1018      if ($t->write()) {
1019          $message = gTxt('thumbnail_saved', array('{id}' => $id));
1020          update_lastmod('thumbnail_created', compact('id', 'width', 'height', 'crop'));
1021  
1022          image_edit($message, $id);
1023      } else {
1024          $message = array(gTxt('thumbnail_not_saved', array('{id}' => $id)), E_ERROR);
1025  
1026          image_edit($message, $id);
1027      }
1028  }
1029  
1030  // -------------------------------------------------------------
1031  
1032  function thumbnail_delete()
1033  {
1034      global $txp_user;
1035  
1036      $id = assert_int(gps('id'));
1037      $author = fetch('author', 'txp_image', 'id', $id);
1038  
1039      if (!has_privs('image.edit') && !($author === $txp_user && has_privs('image.edit.own'))) {
1040          image_list(gTxt('restricted_area'));
1041  
1042          return;
1043      }
1044  
1045      $t = new txp_thumb($id);
1046  
1047      if ($t->delete()) {
1048          callback_event('thumbnail_deleted', '', false, $id);
1049          update_lastmod('thumbnail_deleted', compact('id'));
1050          image_edit(gTxt('thumbnail_deleted'), $id);
1051      } else {
1052          image_edit(array(gTxt('thumbnail_delete_failed'), E_ERROR), $id);
1053      }
1054  }

title

Description

title

Description

title

Description

title

title

Body