[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_banners/src/Model/ -> ClientsModel.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_banners
   6   *
   7   * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9   */
  10  
  11  namespace Joomla\Component\Banners\Administrator\Model;
  12  
  13  use Joomla\CMS\Component\ComponentHelper;
  14  use Joomla\CMS\MVC\Model\ListModel;
  15  use Joomla\Database\ParameterType;
  16  
  17  // phpcs:disable PSR1.Files.SideEffects
  18  \defined('_JEXEC') or die;
  19  // phpcs:enable PSR1.Files.SideEffects
  20  
  21  /**
  22   * Methods supporting a list of banner records.
  23   *
  24   * @since  1.6
  25   */
  26  class ClientsModel extends ListModel
  27  {
  28      /**
  29       * Constructor.
  30       *
  31       * @param   array  $config  An optional associative array of configuration settings.
  32       *
  33       * @since   1.6
  34       */
  35      public function __construct($config = array())
  36      {
  37          if (empty($config['filter_fields'])) {
  38              $config['filter_fields'] = array(
  39                  'id', 'a.id',
  40                  'name', 'a.name',
  41                  'contact', 'a.contact',
  42                  'state', 'a.state',
  43                  'checked_out', 'a.checked_out',
  44                  'checked_out_time', 'a.checked_out_time',
  45                  'purchase_type', 'a.purchase_type'
  46              );
  47          }
  48  
  49          parent::__construct($config);
  50      }
  51  
  52      /**
  53       * Method to auto-populate the model state.
  54       *
  55       * Note. Calling getState in this method will result in recursion.
  56       *
  57       * @param   string  $ordering   An optional ordering field.
  58       * @param   string  $direction  An optional direction (asc|desc).
  59       *
  60       * @return  void
  61       *
  62       * @since   1.6
  63       */
  64      protected function populateState($ordering = 'a.name', $direction = 'asc')
  65      {
  66          // Load the parameters.
  67          $this->setState('params', ComponentHelper::getParams('com_banners'));
  68  
  69          // List state information.
  70          parent::populateState($ordering, $direction);
  71      }
  72  
  73      /**
  74       * Method to get a store id based on model configuration state.
  75       *
  76       * This is necessary because the model is used by the component and
  77       * different modules that might need different sets of data or different
  78       * ordering requirements.
  79       *
  80       * @param   string  $id  A prefix for the store id.
  81       *
  82       * @return  string  A store id.
  83       */
  84      protected function getStoreId($id = '')
  85      {
  86          // Compile the store id.
  87          $id .= ':' . $this->getState('filter.search');
  88          $id .= ':' . $this->getState('filter.state');
  89          $id .= ':' . $this->getState('filter.purchase_type');
  90  
  91          return parent::getStoreId($id);
  92      }
  93  
  94      /**
  95       * Build an SQL query to load the list data.
  96       *
  97       * @return  \Joomla\Database\DatabaseQuery
  98       */
  99      protected function getListQuery()
 100      {
 101          // Create a new query object.
 102          $db    = $this->getDatabase();
 103          $query = $db->getQuery(true);
 104  
 105          $defaultPurchase = (int) ComponentHelper::getParams('com_banners')->get('purchase_type', 3);
 106  
 107          // Select the required fields from the table.
 108          $query->select(
 109              $this->getState(
 110                  'list.select',
 111                  [
 112                      $db->quoteName('a.id'),
 113                      $db->quoteName('a.name'),
 114                      $db->quoteName('a.contact'),
 115                      $db->quoteName('a.checked_out'),
 116                      $db->quoteName('a.checked_out_time'),
 117                      $db->quoteName('a.state'),
 118                      $db->quoteName('a.metakey'),
 119                      $db->quoteName('a.purchase_type'),
 120                  ]
 121              )
 122          )
 123              ->select(
 124                  [
 125                      'COUNT(' . $db->quoteName('b.id') . ') AS ' . $db->quoteName('nbanners'),
 126                      $db->quoteName('uc.name', 'editor'),
 127                  ]
 128              );
 129  
 130          $query->from($db->quoteName('#__banner_clients', 'a'));
 131  
 132          // Join over the banners for counting
 133          $query->join('LEFT', $db->quoteName('#__banners', 'b'), $db->quoteName('a.id') . ' = ' . $db->quoteName('b.cid'));
 134  
 135          // Join over the users for the checked out user.
 136          $query->join('LEFT', $db->quoteName('#__users', 'uc'), $db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out'));
 137  
 138          // Filter by published state
 139          $published = (string) $this->getState('filter.state');
 140  
 141          if (is_numeric($published)) {
 142              $published = (int) $published;
 143              $query->where($db->quoteName('a.state') . ' = :published')
 144                  ->bind(':published', $published, ParameterType::INTEGER);
 145          } elseif ($published === '') {
 146              $query->where($db->quoteName('a.state') . ' IN (0, 1)');
 147          }
 148  
 149          $query->group(
 150              [
 151                  $db->quoteName('a.id'),
 152                  $db->quoteName('a.name'),
 153                  $db->quoteName('a.contact'),
 154                  $db->quoteName('a.checked_out'),
 155                  $db->quoteName('a.checked_out_time'),
 156                  $db->quoteName('a.state'),
 157                  $db->quoteName('a.metakey'),
 158                  $db->quoteName('a.purchase_type'),
 159                  $db->quoteName('uc.name'),
 160              ]
 161          );
 162  
 163          // Filter by search in title
 164          if ($search = trim($this->getState('filter.search', ''))) {
 165              if (stripos($search, 'id:') === 0) {
 166                  $search = (int) substr($search, 3);
 167                  $query->where($db->quoteName('a.id') . ' = :search')
 168                      ->bind(':search', $search, ParameterType::INTEGER);
 169              } else {
 170                  $search = '%' . str_replace(' ', '%', $search) . '%';
 171                  $query->where($db->quoteName('a.name') . ' LIKE :search')
 172                      ->bind(':search', $search);
 173              }
 174          }
 175  
 176          // Filter by purchase type
 177          if ($purchaseType = (int) $this->getState('filter.purchase_type')) {
 178              if ($defaultPurchase === $purchaseType) {
 179                  $query->where('(' . $db->quoteName('a.purchase_type') . ' = :type OR ' . $db->quoteName('a.purchase_type') . ' = -1)');
 180              } else {
 181                  $query->where($db->quoteName('a.purchase_type') . ' = :type');
 182              }
 183  
 184              $query->bind(':type', $purchaseType, ParameterType::INTEGER);
 185          }
 186  
 187          // Add the list ordering clause.
 188          $query->order(
 189              $db->quoteName($db->escape($this->getState('list.ordering', 'a.name'))) . ' ' . $db->escape($this->getState('list.direction', 'ASC'))
 190          );
 191  
 192          return $query;
 193      }
 194  
 195      /**
 196       * Overrides the getItems method to attach additional metrics to the list.
 197       *
 198       * @return  mixed  An array of data items on success, false on failure.
 199       *
 200       * @since   3.6
 201       */
 202      public function getItems()
 203      {
 204          // Get a storage key.
 205          $store = $this->getStoreId('getItems');
 206  
 207          // Try to load the data from internal storage.
 208          if (!empty($this->cache[$store])) {
 209              return $this->cache[$store];
 210          }
 211  
 212          // Load the list items.
 213          $items = parent::getItems();
 214  
 215          // If empty or an error, just return.
 216          if (empty($items)) {
 217              return array();
 218          }
 219  
 220          // Getting the following metric by joins is WAY TOO SLOW.
 221          // Faster to do three queries for very large banner trees.
 222  
 223          // Get the clients in the list.
 224          $db = $this->getDatabase();
 225          $clientIds = array_column($items, 'id');
 226  
 227          $query = $db->getQuery(true)
 228              ->select(
 229                  [
 230                      $db->quoteName('cid'),
 231                      'COUNT(' . $db->quoteName('cid') . ') AS ' . $db->quoteName('count_published'),
 232                  ]
 233              )
 234              ->from($db->quoteName('#__banners'))
 235              ->where($db->quoteName('state') . ' = :state')
 236              ->whereIn($db->quoteName('cid'), $clientIds)
 237              ->group($db->quoteName('cid'))
 238              ->bind(':state', $state, ParameterType::INTEGER);
 239  
 240          $db->setQuery($query);
 241  
 242          // Get the published banners count.
 243          try {
 244              $state = 1;
 245              $countPublished = $db->loadAssocList('cid', 'count_published');
 246          } catch (\RuntimeException $e) {
 247              $this->setError($e->getMessage());
 248  
 249              return false;
 250          }
 251  
 252          // Get the unpublished banners count.
 253          try {
 254              $state = 0;
 255              $countUnpublished = $db->loadAssocList('cid', 'count_published');
 256          } catch (\RuntimeException $e) {
 257              $this->setError($e->getMessage());
 258  
 259              return false;
 260          }
 261  
 262          // Get the trashed banners count.
 263          try {
 264              $state = -2;
 265              $countTrashed = $db->loadAssocList('cid', 'count_published');
 266          } catch (\RuntimeException $e) {
 267              $this->setError($e->getMessage());
 268  
 269              return false;
 270          }
 271  
 272          // Get the archived banners count.
 273          try {
 274              $state = 2;
 275              $countArchived = $db->loadAssocList('cid', 'count_published');
 276          } catch (\RuntimeException $e) {
 277              $this->setError($e->getMessage());
 278  
 279              return false;
 280          }
 281  
 282          // Inject the values back into the array.
 283          foreach ($items as $item) {
 284              $item->count_published   = isset($countPublished[$item->id]) ? $countPublished[$item->id] : 0;
 285              $item->count_unpublished = isset($countUnpublished[$item->id]) ? $countUnpublished[$item->id] : 0;
 286              $item->count_trashed     = isset($countTrashed[$item->id]) ? $countTrashed[$item->id] : 0;
 287              $item->count_archived    = isset($countArchived[$item->id]) ? $countArchived[$item->id] : 0;
 288          }
 289  
 290          // Add the items to the internal cache.
 291          $this->cache[$store] = $items;
 292  
 293          return $this->cache[$store];
 294      }
 295  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer