Your IP : 216.73.216.240


Current Path : /home/juvelize/www/administrator/components/com_joomgallery/models/
Upload File :
Current File : /home/juvelize/www/administrator/components/com_joomgallery/models/images.php

<?php
/****************************************************************************************\
**   JoomGallery 3                                                                      **
**   By: JoomGallery::ProjectTeam                                                       **
**   Copyright (C) 2008 - 2021  JoomGallery::ProjectTeam                                **
**   Based on: JoomGallery 1.0.0 by JoomGallery::ProjectTeam                            **
**   Released under GNU GPL Public License                                              **
**   License: http://www.gnu.org/copyleft/gpl.html or have a look                       **
**   at administrator/components/com_joomgallery/LICENSE.TXT                            **
\****************************************************************************************/

defined('_JEXEC') or die('Direct Access to this location is not allowed.');

/**
 * Images model
 *
 * @package JoomGallery
 * @since   1.5.5
 */
class JoomGalleryModelImages extends JoomGalleryModel
{
  /**
   * Images data array
   *
   * @var array
   */
  protected $_images;

  /**
   * Images number
   *
   * @var int
   */
  protected $_total = null;

  /**
   * Constructor
   *
   * @param   array An optional associative array of configuration settings
   * @return  void
   * @since   2.0
   */
  public function __construct($config = array())
  {
    parent::__construct($config);

    $this->filter_fields = array(
        'id', 'a.id',
        'imgtitle', 'a.imgtitle',
        'alias', 'a.alias',
        'catid', 'a.catid',
        'category', 'category_name',
        'published', 'a.published',
        'approved', 'a.approved',
        'featured', 'a.featured',
        'access', 'a.access', 'access_level',
        'owner', 'a.owner',
        'imgauthor', 'a.imgauthor',
        'imgdate', 'a.imgdate',
        'hits', 'a.hits',
        'downloads', 'a.downloads',
        'ordering', 'a.ordering',
        'state',
        'type'
        );
  }

  /**
   * Retrieves the images data
   *
   * @return  array   Array of objects containing the images data from the database
   * @since   1.5.5
   */
  public function getImages()
  {
    // Let's load the data if it doesn't already exist
    if(empty($this->_images))
    {
      $query = $this->_buildQuery();
      $this->_images = $this->_getList($query, $this->getStart(), $this->getState('list.limit'));
    }

    return $this->_images;
  }

  /**
   * Function to get the active filters
   *
   * @return  array  Associative array in the format: array('filter_published' => 0)
   *
   * @since   3.2.3
   */
  public function getActiveFilters()
  {
    $activeFilters = array();

    if (!empty($this->filter_fields))
    {
      foreach ($this->filter_fields as $filter)
      {
        $filterName = 'filter.' . $filter;

        if (property_exists($this->state, $filterName) && (!empty($this->state->{$filterName}) || is_numeric($this->state->{$filterName})))
        {
          $activeFilters[$filter] = $this->state->get($filterName);
        }
      }
    }

    return $activeFilters;
  }

  /**
   * Method to get the pagination object for the list.
   * This method uses 'getTotel', 'getStart' and the current
   * list limit of this view.
   *
   * @return  object  A pagination object
   * @since   2.0
   */
  public function getPagination()
  {
    return new JPagination($this->getTotal(), $this->getStart(), $this->getState('list.limit'));
  }

  /**
   * Method to get the total number of images
   *
   * @return  int     The total number of images
   * @since   1.5.5
   */
  public function getTotal()
  {
    // Let's load the total number of images if it doesn't already exist
    if(empty($this->_total))
    {
      $query = $this->_buildQuery();
      $this->_total = $this->_getListCount($query);
    }

    return $this->_total;
  }

  /**
   * Method to get the starting number of items for the data set.
   *
   * @return  int The starting number of items available in the data set.
   * @since   2.0
   */
  public function getStart()
  {
    $start = $this->getState('list.start');
    $limit = $this->getState('list.limit');
    $total = $this->getTotal();
    if($start > $total - $limit)
    {
      $start = max(0, (int)(ceil($total / $limit) - 1) * $limit);
    }

    return $start;
  }

  /**
   * Get the filter form
   *
   * @param   array    $data      data
   * @param   boolean  $loadData  load current data
   *
   * @return  JForm/false  the JForm object or false
   *
   * @since   3.2.3
   */
  public function getFilterForm($data = array(), $loadData = true)
  {
    return $this->loadForm(_JOOM_OPTION . '.filter_images', 'filter_images', array('control' => '', 'load_data' => $loadData));
  }

