[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_fields/src/Model/ -> FieldsModel.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_fields
   6   *
   7   * @copyright   (C) 2016 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\Fields\Administrator\Model;
  12  
  13  use Joomla\CMS\Categories\CategoryServiceInterface;
  14  use Joomla\CMS\Categories\SectionNotFoundException;
  15  use Joomla\CMS\Factory;
  16  use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
  17  use Joomla\CMS\MVC\Model\ListModel;
  18  use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
  19  use Joomla\Database\ParameterType;
  20  use Joomla\Registry\Registry;
  21  use Joomla\Utilities\ArrayHelper;
  22  
  23  // phpcs:disable PSR1.Files.SideEffects
  24  \defined('_JEXEC') or die;
  25  // phpcs:enable PSR1.Files.SideEffects
  26  
  27  /**
  28   * Fields Model
  29   *
  30   * @since  3.7.0
  31   */
  32  class FieldsModel extends ListModel
  33  {
  34      /**
  35       * Constructor
  36       *
  37       * @param   array                $config   An array of configuration options (name, state, dbo, table_path, ignore_request).
  38       * @param   MVCFactoryInterface  $factory  The factory.
  39       *
  40       * @since   3.7.0
  41       * @throws  \Exception
  42       */
  43      public function __construct($config = array(), MVCFactoryInterface $factory = null)
  44      {
  45          if (empty($config['filter_fields'])) {
  46              $config['filter_fields'] = array(
  47                  'id', 'a.id',
  48                  'title', 'a.title',
  49                  'type', 'a.type',
  50                  'name', 'a.name',
  51                  'state', 'a.state',
  52                  'access', 'a.access',
  53                  'access_level',
  54                  'only_use_in_subform',
  55                  'language', 'a.language',
  56                  'ordering', 'a.ordering',
  57                  'checked_out', 'a.checked_out',
  58                  'checked_out_time', 'a.checked_out_time',
  59                  'created_time', 'a.created_time',
  60                  'created_user_id', 'a.created_user_id',
  61                  'group_title', 'g.title',
  62                  'category_id', 'a.category_id',
  63                  'group_id', 'a.group_id',
  64                  'assigned_cat_ids'
  65              );
  66          }
  67  
  68          parent::__construct($config, $factory);
  69      }
  70  
  71      /**
  72       * Method to auto-populate the model state.
  73       *
  74       * This method should only be called once per instantiation and is designed
  75       * to be called on the first call to the getState() method unless the model
  76       * configuration flag to ignore the request is set.
  77       *
  78       * Note. Calling getState in this method will result in recursion.
  79       *
  80       * @param   string  $ordering   An optional ordering field.
  81       * @param   string  $direction  An optional direction (asc|desc).
  82       *
  83       * @return  void
  84       *
  85       * @since   3.7.0
  86       */
  87      protected function populateState($ordering = null, $direction = null)
  88      {
  89          // List state information.
  90          parent::populateState('a.ordering', 'asc');
  91  
  92          $context = $this->getUserStateFromRequest($this->context . '.context', 'context', 'com_content.article', 'CMD');
  93          $this->setState('filter.context', $context);
  94  
  95          // Split context into component and optional section
  96          $parts = FieldsHelper::extract($context);
  97  
  98          if ($parts) {
  99              $this->setState('filter.component', $parts[0]);
 100              $this->setState('filter.section', $parts[1]);
 101          }
 102      }
 103  
 104      /**
 105       * Method to get a store id based on the model configuration state.
 106       *
 107       * This is necessary because the model is used by the component and
 108       * different modules that might need different sets of data or different
 109       * ordering requirements.
 110       *
 111       * @param   string  $id  An identifier string to generate the store id.
 112       *
 113       * @return  string  A store id.
 114       *
 115       * @since   3.7.0
 116       */
 117      protected function getStoreId($id = '')
 118      {
 119          // Compile the store id.
 120          $id .= ':' . $this->getState('filter.search');
 121          $id .= ':' . $this->getState('filter.context');
 122          $id .= ':' . serialize($this->getState('filter.assigned_cat_ids'));
 123          $id .= ':' . $this->getState('filter.state');
 124          $id .= ':' . $this->getState('filter.group_id');
 125          $id .= ':' . serialize($this->getState('filter.language'));
 126          $id .= ':' . $this->getState('filter.only_use_in_subform');
 127  
 128          return parent::getStoreId($id);
 129      }
 130  
 131      /**
 132       * Method to get a DatabaseQuery object for retrieving the data set from a database.
 133       *
 134       * @return  \Joomla\Database\DatabaseQuery   A DatabaseQuery object to retrieve the data set.
 135       *
 136       * @since   3.7.0
 137       */
 138      protected function getListQuery()
 139      {
 140          // Create a new query object.
 141          $db    = $this->getDatabase();
 142          $query = $db->getQuery(true);
 143          $user  = Factory::getUser();
 144          $app   = Factory::getApplication();
 145  
 146          // Select the required fields from the table.
 147          $query->select(
 148              $this->getState(
 149                  'list.select',
 150                  'DISTINCT a.id, a.title, a.name, a.checked_out, a.checked_out_time, a.note' .
 151                  ', a.state, a.access, a.created_time, a.created_user_id, a.ordering, a.language' .
 152                  ', a.fieldparams, a.params, a.type, a.default_value, a.context, a.group_id' .
 153                  ', a.label, a.description, a.required, a.only_use_in_subform'
 154              )
 155          );
 156          $query->from('#__fields AS a');
 157  
 158          // Join over the language
 159          $query->select('l.title AS language_title, l.image AS language_image')
 160              ->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');
 161  
 162          // Join over the users for the checked out user.
 163          $query->select('uc.name AS editor')->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');
 164  
 165          // Join over the asset groups.
 166          $query->select('ag.title AS access_level')->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');
 167  
 168          // Join over the users for the author.
 169          $query->select('ua.name AS author_name')->join('LEFT', '#__users AS ua ON ua.id = a.created_user_id');
 170  
 171          // Join over the field groups.
 172          $query->select('g.title AS group_title, g.access as group_access, g.state AS group_state, g.note as group_note');
 173          $query->join('LEFT', '#__fields_groups AS g ON g.id = a.group_id');
 174  
 175          // Filter by context
 176          if ($context = $this->getState('filter.context')) {
 177              $query->where($db->quoteName('a.context') . ' = :context')
 178                  ->bind(':context', $context);
 179          }
 180  
 181          // Filter by access level.
 182          if ($access = $this->getState('filter.access')) {
 183              if (is_array($access)) {
 184                  $access = ArrayHelper::toInteger($access);
 185                  $query->whereIn($db->quoteName('a.access'), $access);
 186              } else {
 187                  $access = (int) $access;
 188                  $query->where($db->quoteName('a.access') . ' = :access')
 189                      ->bind(':access', $access, ParameterType::INTEGER);
 190              }
 191          }
 192  
 193          if (($categories = $this->getState('filter.assigned_cat_ids')) && $context) {
 194              $categories = (array) $categories;
 195              $categories = ArrayHelper::toInteger($categories);
 196              $parts = FieldsHelper::extract($context);
 197  
 198              if ($parts) {
 199                  // Get the categories for this component (and optionally this section, if available)
 200                  $cat = (
 201                      function () use ($parts) {
 202                          // Get the CategoryService for this component
 203                          $componentObject = $this->bootComponent($parts[0]);
 204  
 205                          if (!$componentObject instanceof CategoryServiceInterface) {
 206                              // No CategoryService -> no categories
 207                              return null;
 208                          }
 209  
 210                          $cat = null;
 211  
 212                          // Try to get the categories for this component and section
 213                          try {
 214                              $cat = $componentObject->getCategory([], $parts[1] ?: '');
 215                          } catch (SectionNotFoundException $e) {
 216                              // Not found for component and section -> Now try once more without the section, so only component
 217                              try {
 218                                  $cat = $componentObject->getCategory();
 219                              } catch (SectionNotFoundException $e) {
 220                                  // If we haven't found it now, return (no categories available for this component)
 221                                  return null;
 222                              }
 223                          }
 224  
 225                          // So we found categories for at least the component, return them
 226                          return $cat;
 227                      }
 228                  )();
 229  
 230                  if ($cat) {
 231                      foreach ($categories as $assignedCatIds) {
 232                          // Check if we have the actual category
 233                          $parent = $cat->get($assignedCatIds);
 234  
 235                          if ($parent) {
 236                              $categories[] = (int) $parent->id;
 237  
 238                              // Traverse the tree up to get all the fields which are attached to a parent
 239                              while ($parent->getParent() && $parent->getParent()->id != 'root') {
 240                                  $parent = $parent->getParent();
 241                                  $categories[] = (int) $parent->id;
 242                              }
 243                          }
 244                      }
 245                  }
 246              }
 247  
 248              $categories = array_unique($categories);
 249  
 250              // Join over the assigned categories
 251              $query->join('LEFT', $db->quoteName('#__fields_categories') . ' AS fc ON fc.field_id = a.id');
 252  
 253              if (in_array('0', $categories)) {
 254                  $query->where(
 255                      '(' .
 256                          $db->quoteName('fc.category_id') . ' IS NULL OR ' .
 257                          $db->quoteName('fc.category_id') . ' IN (' . implode(',', $query->bindArray(array_values($categories), ParameterType::INTEGER)) . ')' .
 258                      ')'
 259                  );
 260              } else {
 261                  $query->whereIn($db->quoteName('fc.category_id'), $categories);
 262              }
 263          }
 264  
 265          // Implement View Level Access
 266          if (!$app->isClient('administrator') || !$user->authorise('core.admin')) {
 267              $groups = $user->getAuthorisedViewLevels();
 268              $query->whereIn($db->quoteName('a.access'), $groups);
 269              $query->extendWhere(
 270                  'AND',
 271                  [
 272                      $db->quoteName('a.group_id') . ' = 0',
 273                      $db->quoteName('g.access') . ' IN (' . implode(',', $query->bindArray($groups, ParameterType::INTEGER)) . ')'
 274                  ],
 275                  'OR'
 276              );
 277          }
 278  
 279          // Filter by state
 280          $state = $this->getState('filter.state');
 281  
 282          // Include group state only when not on on back end list
 283          $includeGroupState = !$app->isClient('administrator') ||
 284              $app->input->get('option') != 'com_fields' ||
 285              $app->input->get('view') != 'fields';
 286  
 287          if (is_numeric($state)) {
 288              $state = (int) $state;
 289              $query->where($db->quoteName('a.state') . ' = :state')
 290                  ->bind(':state', $state, ParameterType::INTEGER);
 291  
 292              if ($includeGroupState) {
 293                  $query->extendWhere(
 294                      'AND',
 295                      [
 296                          $db->quoteName('a.group_id') . ' = 0',
 297                          $db->quoteName('g.state') . ' = :gstate',
 298                      ],
 299                      'OR'
 300                  )
 301                      ->bind(':gstate', $state, ParameterType::INTEGER);
 302              }
 303          } elseif (!$state) {
 304              $query->whereIn($db->quoteName('a.state'), [0, 1]);
 305  
 306              if ($includeGroupState) {
 307                  $query->extendWhere(
 308                      'AND',
 309                      [
 310                          $db->quoteName('a.group_id') . ' = 0',
 311                          $db->quoteName('g.state') . ' IN (' . implode(',', $query->bindArray([0, 1], ParameterType::INTEGER)) . ')'
 312                      ],
 313                      'OR'
 314                  );
 315              }
 316          }
 317  
 318          $groupId = $this->getState('filter.group_id');
 319  
 320          if (is_numeric($groupId)) {
 321              $groupId = (int) $groupId;
 322              $query->where($db->quoteName('a.group_id') . ' = :groupid')
 323                  ->bind(':groupid', $groupId, ParameterType::INTEGER);
 324          }
 325  
 326          $onlyUseInSubForm = $this->getState('filter.only_use_in_subform');
 327  
 328          if (is_numeric($onlyUseInSubForm)) {
 329              $onlyUseInSubForm = (int) $onlyUseInSubForm;
 330              $query->where($db->quoteName('a.only_use_in_subform') . ' = :only_use_in_subform')
 331                  ->bind(':only_use_in_subform', $onlyUseInSubForm, ParameterType::INTEGER);
 332          }
 333  
 334          // Filter by search in title
 335          $search = $this->getState('filter.search');
 336  
 337          if (!empty($search)) {
 338              if (stripos($search, 'id:') === 0) {
 339                  $search = (int) substr($search, 3);
 340                  $query->where($db->quoteName('a.id') . ' = :id')
 341                      ->bind(':id', $search, ParameterType::INTEGER);
 342              } elseif (stripos($search, 'author:') === 0) {
 343                  $search = '%' . substr($search, 7) . '%';
 344                  $query->where(
 345                      '(' .
 346                          $db->quoteName('ua.name') . ' LIKE :name OR ' .
 347                          $db->quoteName('ua.username') . ' LIKE :username' .
 348                      ')'
 349                  )
 350                      ->bind(':name', $search)
 351                      ->bind(':username', $search);
 352              } else {
 353                  $search = '%' . str_replace(' ', '%', trim($search)) . '%';
 354                  $query->where(
 355                      '(' .
 356                          $db->quoteName('a.title') . ' LIKE :title OR ' .
 357                          $db->quoteName('a.name') . ' LIKE :sname OR ' .
 358                          $db->quoteName('a.note') . ' LIKE :note' .
 359                      ')'
 360                  )
 361                      ->bind(':title', $search)
 362                      ->bind(':sname', $search)
 363                      ->bind(':note', $search);
 364              }
 365          }
 366  
 367          // Filter on the language.
 368          if ($language = $this->getState('filter.language')) {
 369              $language = (array) $language;
 370  
 371              $query->whereIn($db->quoteName('a.language'), $language, ParameterType::STRING);
 372          }
 373  
 374          // Add the list ordering clause
 375          $listOrdering  = $this->state->get('list.ordering', 'a.ordering');
 376          $orderDirn     = $this->state->get('list.direction', 'ASC');
 377  
 378          $query->order($db->escape($listOrdering) . ' ' . $db->escape($orderDirn));
 379  
 380          return $query;
 381      }
 382  
 383      /**
 384       * Gets an array of objects from the results of database query.
 385       *
 386       * @param   string   $query       The query.
 387       * @param   integer  $limitstart  Offset.
 388       * @param   integer  $limit       The number of records.
 389       *
 390       * @return  array  An array of results.
 391       *
 392       * @since   3.7.0
 393       * @throws  \RuntimeException
 394       */
 395      protected function _getList($query, $limitstart = 0, $limit = 0)
 396      {
 397          $result = parent::_getList($query, $limitstart, $limit);
 398  
 399          if (is_array($result)) {
 400              foreach ($result as $field) {
 401                  $field->fieldparams = new Registry($field->fieldparams);
 402                  $field->params = new Registry($field->params);
 403              }
 404          }
 405  
 406          return $result;
 407      }
 408  
 409      /**
 410       * Get the filter form
 411       *
 412       * @param   array    $data      data
 413       * @param   boolean  $loadData  load current data
 414       *
 415       * @return  \Joomla\CMS\Form\Form|bool  the Form object or false
 416       *
 417       * @since   3.7.0
 418       */
 419      public function getFilterForm($data = array(), $loadData = true)
 420      {
 421          $form = parent::getFilterForm($data, $loadData);
 422  
 423          if ($form) {
 424              $form->setValue('context', null, $this->getState('filter.context'));
 425              $form->setFieldAttribute('group_id', 'context', $this->getState('filter.context'), 'filter');
 426              $form->setFieldAttribute('assigned_cat_ids', 'extension', $this->state->get('filter.component'), 'filter');
 427          }
 428  
 429          return $form;
 430      }
 431  
 432      /**
 433       * Get the groups for the batch method
 434       *
 435       * @return  array  An array of groups
 436       *
 437       * @since   3.7.0
 438       */
 439      public function getGroups()
 440      {
 441          $user       = Factory::getUser();
 442          $viewlevels = ArrayHelper::toInteger($user->getAuthorisedViewLevels());
 443          $context    = $this->state->get('filter.context');
 444  
 445          $db    = $this->getDatabase();
 446          $query = $db->getQuery(true);
 447          $query->select(
 448              [
 449                  $db->quoteName('title', 'text'),
 450                  $db->quoteName('id', 'value'),
 451                  $db->quoteName('state'),
 452              ]
 453          );
 454          $query->from($db->quoteName('#__fields_groups'));
 455          $query->whereIn($db->quoteName('state'), [0, 1]);
 456          $query->where($db->quoteName('context') . ' = :context');
 457          $query->whereIn($db->quoteName('access'), $viewlevels);
 458          $query->bind(':context', $context);
 459  
 460          $db->setQuery($query);
 461  
 462          return $db->loadObjectList();
 463      }
 464  }


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