[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/components/com_content/src/Model/ -> ArticleModel.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Site
   5   * @subpackage  com_content
   6   *
   7   * @copyright   (C) 2006 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\Content\Site\Model;
  12  
  13  use Joomla\CMS\Factory;
  14  use Joomla\CMS\Language\Multilanguage;
  15  use Joomla\CMS\Language\Text;
  16  use Joomla\CMS\MVC\Model\ItemModel;
  17  use Joomla\CMS\Table\Table;
  18  use Joomla\Component\Content\Administrator\Extension\ContentComponent;
  19  use Joomla\Database\ParameterType;
  20  use Joomla\Registry\Registry;
  21  use Joomla\Utilities\IpHelper;
  22  
  23  // phpcs:disable PSR1.Files.SideEffects
  24  \defined('_JEXEC') or die;
  25  // phpcs:enable PSR1.Files.SideEffects
  26  
  27  /**
  28   * Content Component Article Model
  29   *
  30   * @since  1.5
  31   */
  32  class ArticleModel extends ItemModel
  33  {
  34      /**
  35       * Model context string.
  36       *
  37       * @var        string
  38       */
  39      protected $_context = 'com_content.article';
  40  
  41      /**
  42       * Method to auto-populate the model state.
  43       *
  44       * Note. Calling getState in this method will result in recursion.
  45       *
  46       * @since   1.6
  47       *
  48       * @return void
  49       */
  50      protected function populateState()
  51      {
  52          $app = Factory::getApplication();
  53  
  54          // Load state from the request.
  55          $pk = $app->input->getInt('id');
  56          $this->setState('article.id', $pk);
  57  
  58          $offset = $app->input->getUint('limitstart');
  59          $this->setState('list.offset', $offset);
  60  
  61          // Load the parameters.
  62          $params = $app->getParams();
  63          $this->setState('params', $params);
  64  
  65          $user = Factory::getUser();
  66  
  67          // If $pk is set then authorise on complete asset, else on component only
  68          $asset = empty($pk) ? 'com_content' : 'com_content.article.' . $pk;
  69  
  70          if ((!$user->authorise('core.edit.state', $asset)) && (!$user->authorise('core.edit', $asset))) {
  71              $this->setState('filter.published', ContentComponent::CONDITION_PUBLISHED);
  72              $this->setState('filter.archived', ContentComponent::CONDITION_ARCHIVED);
  73          }
  74  
  75          $this->setState('filter.language', Multilanguage::isEnabled());
  76      }
  77  
  78      /**
  79       * Method to get article data.
  80       *
  81       * @param   integer  $pk  The id of the article.
  82       *
  83       * @return  object|boolean  Menu item data object on success, boolean false
  84       */
  85      public function getItem($pk = null)
  86      {
  87          $user = Factory::getUser();
  88  
  89          $pk = (int) ($pk ?: $this->getState('article.id'));
  90  
  91          if ($this->_item === null) {
  92              $this->_item = array();
  93          }
  94  
  95          if (!isset($this->_item[$pk])) {
  96              try {
  97                  $db = $this->getDatabase();
  98                  $query = $db->getQuery(true);
  99  
 100                  $query->select(
 101                      $this->getState(
 102                          'item.select',
 103                          [
 104                              $db->quoteName('a.id'),
 105                              $db->quoteName('a.asset_id'),
 106                              $db->quoteName('a.title'),
 107                              $db->quoteName('a.alias'),
 108                              $db->quoteName('a.introtext'),
 109                              $db->quoteName('a.fulltext'),
 110                              $db->quoteName('a.state'),
 111                              $db->quoteName('a.catid'),
 112                              $db->quoteName('a.created'),
 113                              $db->quoteName('a.created_by'),
 114                              $db->quoteName('a.created_by_alias'),
 115                              $db->quoteName('a.modified'),
 116                              $db->quoteName('a.modified_by'),
 117                              $db->quoteName('a.checked_out'),
 118                              $db->quoteName('a.checked_out_time'),
 119                              $db->quoteName('a.publish_up'),
 120                              $db->quoteName('a.publish_down'),
 121                              $db->quoteName('a.images'),
 122                              $db->quoteName('a.urls'),
 123                              $db->quoteName('a.attribs'),
 124                              $db->quoteName('a.version'),
 125                              $db->quoteName('a.ordering'),
 126                              $db->quoteName('a.metakey'),
 127                              $db->quoteName('a.metadesc'),
 128                              $db->quoteName('a.access'),
 129                              $db->quoteName('a.hits'),
 130                              $db->quoteName('a.metadata'),
 131                              $db->quoteName('a.featured'),
 132                              $db->quoteName('a.language'),
 133                          ]
 134                      )
 135                  )
 136                      ->select(
 137                          [
 138                              $db->quoteName('fp.featured_up'),
 139                              $db->quoteName('fp.featured_down'),
 140                              $db->quoteName('c.title', 'category_title'),
 141                              $db->quoteName('c.alias', 'category_alias'),
 142                              $db->quoteName('c.access', 'category_access'),
 143                              $db->quoteName('c.language', 'category_language'),
 144                              $db->quoteName('fp.ordering'),
 145                              $db->quoteName('u.name', 'author'),
 146                              $db->quoteName('parent.title', 'parent_title'),
 147                              $db->quoteName('parent.id', 'parent_id'),
 148                              $db->quoteName('parent.path', 'parent_route'),
 149                              $db->quoteName('parent.alias', 'parent_alias'),
 150                              $db->quoteName('parent.language', 'parent_language'),
 151                              'ROUND(' . $db->quoteName('v.rating_sum') . ' / ' . $db->quoteName('v.rating_count') . ', 1) AS '
 152                                  . $db->quoteName('rating'),
 153                              $db->quoteName('v.rating_count', 'rating_count'),
 154                          ]
 155                      )
 156                      ->from($db->quoteName('#__content', 'a'))
 157                      ->join(
 158                          'INNER',
 159                          $db->quoteName('#__categories', 'c'),
 160                          $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid')
 161                      )
 162                      ->join('LEFT', $db->quoteName('#__content_frontpage', 'fp'), $db->quoteName('fp.content_id') . ' = ' . $db->quoteName('a.id'))
 163                      ->join('LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('a.created_by'))
 164                      ->join('LEFT', $db->quoteName('#__categories', 'parent'), $db->quoteName('parent.id') . ' = ' . $db->quoteName('c.parent_id'))
 165                      ->join('LEFT', $db->quoteName('#__content_rating', 'v'), $db->quoteName('a.id') . ' = ' . $db->quoteName('v.content_id'))
 166                      ->where(
 167                          [
 168                              $db->quoteName('a.id') . ' = :pk',
 169                              $db->quoteName('c.published') . ' > 0',
 170                          ]
 171                      )
 172                      ->bind(':pk', $pk, ParameterType::INTEGER);
 173  
 174                  // Filter by language
 175                  if ($this->getState('filter.language')) {
 176                      $query->whereIn($db->quoteName('a.language'), [Factory::getLanguage()->getTag(), '*'], ParameterType::STRING);
 177                  }
 178  
 179                  if (
 180                      !$user->authorise('core.edit.state', 'com_content.article.' . $pk)
 181                      && !$user->authorise('core.edit', 'com_content.article.' . $pk)
 182                  ) {
 183                      // Filter by start and end dates.
 184                      $nowDate = Factory::getDate()->toSql();
 185  
 186                      $query->extendWhere(
 187                          'AND',
 188                          [
 189                              $db->quoteName('a.publish_up') . ' IS NULL',
 190                              $db->quoteName('a.publish_up') . ' <= :publishUp',
 191                          ],
 192                          'OR'
 193                      )
 194                          ->extendWhere(
 195                              'AND',
 196                              [
 197                                  $db->quoteName('a.publish_down') . ' IS NULL',
 198                                  $db->quoteName('a.publish_down') . ' >= :publishDown',
 199                              ],
 200                              'OR'
 201                          )
 202                          ->bind([':publishUp', ':publishDown'], $nowDate);
 203                  }
 204  
 205                  // Filter by published state.
 206                  $published = $this->getState('filter.published');
 207                  $archived = $this->getState('filter.archived');
 208  
 209                  if (is_numeric($published)) {
 210                      $query->whereIn($db->quoteName('a.state'), [(int) $published, (int) $archived]);
 211                  }
 212  
 213                  $db->setQuery($query);
 214  
 215                  $data = $db->loadObject();
 216  
 217                  if (empty($data)) {
 218                      throw new \Exception(Text::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'), 404);
 219                  }
 220  
 221                  // Check for published state if filter set.
 222                  if ((is_numeric($published) || is_numeric($archived)) && ($data->state != $published && $data->state != $archived)) {
 223                      throw new \Exception(Text::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'), 404);
 224                  }
 225  
 226                  // Convert parameter fields to objects.
 227                  $registry = new Registry($data->attribs);
 228  
 229                  $data->params = clone $this->getState('params');
 230                  $data->params->merge($registry);
 231  
 232                  $data->metadata = new Registry($data->metadata);
 233  
 234                  // Technically guest could edit an article, but lets not check that to improve performance a little.
 235                  if (!$user->get('guest')) {
 236                      $userId = $user->get('id');
 237                      $asset = 'com_content.article.' . $data->id;
 238  
 239                      // Check general edit permission first.
 240                      if ($user->authorise('core.edit', $asset)) {
 241                          $data->params->set('access-edit', true);
 242                      } elseif (!empty($userId) && $user->authorise('core.edit.own', $asset)) {
 243                          // Now check if edit.own is available.
 244                          // Check for a valid user and that they are the owner.
 245                          if ($userId == $data->created_by) {
 246                              $data->params->set('access-edit', true);
 247                          }
 248                      }
 249                  }
 250  
 251                  // Compute view access permissions.
 252                  if ($access = $this->getState('filter.access')) {
 253                      // If the access filter has been set, we already know this user can view.
 254                      $data->params->set('access-view', true);
 255                  } else {
 256                      // If no access filter is set, the layout takes some responsibility for display of limited information.
 257                      $user = Factory::getUser();
 258                      $groups = $user->getAuthorisedViewLevels();
 259  
 260                      if ($data->catid == 0 || $data->category_access === null) {
 261                          $data->params->set('access-view', in_array($data->access, $groups));
 262                      } else {
 263                          $data->params->set('access-view', in_array($data->access, $groups) && in_array($data->category_access, $groups));
 264                      }
 265                  }
 266  
 267                  $this->_item[$pk] = $data;
 268              } catch (\Exception $e) {
 269                  if ($e->getCode() == 404) {
 270                      // Need to go through the error handler to allow Redirect to work.
 271                      throw $e;
 272                  } else {
 273                      $this->setError($e);
 274                      $this->_item[$pk] = false;
 275                  }
 276              }
 277          }
 278  
 279          return $this->_item[$pk];
 280      }
 281  
 282      /**
 283       * Increment the hit counter for the article.
 284       *
 285       * @param   integer  $pk  Optional primary key of the article to increment.
 286       *
 287       * @return  boolean  True if successful; false otherwise and internal error set.
 288       */
 289      public function hit($pk = 0)
 290      {
 291          $input = Factory::getApplication()->input;
 292          $hitcount = $input->getInt('hitcount', 1);
 293  
 294          if ($hitcount) {
 295              $pk = (!empty($pk)) ? $pk : (int) $this->getState('article.id');
 296  
 297              $table = Table::getInstance('Content', 'JTable');
 298              $table->hit($pk);
 299          }
 300  
 301          return true;
 302      }
 303  
 304      /**
 305       * Save user vote on article
 306       *
 307       * @param   integer  $pk    Joomla Article Id
 308       * @param   integer  $rate  Voting rate
 309       *
 310       * @return  boolean          Return true on success
 311       */
 312      public function storeVote($pk = 0, $rate = 0)
 313      {
 314          $pk   = (int) $pk;
 315          $rate = (int) $rate;
 316  
 317          if ($rate >= 1 && $rate <= 5 && $pk > 0) {
 318              $userIP = IpHelper::getIp();
 319  
 320              // Initialize variables.
 321              $db    = $this->getDatabase();
 322              $query = $db->getQuery(true);
 323  
 324              // Create the base select statement.
 325              $query->select('*')
 326                  ->from($db->quoteName('#__content_rating'))
 327                  ->where($db->quoteName('content_id') . ' = :pk')
 328                  ->bind(':pk', $pk, ParameterType::INTEGER);
 329  
 330              // Set the query and load the result.
 331              $db->setQuery($query);
 332  
 333              // Check for a database error.
 334              try {
 335                  $rating = $db->loadObject();
 336              } catch (\RuntimeException $e) {
 337                  Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
 338  
 339                  return false;
 340              }
 341  
 342              // There are no ratings yet, so lets insert our rating
 343              if (!$rating) {
 344                  $query = $db->getQuery(true);
 345  
 346                  // Create the base insert statement.
 347                  $query->insert($db->quoteName('#__content_rating'))
 348                      ->columns(
 349                          [
 350                              $db->quoteName('content_id'),
 351                              $db->quoteName('lastip'),
 352                              $db->quoteName('rating_sum'),
 353                              $db->quoteName('rating_count'),
 354                          ]
 355                      )
 356                      ->values(':pk, :ip, :rate, 1')
 357                      ->bind(':pk', $pk, ParameterType::INTEGER)
 358                      ->bind(':ip', $userIP)
 359                      ->bind(':rate', $rate, ParameterType::INTEGER);
 360  
 361                  // Set the query and execute the insert.
 362                  $db->setQuery($query);
 363  
 364                  try {
 365                      $db->execute();
 366                  } catch (\RuntimeException $e) {
 367                      Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
 368  
 369                      return false;
 370                  }
 371              } else {
 372                  if ($userIP != $rating->lastip) {
 373                      $query = $db->getQuery(true);
 374  
 375                      // Create the base update statement.
 376                      $query->update($db->quoteName('#__content_rating'))
 377                          ->set(
 378                              [
 379                                  $db->quoteName('rating_count') . ' = ' . $db->quoteName('rating_count') . ' + 1',
 380                                  $db->quoteName('rating_sum') . ' = ' . $db->quoteName('rating_sum') . ' + :rate',
 381                                  $db->quoteName('lastip') . ' = :ip',
 382                              ]
 383                          )
 384                          ->where($db->quoteName('content_id') . ' = :pk')
 385                          ->bind(':rate', $rate, ParameterType::INTEGER)
 386                          ->bind(':ip', $userIP)
 387                          ->bind(':pk', $pk, ParameterType::INTEGER);
 388  
 389                      // Set the query and execute the update.
 390                      $db->setQuery($query);
 391  
 392                      try {
 393                          $db->execute();
 394                      } catch (\RuntimeException $e) {
 395                          Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
 396  
 397                          return false;
 398                      }
 399                  } else {
 400                      return false;
 401                  }
 402              }
 403  
 404              $this->cleanCache();
 405  
 406              return true;
 407          }
 408  
 409          Factory::getApplication()->enqueueMessage(Text::sprintf('COM_CONTENT_INVALID_RATING', $rate), 'error');
 410  
 411          return false;
 412      }
 413  
 414      /**
 415       * Cleans the cache of com_content and content modules
 416       *
 417       * @param   string   $group     The cache group
 418       * @param   integer  $clientId  @deprecated   5.0   No longer used.
 419       *
 420       * @return  void
 421       *
 422       * @since   3.9.9
 423       */
 424      protected function cleanCache($group = null, $clientId = 0)
 425      {
 426          parent::cleanCache('com_content');
 427          parent::cleanCache('mod_articles_archive');
 428          parent::cleanCache('mod_articles_categories');
 429          parent::cleanCache('mod_articles_category');
 430          parent::cleanCache('mod_articles_latest');
 431          parent::cleanCache('mod_articles_news');
 432          parent::cleanCache('mod_articles_popular');
 433      }
 434  }


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