  /**
   * Method to get a form object.
   *
   * @param   string   $name     The name of the form.
   * @param   string   $source   The form source. Can be XML string if file flag is set to false.
   * @param   array    $options  Optional array of options for the form creation.
   * @param   boolean  $clear    Optional argument to force load a new form.
   * @param   string   $xpath    An optional xpath to search for the fields.
   *
   * @return  mixed  JForm object on success, False on error.
   *
   * @see     JForm
   * @since   3.2.3
   */
  protected function loadForm($name, $source = null, $options = array(), $clear = false, $xpath = false)
  {
    // Handle the optional arguments.
    $options['control'] = JArrayHelper::getValue($options, 'control', false);

    // Get the form.
    JForm::addFormPath(JPATH_COMPONENT . '/models/forms');
    JForm::addFieldPath(JPATH_COMPONENT . '/models/fields');

    try
    {
      $form = JForm::getInstance($name, $source, $options, false, $xpath);

      $form->setFieldAttribute('owner', 'useListboxMaxUserCount', $this->_config->get('jg_use_listbox_max_user_count'), 'filter');

      if(isset($options['load_data']) && $options['load_data'])
      {
        // Get the data for the form.
        $data = $this->loadFormData();
      }
      else
      {
        $data = array();
      }

      // Load the data into the form after the plugins have operated.
      $form->bind($data);
    }
    catch(Exception $e)
    {
      $this->setError($e->getMessage());

      return false;
    }

    return $form;
  }

  /**
   * Method to get the data that should be injected in the form.
   *
   * @return  mixed  The data for the form.
   *
   * @since  3.2.3
   */
  protected function loadFormData()
  {
    // Check the session for previously entered form data.
    $data = JFactory::getApplication()->getUserState('joom.images', new stdClass);

    // Pre-fill the list options
    if (!property_exists($data, 'list'))
    {
      $data->list = array(
          'direction' => $this->state->{'list.direction'},
          'limit'     => $this->state->{'list.limit'},
          'ordering'  => $this->state->{'list.ordering'},
          'start'     => $this->state->{'list.start'}
      );
    }

    return $data;
  }

