[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |