[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/components/com_contact/src/Model/ -> ContactModel.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Site
   5   * @subpackage  com_contact
   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\Contact\Site\Model;
  12  
  13  use Joomla\CMS\Application\SiteApplication;
  14  use Joomla\CMS\Component\ComponentHelper;
  15  use Joomla\CMS\Factory;
  16  use Joomla\CMS\Form\Form;
  17  use Joomla\CMS\Helper\TagsHelper;
  18  use Joomla\CMS\Language\Multilanguage;
  19  use Joomla\CMS\Language\Text;
  20  use Joomla\CMS\MVC\Model\FormModel;
  21  use Joomla\CMS\Plugin\PluginHelper;
  22  use Joomla\Database\ParameterType;
  23  use Joomla\Database\QueryInterface;
  24  use Joomla\Registry\Registry;
  25  
  26  // phpcs:disable PSR1.Files.SideEffects
  27  \defined('_JEXEC') or die;
  28  // phpcs:enable PSR1.Files.SideEffects
  29  
  30  /**
  31   * Single item model for a contact
  32   *
  33   * @package     Joomla.Site
  34   * @subpackage  com_contact
  35   * @since       1.5
  36   */
  37  class ContactModel extends FormModel
  38  {
  39      /**
  40       * The name of the view for a single item
  41       *
  42       * @var    string
  43       * @since  1.6
  44       */
  45      protected $view_item = 'contact';
  46  
  47      /**
  48       * A loaded item
  49       *
  50       * @var    \stdClass
  51       * @since  1.6
  52       */
  53      protected $_item = null;
  54  
  55      /**
  56       * Model context string.
  57       *
  58       * @var     string
  59       */
  60      protected $_context = 'com_contact.contact';
  61  
  62      /**
  63       * Method to auto-populate the model state.
  64       *
  65       * Note. Calling getState in this method will result in recursion.
  66       *
  67       * @return  void
  68       *
  69       * @since   1.6
  70       */
  71      protected function populateState()
  72      {
  73          /** @var SiteApplication $app */
  74          $app = Factory::getContainer()->get(SiteApplication::class);
  75  
  76          if (Factory::getApplication()->isClient('api')) {
  77              // @todo: remove this
  78              $app->loadLanguage();
  79              $this->setState('contact.id', Factory::getApplication()->input->post->getInt('id'));
  80          } else {
  81              $this->setState('contact.id', $app->input->getInt('id'));
  82          }
  83  
  84          $this->setState('params', $app->getParams());
  85  
  86          $user = Factory::getUser();
  87  
  88          if ((!$user->authorise('core.edit.state', 'com_contact')) &&  (!$user->authorise('core.edit', 'com_contact'))) {
  89              $this->setState('filter.published', 1);
  90              $this->setState('filter.archived', 2);
  91          }
  92      }
  93  
  94      /**
  95       * Method to get the contact form.
  96       * The base form is loaded from XML and then an event is fired
  97       *
  98       * @param   array    $data      An optional array of data for the form to interrogate.
  99       * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
 100       *
 101       * @return  Form  A Form object on success, false on failure
 102       *
 103       * @since   1.6
 104       */
 105      public function getForm($data = array(), $loadData = true)
 106      {
 107          $form = $this->loadForm('com_contact.contact', 'contact', array('control' => 'jform', 'load_data' => true));
 108  
 109          if (empty($form)) {
 110              return false;
 111          }
 112  
 113          $temp = clone $this->getState('params');
 114          $contact = $this->_item[$this->getState('contact.id')];
 115          $active = Factory::getContainer()->get(SiteApplication::class)->getMenu()->getActive();
 116  
 117          if ($active) {
 118              // If the current view is the active item and a contact view for this contact, then the menu item params take priority
 119              if (strpos($active->link, 'view=contact') && strpos($active->link, '&id=' . (int) $contact->id)) {
 120                  // $contact->params are the contact params, $temp are the menu item params
 121                  // Merge so that the menu item params take priority
 122                  $contact->params->merge($temp);
 123              } else {
 124                  // Current view is not a single contact, so the contact params take priority here
 125                  // Merge the menu item params with the contact params so that the contact params take priority
 126                  $temp->merge($contact->params);
 127                  $contact->params = $temp;
 128              }
 129          } else {
 130              // Merge so that contact params take priority
 131              $temp->merge($contact->params);
 132              $contact->params = $temp;
 133          }
 134  
 135          if (!$contact->params->get('show_email_copy', 0)) {
 136              $form->removeField('contact_email_copy');
 137          }
 138  
 139          return $form;
 140      }
 141  
 142      /**
 143       * Method to get the data that should be injected in the form.
 144       *
 145       * @return  array    The default data is an empty array.
 146       *
 147       * @since   1.6.2
 148       */
 149      protected function loadFormData()
 150      {
 151          $data = (array) Factory::getApplication()->getUserState('com_contact.contact.data', array());
 152  
 153          if (empty($data['language']) && Multilanguage::isEnabled()) {
 154              $data['language'] = Factory::getLanguage()->getTag();
 155          }
 156  
 157          // Add contact catid to contact form data, so fields plugin can work properly
 158          if (empty($data['catid'])) {
 159              $data['catid'] = $this->getItem()->catid;
 160          }
 161  
 162          $this->preprocessData('com_contact.contact', $data);
 163  
 164          return $data;
 165      }
 166  
 167      /**
 168       * Gets a contact
 169       *
 170       * @param   integer  $pk  Id for the contact
 171       *
 172       * @return  mixed Object or null
 173       *
 174       * @since   1.6.0
 175       */
 176      public function getItem($pk = null)
 177      {
 178          $pk = $pk ?: (int) $this->getState('contact.id');
 179  
 180          if ($this->_item === null) {
 181              $this->_item = array();
 182          }
 183  
 184          if (!isset($this->_item[$pk])) {
 185              try {
 186                  $db    = $this->getDatabase();
 187                  $query = $db->getQuery(true);
 188  
 189                  $query->select($this->getState('item.select', 'a.*'))
 190                      ->select($this->getSlugColumn($query, 'a.id', 'a.alias') . ' AS slug')
 191                      ->select($this->getSlugColumn($query, 'c.id', 'c.alias') . ' AS catslug')
 192                      ->from($db->quoteName('#__contact_details', 'a'))
 193  
 194                      // Join on category table.
 195                      ->select('c.title AS category_title, c.alias AS category_alias, c.access AS category_access')
 196                      ->leftJoin($db->quoteName('#__categories', 'c'), 'c.id = a.catid')
 197  
 198                      // Join over the categories to get parent category titles
 199                      ->select('parent.title AS parent_title, parent.id AS parent_id, parent.path AS parent_route, parent.alias AS parent_alias')
 200                      ->leftJoin($db->quoteName('#__categories', 'parent'), 'parent.id = c.parent_id')
 201                      ->where($db->quoteName('a.id') . ' = :id')
 202                      ->bind(':id', $pk, ParameterType::INTEGER);
 203  
 204                  // Filter by start and end dates.
 205                  $nowDate = Factory::getDate()->toSql();
 206  
 207                  // Filter by published state.
 208                  $published = $this->getState('filter.published');
 209                  $archived = $this->getState('filter.archived');
 210  
 211                  if (is_numeric($published)) {
 212                      $queryString = $db->quoteName('a.published') . ' = :published';
 213  
 214                      if ($archived !== null) {
 215                          $queryString = '(' . $queryString . ' OR ' . $db->quoteName('a.published') . ' = :archived)';
 216                          $query->bind(':archived', $archived, ParameterType::INTEGER);
 217                      }
 218  
 219                      $query->where($queryString)
 220                          ->where('(' . $db->quoteName('a.publish_up') . ' IS NULL OR ' . $db->quoteName('a.publish_up') . ' <= :publish_up)')
 221                          ->where('(' . $db->quoteName('a.publish_down') . ' IS NULL OR ' . $db->quoteName('a.publish_down') . ' >= :publish_down)')
 222                          ->bind(':published', $published, ParameterType::INTEGER)
 223                          ->bind(':publish_up', $nowDate)
 224                          ->bind(':publish_down', $nowDate);
 225                  }
 226  
 227                  $db->setQuery($query);
 228                  $data = $db->loadObject();
 229  
 230                  if (empty($data)) {
 231                      throw new \Exception(Text::_('COM_CONTACT_ERROR_CONTACT_NOT_FOUND'), 404);
 232                  }
 233  
 234                  // Check for published state if filter set.
 235                  if ((is_numeric($published) || is_numeric($archived)) && (($data->published != $published) && ($data->published != $archived))) {
 236                      throw new \Exception(Text::_('COM_CONTACT_ERROR_CONTACT_NOT_FOUND'), 404);
 237                  }
 238  
 239                  /**
 240                   * In case some entity params have been set to "use global", those are
 241                   * represented as an empty string and must be "overridden" by merging
 242                   * the component and / or menu params here.
 243                   */
 244                  $registry = new Registry($data->params);
 245  
 246                  $data->params = clone $this->getState('params');
 247                  $data->params->merge($registry);
 248  
 249                  $registry = new Registry($data->metadata);
 250                  $data->metadata = $registry;
 251  
 252                  // Some contexts may not use tags data at all, so we allow callers to disable loading tag data
 253                  if ($this->getState('load_tags', true)) {
 254                      $data->tags = new TagsHelper();
 255                      $data->tags->getItemTags('com_contact.contact', $data->id);
 256                  }
 257  
 258                  // Compute access permissions.
 259                  if (($access = $this->getState('filter.access'))) {
 260                      // If the access filter has been set, we already know this user can view.
 261                      $data->params->set('access-view', true);
 262                  } else {
 263                      // If no access filter is set, the layout takes some responsibility for display of limited information.
 264                      $user = Factory::getUser();
 265                      $groups = $user->getAuthorisedViewLevels();
 266  
 267                      if ($data->catid == 0 || $data->category_access === null) {
 268                          $data->params->set('access-view', in_array($data->access, $groups));
 269                      } else {
 270                          $data->params->set('access-view', in_array($data->access, $groups) && in_array($data->category_access, $groups));
 271                      }
 272                  }
 273  
 274                  $this->_item[$pk] = $data;
 275              } catch (\Exception $e) {
 276                  if ($e->getCode() == 404) {
 277                      // Need to go through the error handler to allow Redirect to work.
 278                      throw $e;
 279                  } else {
 280                      $this->setError($e);
 281                      $this->_item[$pk] = false;
 282                  }
 283              }
 284          }
 285  
 286          if ($this->_item[$pk]) {
 287              $this->buildContactExtendedData($this->_item[$pk]);
 288          }
 289  
 290          return $this->_item[$pk];
 291      }
 292  
 293      /**
 294       * Load extended data (profile, articles) for a contact
 295       *
 296       * @param   object  $contact  The contact object
 297       *
 298       * @return  void
 299       */
 300      protected function buildContactExtendedData($contact)
 301      {
 302          $db        = $this->getDatabase();
 303          $nowDate   = Factory::getDate()->toSql();
 304          $user      = Factory::getUser();
 305          $groups    = $user->getAuthorisedViewLevels();
 306          $published = $this->getState('filter.published');
 307          $query     = $db->getQuery(true);
 308  
 309          // If we are showing a contact list, then the contact parameters take priority
 310          // So merge the contact parameters with the merged parameters
 311          if ($this->getState('params')->get('show_contact_list')) {
 312              $this->getState('params')->merge($contact->params);
 313          }
 314  
 315          // Get the com_content articles by the linked user
 316          if ((int) $contact->user_id && $this->getState('params')->get('show_articles')) {
 317              $query->select('a.id')
 318                  ->select('a.title')
 319                  ->select('a.state')
 320                  ->select('a.access')
 321                  ->select('a.catid')
 322                  ->select('a.created')
 323                  ->select('a.language')
 324                  ->select('a.publish_up')
 325                  ->select('a.introtext')
 326                  ->select('a.images')
 327                  ->select($this->getSlugColumn($query, 'a.id', 'a.alias') . ' AS slug')
 328                  ->select($this->getSlugColumn($query, 'c.id', 'c.alias') . ' AS catslug')
 329                  ->from($db->quoteName('#__content', 'a'))
 330                  ->leftJoin($db->quoteName('#__categories', 'c') . ' ON a.catid = c.id')
 331                  ->where($db->quoteName('a.created_by') . ' = :created_by')
 332                  ->whereIn($db->quoteName('a.access'), $groups)
 333                  ->bind(':created_by', $contact->user_id, ParameterType::INTEGER)
 334                  ->order('a.publish_up DESC');
 335  
 336              // Filter per language if plugin published
 337              if (Multilanguage::isEnabled()) {
 338                  $language = [Factory::getLanguage()->getTag(), $db->quote('*')];
 339                  $query->whereIn($db->quoteName('a.language'), $language, ParameterType::STRING);
 340              }
 341  
 342              if (is_numeric($published)) {
 343                  $query->where('a.state IN (1,2)')
 344                      ->where('(' . $db->quoteName('a.publish_up') . ' IS NULL' .
 345                          ' OR ' . $db->quoteName('a.publish_up') . ' <= :now1)')
 346                      ->where('(' . $db->quoteName('a.publish_down') . ' IS NULL' .
 347                          ' OR ' . $db->quoteName('a.publish_down') . ' >= :now2)')
 348                      ->bind([':now1', ':now2'], $nowDate);
 349              }
 350  
 351              // Number of articles to display from config/menu params
 352              $articles_display_num = $this->getState('params')->get('articles_display_num', 10);
 353  
 354              // Use contact setting?
 355              if ($articles_display_num === 'use_contact') {
 356                  $articles_display_num = $contact->params->get('articles_display_num', 10);
 357  
 358                  // Use global?
 359                  if ((string) $articles_display_num === '') {
 360                      $articles_display_num = ComponentHelper::getParams('com_contact')->get('articles_display_num', 10);
 361                  }
 362              }
 363  
 364              $query->setLimit((int) $articles_display_num);
 365              $db->setQuery($query);
 366              $contact->articles = $db->loadObjectList();
 367          } else {
 368              $contact->articles = null;
 369          }
 370  
 371          // Get the profile information for the linked user
 372          $userModel = $this->bootComponent('com_users')->getMVCFactory()
 373              ->createModel('User', 'Administrator', ['ignore_request' => true]);
 374          $data = $userModel->getItem((int) $contact->user_id);
 375  
 376          PluginHelper::importPlugin('user');
 377  
 378          // Get the form.
 379          Form::addFormPath(JPATH_SITE . '/components/com_users/forms');
 380  
 381          $form = Form::getInstance('com_users.profile', 'profile');
 382  
 383          // Trigger the form preparation event.
 384          Factory::getApplication()->triggerEvent('onContentPrepareForm', array($form, $data));
 385  
 386          // Trigger the data preparation event.
 387          Factory::getApplication()->triggerEvent('onContentPrepareData', array('com_users.profile', $data));
 388  
 389          // Load the data into the form after the plugins have operated.
 390          $form->bind($data);
 391          $contact->profile = $form;
 392      }
 393  
 394      /**
 395       * Generate column expression for slug or catslug.
 396       *
 397       * @param   QueryInterface  $query  Current query instance.
 398       * @param   string          $id     Column id name.
 399       * @param   string          $alias  Column alias name.
 400       *
 401       * @return  string
 402       *
 403       * @since   4.0.0
 404       */
 405      private function getSlugColumn($query, $id, $alias)
 406      {
 407          return 'CASE WHEN '
 408              . $query->charLength($alias, '!=', '0')
 409              . ' THEN '
 410              . $query->concatenate(array($query->castAsChar($id), $alias), ':')
 411              . ' ELSE '
 412              . $query->castAsChar($id) . ' END';
 413      }
 414  
 415      /**
 416       * Increment the hit counter for the contact.
 417       *
 418       * @param   integer  $pk  Optional primary key of the contact to increment.
 419       *
 420       * @return  boolean  True if successful; false otherwise and internal error set.
 421       *
 422       * @since   3.0
 423       */
 424      public function hit($pk = 0)
 425      {
 426          $input = Factory::getApplication()->input;
 427          $hitcount = $input->getInt('hitcount', 1);
 428  
 429          if ($hitcount) {
 430              $pk = $pk ?: (int) $this->getState('contact.id');
 431  
 432              $table = $this->getTable('Contact');
 433              $table->hit($pk);
 434          }
 435  
 436          return true;
 437      }
 438  }


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