  /**
   * Method to auto-populate the model state.
   *
   * Note. Calling getState in this method will result in recursion.
   *
   * @param   string  An optional ordering field.
   * @param   string  An optional direction (asc|desc).
   * @return  void
   * @since   2.0
   */
  protected function populateState($ordering = 'a.ordering', $direction = 'asc')
  {
    // Receive & set filters
    $filters = $this->getUserStateFromRequest('joom.images.filter', 'filter',
      array('search' => null, 'access' => '', 'state' => '', 'type' => '', 'category' => '', 'owner' => ''), 'array');

    if($filters)
    {
      foreach($filters as $name => $value)
      {
        // Special case for category filter to ensure that search tools will be hidden
        // , if 'None' has been selected in AJAX category selection box
        if($this->_config->get('jg_ajaxcategoryselection') && $name == 'category' && $value == 0)
        {
          $value = '';
          JFactory::getApplication()->setUserState('joom.images.filter.' . $name, $value);
        }

        $this->setState('filter.' . $name, $value);

        if($value)
        {
          $this->setState('filter.inuse', 1);
        }
      }
    }

    $limit = 0;

    // Receive & set list options
    $list = $this->getUserStateFromRequest('joom.images.list', 'list',
      array('ordering' => $ordering, 'direction' => $direction, 'fullordering' => $ordering . ' ' . $direction,
      'limit' => $this->_mainframe->getCfg('list_limit'), 'start' => 0), 'array');

    if($list)
    {
      foreach($list as $name => $value)
      {
        // Extra validations
        switch($name)
        {
          case 'fullordering':
            $orderingParts = explode(' ', $value);

            if(count($orderingParts) >= 2)
            {
              // Latest part will be considered the direction
              $fullDirection = end($orderingParts);

              if(in_array(strtoupper($fullDirection), array('ASC', 'DESC', '')))
              {
                $this->setState('list.direction', $fullDirection);
              }

              unset($orderingParts[count($orderingParts) - 1]);

              // The rest will be the ordering
              $fullOrdering = implode(' ', $orderingParts);

              if(in_array($fullOrdering, $this->filter_fields))
              {
                $this->setState('list.ordering', $fullOrdering);
              }
            }
            else
            {
              $this->setState('list.ordering', $ordering);
              $this->setState('list.direction', $direction);
            }
            break;
          case 'ordering':
            if(!in_array($value, $this->filter_fields))
            {
              $value = $ordering;
            }
            break;

          case 'direction':
            if(!in_array(strtoupper($value), array('ASC', 'DESC', '')))
            {
              $value = $direction;
            }
            break;

          case 'limit':
            $limit = $value;
            break;

            // Just to keep the default case
          default:
            $value = $value;
            break;
        }

        $this->setState('list.' . $name, $value);
      }

      $value      = $this->getUserStateFromRequest('joom.images.limitstart', 'limitstart', 0);
      $limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0);
      $this->setState('list.start', $limitstart);

    }
  }

  /**
   * Method to reorder images in categories
   *
   * @param    object  $table  Image table object
   * @return   array   $cats   Array of categories
   * @return   void
   * @since    3.1
   */
  protected function reorder($table, $cats)
  {
    if(!empty($cats))
    {
      $cats = array_unique($cats);

      // Execute reorder for each category
      foreach($cats as $cat)
      {
        $table->reorder('catid = '.(int) $cat);
      }
    }
  }

  /**
   * Method to delete one or more images
   *
   * @param   array $ids  IDs of images to delete
   * @return  int   Number of successfully deleted images, boolean false if an error occurred
   * @throws  RuntimeException
   * @since   1.5.5
   */
  public function delete($ids)
  {
    jimport('joomla.filesystem.file');

    $row = $this->getTable('joomgalleryimages');

    if(!count($ids))
    {
      throw new RuntimeException(JText::_('COM_JOOMGALLERY_COMMON_MSG_NO_IMAGES_SELECTED'));
    }

    $count         = 0;
    $catsToReorder = array();

    // Loop through selected images
    foreach($ids as $cid)
    {
      $row->load($cid);

      if(   !$this->_user->authorise('core.delete', _JOOM_OPTION.'.image.'.$cid)
        && (!$this->_user->authorise('joom.delete.own', _JOOM_OPTION.'.image.'.$cid) || !$row->owner || $row->owner != $this->_user->get('id')))
      {
        JLog::add(JText::plural('COM_JOOMGALLERY_IMGMAN_ERROR_DELETE_NOT_PERMITTED', 1), JLog::ERROR, 'jerror');

        continue;
      }

      // Database query to check if there are other images which this
      // thumbnail is assigned to and how many of them exist
      $query = $this->_db->getQuery(true)
             ->select('COUNT(id)')
             ->from(_JOOM_TABLE_IMAGES)
             ->where("imgthumbname  = '".$row->imgthumbname."'")
             ->where('id != '.$row->id)
             ->where('catid = '.$row->catid);

      $this->_db->setQuery($query);
      $thumb_count = $this->_db->loadResult();

      // Database query to check if there are other images which this
      // detail image is assigned to and how many of them exist
      $query->clear('where')
            ->where("imgfilename = '".$row->imgfilename."'")
            ->where('id != '.$row->id)
            ->where('catid = '.$row->catid);

      $this->_db->setQuery($query);
      $img_count = $this->_db->loadResult();

      // Delete the thumbnail if there are no other images
      // in the same category assigned to it
      if(!$thumb_count)
      {
        $thumb = $this->_ambit->getImg('thumb_path', $row);
        if(!JFile::delete($thumb))
        {
          // If thumbnail is not deletable raise an error message
          JLog::add(JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_COULD_NOT_DELETE_THUMB', $thumb), JLog::WARNING, 'jerror');
        }
      }

      // Delete the detail image if there are no other detail and
      // original images from the same category assigned to it
      if(!$img_count)
      {
        $img = $this->_ambit->getImg('img_path', $row);
        if(!JFile::delete($img))
        {
          // If detail image is not deletable raise an error message
          JLog::add(JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_COULD_NOT_DELETE_IMG', $img), JLog::WARNING, 'jerror');
        }

        // Original exists?
        $orig = $this->_ambit->getImg('orig_path', $row);
        if(JFile::exists($orig))
        {
          // Delete it
          if(!JFile::delete($orig))
          {
            // If original is not deletable raise an error message and abort
            JLog::add(JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_COULD_NOT_DELETE_ORIG', $orig), JLog::WARNING, 'jerror');
          }
        }
      }

      // Delete the corresponding database entries of the comments
      $query = $this->_db->getQuery(true)
            ->delete()
            ->from(_JOOM_TABLE_COMMENTS)
            ->where('cmtpic = '.$cid);

      $this->_db->setQuery($query);
      if(!$this->_db->query())
      {
        JLog::add(JText::sprintf('COM_JOOMGALLERY_MAIMAN_MSG_NOT_DELETE_COMMENTS', $cid), JLog::WARNING, 'jerror');
      }

      // Delete the corresponding database entries of the name tags
      $query = $this->_db->getQuery(true)
            ->delete()
            ->from(_JOOM_TABLE_NAMESHIELDS)
            ->where('npicid = '.$cid);

      $this->_db->setQuery($query);
      if(!$this->_db->query())
      {
        JLog::add(JText::sprintf('COM_JOOMGALLERY_MAIMAN_MSG_NOT_DELETE_NAMETAGS', $cid), JLog::WARNING, 'jerror');
      }

      // Delete the corresponding database entries of the votes
      $query = $this->_db->getQuery(true)
            ->delete()
            ->from(_JOOM_TABLE_VOTES)
            ->where('picid = '.$cid);

      $this->_db->setQuery($query);
      if(!$this->_db->query())
      {
        JLog::add(JText::sprintf('COM_JOOMGALLERY_MAIMAN_MSG_NOT_DELETE_VOTES', $cid), JLog::WARNING, 'jerror');
      }

      // Delete the database entry of the image
      if(!$row->delete())
      {
        $this->reorder($row, $catsToReorder);

        throw new RuntimeException(JText::sprintf('COM_JOOMGALLERY_MAIMAN_MSG_NOT_DELETE_IMAGE_DATA', $cid));
      }

      JPluginHelper::importPlugin('content');
      $this->_mainframe->triggerEvent('onContentAfterDelete', array(_JOOM_OPTION.'.image', $row));

      // Image successfully deleted
      $count++;

      // Remember the categories for reordering later
      $catsToReorder[] = $row->catid;
    }

    // Execute reorder for each category
    $this->reorder($row, $catsToReorder);

    return $count;
  }

  /**
   * Publishes/unpublishes or approves/rejects one or more images
   *
   * @param   array   $cid      An array of image IDs to work with
   * @param   int     $publish  1 for publishing and approving, 0 otherwise
   * @param   string  $task     'publish' for publishing/unpublishing, anything else otherwise
   * @return  int     The number of successfully edited images, boolean false if an error occured
   * @since   1.5.5
   */
  public function publish($cid, $publish = 1, $task = 'publish')
  {
    JArrayHelper::toInteger($cid);
    $publish = intval($publish);
    $count = count($cid);

    $row = $this->getTable('joomgalleryimages');

    $column = 'approved';
    if($task == 'publish')
    {
      $column = 'published';
    }
    if($task == 'feature')
    {
      $column = 'featured';
    }

    foreach($cid as $id)
    {
      $row->load($id);
      $row->$column = $publish;
      if(!$row->check())
      {
        $count--;
        continue;
      }

      if(!$row->store())
      {
        $count--;
        continue;
      }

      // If publishing or unpublishung wasn't successful, decrease the
      // counter of successfully published or unpublished images
      if($row->$column != $publish)
      {
        $count--;
      }
    }

    // Convert tasks and states
    switch($task)
    {
      case 'approve':
        if($publish == 1)
        {
          // approved
          $state = 4;
        }
        else
        {
          // not approved
          $state = 3;
        }
        break;

      case 'feature':
        if($publish == 1)
        {
          // featured
          $state = 6;
        }
        else
        {
          // not featured
          $state = 5;
        }
        break;

      default:
        // publish
        $state = $publish;
        break;
    }

    JPluginHelper::importPlugin('content');
    $this->_mainframe->triggerEvent('onContentChangeState', array(_JOOM_OPTION.'.image', $cid, $state));

    return $count;
  }

  /**
   * Sends message about reason of rejection to image owner
   *
   * @param   int     $id       The image ID
   * @param   string  $message  The message to send
   * @return  boolean True on success, false otherwise
   * @since   3.1
   */
  public function sendRejectionMessage($id, $message)
  {
    if(!$image = $this->_ambit->getImgObject($id))
    {
      return false;
    }

    if(!$image->owner)
    {
      return false;
    }

    require_once JPATH_COMPONENT_SITE.'/helpers/messenger.php';
    $messenger  = new JoomMessenger();

    $message    = array(
                        'from'      => $this->_user->get('id'),
                        'recipient' => $image->owner,
                        'subject'   => JText::sprintf('COM_JOOMGALLERY_IMGMAN_REJECT_IMAGE_SUBJECT', $image->imgtitle),
                        'body'      => $message,
                        'mode'      => 'rejectimg'
                      );

    return $messenger->send($message);
  }

  /**
   * Recreates thumbnails of the selected images.
   * If original image is existent, detail image will be recreated, too.
   *
   * @return  array   An array of result information (thumbnail number, detail image number, array with information which image types have been recreated)
   * @since   1.5.5
   */
  public function recreate()
  {
    jimport('joomla.filesystem.file');

    $cids         = $this->_mainframe->getUserStateFromRequest('joom.recreate.cids', 'cid', array(), 'array');
    $type         = $this->_mainframe->getUserStateFromRequest('joom.recreate.type', 'type', '', 'cmd');
    $thumb_count  = $this->_mainframe->getUserState('joom.recreate.thumbcount');
    $img_count    = $this->_mainframe->getUserState('joom.recreate.imgcount');
    $recreated    = $this->_mainframe->getUserState('joom.recreate.recreated');

    $row  = $this->getTable('joomgalleryimages');

    // Before first loop check for selected images
    if(is_null($thumb_count) && !count($cids))
    {
      $this->setError(JText::_('COM_JOOMGALLERY_COMMON_MSG_NO_IMAGES_SELECTED'));
      return array(false);
    }

    if(is_null($recreated))
    {
      $recreated = array();
    }

    require_once JPATH_COMPONENT.'/helpers/refresher.php';

    $refresher = new JoomRefresher(array('controller' => 'images', 'task' => 'recreate', 'remaining' => count($cids), 'start' => JRequest::getBool('cid')));

    $debugoutput = '';

    $angle = 0;

    // Loop through selected images
    foreach($cids as $key => $cid)
    {
      $row->load($cid);

      $orig   = $this->_ambit->getImg('orig_path', $row);
      $img    = $this->_ambit->getImg('img_path', $row);
      $thumb  = $this->_ambit->getImg('thumb_path', $row);

      // Check if there is an original image
      if(JFile::exists($orig))
      {
        $orig_existent = true;
      }
      else
      {
        // If not, use detail image to create thumbnail
        $orig_existent = false;
        if(JFile::exists($img))
        {
          $orig = $img;
        }
        else
        {
          JError::raiseWarning(100, JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_IMAGE_NOT_EXISTENT', $img));
          $this->_mainframe->setUserState('joom.recreate.cids', array());
          $this->_mainframe->setUserState('joom.recreate.imgcount', null);
          $this->_mainframe->setUserState('joom.recreate.thumbcount', null);
          $this->_mainframe->setUserState('joom.recreate.recreated', null);
          return false;
        }
      }

      // Recreate thumbnail
      if(!$type || $type == 'thumb')
      {
        // TODO: Move image into a trash instead of deleting immediately for possible rollback
        if(JFile::exists($thumb))
        {
          JFile::delete($thumb);
        }
        $return = JoomIMGtools::resizeImage($debugoutput,
                                            $orig,
                                            $thumb,
                                            $this->_config->get('jg_useforresizedirection'),
                                            $this->_config->get('jg_thumbwidth'),
                                            $this->_config->get('jg_thumbheight'),
                                            $this->_config->get('jg_thumbcreation'),
                                            $this->_config->get('jg_thumbquality'),
                                            $this->_config->get('jg_cropposition'),
                                            $angle,
                                            $this->_config->get('jg_thumbautorot'),
                                            false,
                                            false,
                                            true
                                           );

        if(!$return)
        {
          JError::raiseWarning(100, JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_COULD_NOT_CREATE_THUMB', $thumb));
          $this->_mainframe->setUserState('joom.recreate.cids', array());
          $this->_mainframe->setUserState('joom.recreate.thumbcount', null);
          $this->_mainframe->setUserState('joom.recreate.imgcount', null);
          $this->_mainframe->setUserState('joom.recreate.recreated', null);

          return false;
        }

        //$this->_mainframe->enqueueMessage(JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_SUCCESSFULLY_CREATED_THUMB', $row->id, $row->imgtitle));
        $recreated[$cid][] = 'thumb';
        $thumb_count++;
      }

      // Recreate detail image if original image is existent
      if($orig_existent && (!$type || $type == 'img'))
      {
        // TODO: Move image into a trash instead of deleting immediately for possible rollback
        if(JFile::exists($img))
        {
          JFile::delete($img);
        }

        $return = JoomIMGtools::resizeImage($debugoutput,
                                            $orig,
                                            $img,
                                            $this->_config->get('jg_resizetomaxwidth'),
                                            $this->_config->get('jg_maxwidth'),
                                            $this->_config->get('jg_maxheight'),
                                            $this->_config->get('jg_thumbcreation'),
                                            $this->_config->get('jg_picturequality'),
                                            false,
                                            $angle,
                                            $this->_config->get('jg_detailautorot'),
                                            false,
                                            true,
                                            false
                                           );

        if(!$return)
        {
          JError::raiseWarning(100, JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_COULD_NOT_CREATE_IMG', $img));
          $this->_mainframe->setUserState('joom.recreate.cids', array());
          $this->_mainframe->setUserState('joom.recreate.thumbcount', null);
          $this->_mainframe->setUserState('joom.recreate.imgcount', null);
          $this->_mainframe->setUserState('joom.recreate.recreated', null);

          return false;
        }

        //$this->_mainframe->enqueueMessage(JText::sprintf('COM_JOOMGALLERY_IMGMAN_MSG_SUCCESSFULLY_CREATED_IMG', $row->id, $row->imgtitle));
        $recreated[$cid][] = 'img';
        $img_count++;
      }

      // trigger Event "onJoomAfterRecreate($files,$orig_exists,$autorot)". Attached is an array with infos about the recreation
      // files: path to the files; orig_exists: true, if original exists; autorot: is there auto rotation for the different image
      $this->_mainframe->triggerEvent('onJoomAfterRecreate', array(array('original'=>$orig, 'detail'=>$img, 'thumbnail'=>$thumb), $orig_existent, array('original'=>$autorot_orig, 'detail'=>$autorot_det, 'thumbnail'=>$autorot_thumb) ));

      unset($cids[$key]);

      // Check remaining time
      if(!$refresher->check())
      {
        $this->_mainframe->setUserState('joom.recreate.cids', $cids);
        $this->_mainframe->setUserState('joom.recreate.thumbcount', $thumb_count);
        $this->_mainframe->setUserState('joom.recreate.imgcount', $img_count);
        $this->_mainframe->setUserState('joom.recreate.recreated', $recreated);
        $refresher->refresh(count($cids));
      }
    }

    $this->_mainframe->setUserState('joom.recreate.cids', array());
    $this->_mainframe->setUserState('joom.recreate.type', null);
    $this->_mainframe->setUserState('joom.recreate.thumbcount', null);
    $this->_mainframe->setUserState('joom.recreate.imgcount', null);
    $this->_mainframe->setUserState('joom.recreate.recreated', null);

    return array($thumb_count, $img_count, $recreated);
  }

  /**
   * Rotate selected images
   *
   * @return  mixed   Result information
   *
   * @since   3.4
   */
  public function rotate()
  {
    jimport('joomla.filesystem.file');

    $cids             = $this->_mainframe->getUserStateFromRequest('joom.rotate.cids', 'cid', array(), 'array');
    $rotateImageTypes = $this->_mainframe->getUserStateFromRequest('joom.rotate.imagetypes', 'rotateimagetypes', 1, 'int');
    $rotateImageAngle = $this->_mainframe->getUserStateFromRequest('joom.rotate.imageangle', 'rotateimageangle', 90, 'int');

    $thumb_count  = $this->_mainframe->getUserState('joom.rotate.thumbcount', count($cids));
    $img_count    = $this->_mainframe->getUserState('joom.rotate.imgcount', count($cids));
    $orig_count   = $this->_mainframe->getUserState('joom.rotate.origcount', $rotateImageTypes == 2 ? count($cids) : 0);
    $debugoutput  = $this->_mainframe->getUserState('joom.rotate.debugoutput', '');
    $firstLoop    = $this->_mainframe->getUserState('joom.rotate.firstloop', true);

    // Before first loop check for selected images
    if($firstLoop && !count($cids))
    {
      $this->setError(JText::_('COM_JOOMGALLERY_COMMON_MSG_NO_IMAGES_SELECTED'));

      return false;
    }

    require_once JPATH_COMPONENT_ADMINISTRATOR.'/helpers/refresher.php';

    $refresher = new JoomRefresher(array('controller' => 'images', 'task' => 'rotate', 'remaining' => count($cids), 'start' => JRequest::getBool('cid')));

    // Loop through selected images
    foreach($cids as $key => $cid)
    {
      $orig  = $this->_ambit->getImg('orig_path', $cid);
      $img   = $this->_ambit->getImg('img_path', $cid);
      $thumb = $this->_ambit->getImg('thumb_path', $cid);
      $err   = false;

      if($rotateImageTypes == 2 && JFile::exists($orig))
      {
        if(JoomIMGtools::rotateImage($debugoutput,
                                     $orig,
                                     $orig,
                                     $this->_config->get('jg_thumbcreation'),
                                     $this->_config->get('jg_originalquality'),
                                     $rotateImageAngle,
                                     false,
                                     true,
                                     true
                                    )
          )
        {
          $orig_count--;

          // Control, if the exif orientation of the original was set to 1 during upload (only if JPG)
          if(exif_imagetype($orig) == IMAGETYPE_JPEG && extension_loaded('exif') && function_exists('exif_read_data'))
          {
            // Read EXIF data (only JPG)
            $exif_tmp = exif_read_data($orig, null, 1);

            if(isset($exif_tmp['IFD0']['Orientation']))
            {
              if($exif_tmp['IFD0']['Orientation'] != 1)
              {
                // Set exif orientation to 1
                $meta_success = JoomIMGtools::copyImageMetadata($orig, $orig, 'JPG', 'JPG', 1, true);
              }
            }
          }
        }
        else
        {
          $debugoutput .= JText::sprintf('COM_JOOMGALLERY_COMMON_ERROR_ROTATE_IMAGE', $orig).'<br />';
          $err          = true;
        }
      }
      else
      {
        if($rotateImageTypes == 2 && !JFile::exists($orig))
        {
          $debugoutput .= JText::sprintf('COM_JOOMGALLERY_ROTATE_NO_ORIG', $orig).'<br />';
          $err          = true;
        }
      }

      if($rotateImageTypes != 2 || ($rotateImageTypes == 2 && !$err))
      {
        // If there are no errors so far...
        if($rotateImageTypes == 2)
        {
          // As we have a successfully rotated original we should use a resize here
          if(JoomIMGtools::resizeImage($debugoutput,
                                       $orig,
                                       $img,
                                       $this->_config->get('jg_resizetomaxwidth'),
                                       $this->_config->get('jg_maxwidth'),
                                       $this->_config->get('jg_maxheight'),
                                       $this->_config->get('jg_thumbcreation'),
                                       $this->_config->get('jg_picturequality'),
                                       false,
                                       0,
                                       false,
                                       false,
                                       true,
                                       false
                                      )
            )
          {
            $img_count--;
          }
          else
          {
            $debugoutput .= JText::sprintf('COM_JOOMGALLERY_COMMON_ERROR_ROTATE_IMAGE', $img).'<br />';
            $err          = true;
          }
        }
        else
        {
          if(JoomIMGtools::rotateImage($debugoutput,
                                       $img,
                                       $img,
                                       $this->_config->get('jg_thumbcreation'),
                                       $this->_config->get('jg_picturequality'),
                                       $rotateImageAngle,
                                       false,
                                       false,
                                       true
                                      )
            )
          {
            $img_count--;
          }
          else
          {
            $debugoutput .= JText::sprintf('COM_JOOMGALLERY_COMMON_ERROR_ROTATE_IMAGE', $img).'<br />';

            // As the rotation of the detail image failed the thumb should be resized instead of rotated.
            $err = true;
          }
        }

        $tmpdebugoutput = '';

        // As there is no original image available or original was not rotated, use detail image instead
        if(!JFile::exists($orig) || $rotateImageTypes != 2)
        {
          $orig = $img;
        }

        // As we have a successfully rotated original or detail we should use a resize here to ensure the correct
        // appearance according to the thumbnail conversion settings
        $ret = JoomIMGtools::resizeImage($tmpdebugoutput,
                                         $orig,
                                         $thumb,
                                         $this->_config->get('jg_useforresizedirection'),
                                         $this->_config->get('jg_thumbwidth'),
                                         $this->_config->get('jg_thumbheight'),
                                         $this->_config->get('jg_thumbcreation'),
                                         $this->_config->get('jg_thumbquality'),
                                         $this->_config->get('jg_cropposition'),
                                         0,
                                         false,
                                         false,
                                         false,
                                         true
                                        );

        if($ret)
        {
          $thumb_count--;
        }
        else
        {
          $debugoutput .= $tmpdebugoutput;
          $debugoutput .= JText::sprintf('COM_JOOMGALLERY_COMMON_ERROR_ROTATE_IMAGE', $thumb).'<br />';
          $err          = true;
        }
      }

      // trigger Event "onJoomAfterRotate($files,$angle,$imgtypes)". Attached is an array with infos about the rotation
      // files: path to the files; angle: the angle by which the images were rotated; imgtypes: 1(Thumbs and details), 2(All images)
      $this->_mainframe->triggerEvent('onJoomAfterRotate', array(array('original'=>$orig, 'detail'=>$img, 'thumbnail'=>$thumb), $rotateImageAngle, $rotateimagetypes));

      unset($cids[$key]);

      // Check remaining time
      if(!$refresher->check())
      {
        $this->_mainframe->setUserState('joom.rotate.cids', $cids);
        $this->_mainframe->setUserState('joom.rotate.imagetypes', $rotateImageTypes);
        $this->_mainframe->setUserState('joom.rotate.imageangle', $rotateImageAngle);
        $this->_mainframe->setUserState('joom.rotate.thumbcount', $thumb_count);
        $this->_mainframe->setUserState('joom.rotate.imgcount', $img_count);
        $this->_mainframe->setUserState('joom.rotate.rotated', $orig_count);
        $this->_mainframe->setUserState('joom.rotate.debugoutput', $debugoutput);
        $this->_mainframe->setUserState('joom.rotate.firstloop', false);

        $refresher->refresh(count($cids));
      }
    }

    $this->_mainframe->setUserState('joom.rotate.cids', null);
    $this->_mainframe->setUserState('joom.rotate.imagetypes', null);
    $this->_mainframe->setUserState('joom.rotate.imageangle', null);
    $this->_mainframe->setUserState('joom.rotate.thumbcount', null);
    $this->_mainframe->setUserState('joom.rotate.imgcount', null);
    $this->_mainframe->setUserState('joom.rotate.origcount', null);
    $this->_mainframe->setUserState('joom.rotate.debugoutput', null);
    $this->_mainframe->setUserState('joom.rotate.firstloop', null);

    return array($thumb_count, $img_count, $orig_count, $debugoutput);
  }

  /**
   * Search and replace information in selected images
   *
   * @return  mixed   Result information
   *
   * @since   3.6
   */
  public function replace()
  {
    // get Data
    $cids       = $this->_mainframe->input->get('cid', array(), 'array');
    $fields     = $this->_mainframe->input->get('batch_fields', array(), 'array');
    $searchVal  = $this->_mainframe->input->get('batch_search', '', 'string');
    $replaceVal = $this->_mainframe->input->get('batch_replace', '', 'string');

    $nmb_imgs    = count($cids);  // Number of images to process
    $nmb_rep     = 0;             // Number of performed replacements
    $nmb_repimgs = 0;             // Number of images with performed replacements
    $nmb_err     = 0;             // Number of error images
    $erroroutput = '';
    $firstLoop   = true;

    // Before first loop check for selected images
    if($firstLoop && !count($cids))
    {
      $this->setError(JText::_('COM_JOOMGALLERY_COMMON_MSG_NO_IMAGES_SELECTED'));

      return false;
    }

    $row = $this->getTable('joomgalleryimages');

    // Loop through selected images
    foreach($cids as $i => $id)
    {
      // Reset JTable class
      $row->reset();

      // Read image from database
      $row->load($id);

      $tmp_rep = 0;
      foreach($fields as $fieldname)
      {
        if($fieldname != 'additional')
        {
          $replacements = 0;

          // Replace image informations
          $row->{$fieldname} = str_replace($searchVal, $replaceVal, $row->{$fieldname}, $replacements);

          // count replacements
          $tmp_rep = $tmp_rep + $replacements;
        }
      }

      // Make sure the record is valid
      if(!$row->check())
      {
        $erroroutput .= 'Image (ID:' . $id . '):' . $row->getError() . '<br />';
        $nmb_err      = $nmb_err + 1;

        continue;
      }

      // Store the entry to the database
      if(!$row->store())
      {
        $erroroutput .= 'Image (ID:' . $id . '):' . $row->getError() . '<br />';
        $nmb_err      = $nmb_err + 1;

        continue;
      }

      // Plugin event onJoomAfterSearchReplace
      $this->_mainframe->triggerEvent('onJoomAfterSearchReplace', array($id, $searchVal, $replaceVal, $fields, &$tmp_rep));

      // count image if there was a replacement
      if($tmp_rep > 0)
      {
        $nmb_rep     = $nmb_rep + $tmp_rep;
        $nmb_repimgs = $nmb_repimgs + 1;
      }
    }

    return array('stats'=>array($nmb_imgs, $nmb_rep, $nmb_repimgs, $nmb_err), 'msg' => $erroroutput);
  }

  /**
   * Returns the query for listing the images
   *
   * @return  string    The query to be used to retrieve the images data from the database
   * @since   1.5.5
   */
  protected function _buildQuery()
  {
    // Create a new query object
    $query = $this->_db->getQuery(true);

    // Select the required fields from the table
    $query->select('a.*')
          ->from(_JOOM_TABLE_IMAGES.' AS a');

    // Join over the categories
    $query->select('c.cid AS category, c.name AS category_name')
          ->leftJoin(_JOOM_TABLE_CATEGORIES.' AS c ON c.cid = a.catid');

    // Join over the access levels
    $query->select('v.title AS access_level')
          ->leftJoin('#__viewlevels AS v ON v.id = a.access');

    // Join over the users
    $query->leftJoin('#__users AS u ON u.id = a.owner');

    // Join over the categories again in order to check access levels
    if(!$this->_user->authorise('core.admin'))
    {
      $query->leftJoin(_JOOM_TABLE_CATEGORIES.' AS p ON c.lft BETWEEN p.lft AND p.rgt')
            ->select('c.level')
            ->where('p.access IN ('.implode(',', $this->_user->getAuthorisedViewLevels()).')')
            ->group('a.id')
            ->having('COUNT(p.cid) > c.level')

      // Access level check for the image and the category the image is in
            ->where('a.access IN ('.implode(',', $this->_user->getAuthorisedViewLevels()).')')
            ->where('c.access IN ('.implode(',', $this->_user->getAuthorisedViewLevels()).')');
    }

    // Filter by access level
    if($access = $this->getState('filter.access'))
    {
      $query->where('a.access = '.(int) $access);
    }

    // Filter by owner
    if($owner = $this->getState('filter.owner'))
    {
      $query->where('a.owner = '.(int) $owner);
    }

    // Filter by category
    if($category = $this->getState('filter.category'))
    {
      $query->where('a.catid = '.(int) $category);
    }

    // Filter by state
    $published = $this->getState('filter.state');
    switch($published)
    {
      case 1:
        // Published
        $query->where('a.published = 1');
        break;
      case 2:
        // Not published
        $query->where('a.published = 0');
        break;
      case 3:
        // Approved
        $query->where('a.approved = 1');
        break;
      case 4:
        // Not approved
        $query->where('a.approved = 0');
        break;
      case 5:
        // Rejected
        $query->where('a.approved = -1');
        break;
      case 6:
        // Featured
        $query->where('a.featured = 1');
        break;
      case 7:
        // Not featured
        $query->where('a.featured = 0');
        break;
      default:
        // No filter by state
        break;
    }

    // Filter by type
    $type = $this->getState('filter.type');
    switch($type)
    {
      case 1:
        // User images
        $query->where('a.owner != 0');
        break;
      case 2:
        // Administrator images
        $query->where('a.owner = 0');
        break;
      default:
        // No filter by type
        break;
    }

    // Filter by search
    $search = $this->getState('filter.search');
    if(!empty($search))
    {
      if(stripos($search, 'id:') === 0)
      {
        $query->where('a.id = '.(int) substr($search, 3));
      }
      else
      {
        if(stripos($search, 'author:') === 0)
        {
          $search = $this->_db->Quote('%'.$this->_db->escape(substr($search, 7), true).'%');
          $query->where('(u.name LIKE '.$search.' OR u.username LIKE '.$search.')');
        }
        else
        {
          $search = $this->_db->Quote('%'.$this->_db->escape($search, true).'%');
          $query->where('(a.imgtitle LIKE '.$search.' OR a.alias LIKE '.$search.' OR LOWER(a.imgtext) LIKE '.$search.')');
        }
      }
    }

    // Add the order clause
    $orderCol   = $this->state->get('list.ordering');
    $orderDirn  = $this->state->get('list.direction');
    if($orderCol == 'a.ordering' || $orderCol == 'category_name')
    {
      $orderCol = 'category_name '.$orderDirn.', a.ordering';
    }
    $query->order($this->_db->escape($orderCol.' '.$orderDirn));

    return $query;
  }

  /**
   * Gets the value of a user state variable and sets it in the session
   * This is the same as the method in JApplication except that this also can optionally
   * force you back to the first page when a filter has changed
   *
   * @param   string  $key        The key of the user state variable
   * @param   string  $request    The name of the variable passed in a request
   * @param   string  $default    The default value for the variable if not found (optional)
   * @param   string  $type       Filter for the variable, for valid values see {@link JFilterInput::clean()} (optional)
   * @param   boolean $resetPage  If true, the limitstart in request is set to zero if the state has changed
   * @return  The requested user state
   * @since   2.0
   */
  public function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $resetPage = true)
  {
    $app = JFactory::getApplication();

    $old_state = $app->getUserState($key);
    $cur_state = (!is_null($old_state)) ? $old_state : $default;
    $new_state = JRequest::getVar($request, null, 'default', $type);

    // Special case for owner filter since Joomla! 3.5 when using modal user selection
    if(    !is_null($new_state) && isset($new_state['owner'])
        && ($new_state['owner'] === 0 || $new_state['owner'] === '0')
      )
    {
      $new_state['owner'] = '';
    }

    if($cur_state != $new_state && !is_null($new_state) && !is_null($old_state) && $resetPage)
    {
      JRequest::setVar('limitstart', 0);
    }

    // Save the new value only if it was set in this request.
    if($new_state !== null)
    {
      $app->setUserState($key, $new_state);
    }
    else
    {
      $new_state = $cur_state;
    }

    return $new_state;
  }
}