Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/model.zip
Назад
PK �s!]�\��� � model.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework Model class. The Model is the workhorse. It performs all * of the business logic based on its state and then returns the raw (processed) * data to the caller, or modifies its own state. It's important to note that * the model doesn't get data directly from the request (this is the * Controller's business) and that it doesn't output anything (that the View's * business). * * @package FrameworkOnFramework * @since 1.0 */ class F0FModel extends F0FUtilsObject { /** * Indicates if the internal state has been set * * @var boolean * @since 12.2 */ protected $__state_set = null; /** * Database Connector * * @var object * @since 12.2 */ protected $_db; /** * The event to trigger after deleting the data. * @var string */ protected $event_after_delete = 'onContentAfterDelete'; /** * The event to trigger after saving the data. * @var string */ protected $event_after_save = 'onContentAfterSave'; /** * The event to trigger before deleting the data. * @var string */ protected $event_before_delete = 'onContentBeforeDelete'; /** * The event to trigger before saving the data. * @var string */ protected $event_before_save = 'onContentBeforeSave'; /** * The event to trigger after changing the published state of the data. * @var string */ protected $event_change_state = 'onContentChangeState'; /** * The event to trigger when cleaning cache. * * @var string * @since 12.2 */ protected $event_clean_cache = null; /** * Stores a list of IDs passed to the model's state * @var array */ protected $id_list = array(); /** * The first row ID passed to the model's state * @var int */ protected $id = null; /** * Input variables, passed on from the controller, in an associative array * @var F0FInput */ protected $input = array(); /** * The list of records made available through getList * @var array */ protected $list = null; /** * The model (base) name * * @var string * @since 12.2 */ protected $name; /** * The URL option for the component. * * @var string * @since 12.2 */ protected $option = null; /** * The table object, populated when saving data * @var F0FTable */ protected $otable = null; /** * Pagination object * @var JPagination */ protected $pagination = null; /** * The table object, populated when retrieving data * @var F0FTable */ protected $record = null; /** * A state object * * @var string * @since 12.2 */ protected $state; /** * The name of the table to use * @var string */ protected $table = null; /** * Total rows based on the filters set in the model's state * @var int */ protected $total = null; /** * Should I save the model's state in the session? * @var bool */ protected $_savestate = null; /** * Array of form objects. * * @var array * @since 2.0 */ protected $_forms = array(); /** * The data to load into a form * * @var array * @since 2.0 */ protected $_formData = array(); /** * An instance of F0FConfigProvider to provision configuration overrides * * @var F0FConfigProvider */ protected $configProvider = null; /** * F0FModelDispatcherBehavior for dealing with extra behaviors * * @var F0FModelDispatcherBehavior */ protected $modelDispatcher = null; /** * Default behaviors to apply to the model * * @var array */ protected $default_behaviors = array('filters'); /** * Behavior parameters * * @var array */ protected $_behaviorParams = array(); /** * Returns a new model object. Unless overriden by the $config array, it will * try to automatically populate its state from the request variables. * * @param string $type Model type, e.g. 'Items' * @param string $prefix Model prefix, e.g. 'FoobarModel' * @param array $config Model configuration variables * * @return F0FModel */ public static function &getAnInstance($type, $prefix = '', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } $type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type); $modelClass = $prefix . ucfirst($type); $result = false; // Guess the component name and include path if (!empty($prefix)) { preg_match('/(.*)Model$/', $prefix, $m); $component = 'com_' . strtolower($m[1]); } else { $component = ''; } if (array_key_exists('input', $config)) { if (!($config['input'] instanceof F0FInput)) { if (!is_array($config['input'])) { $config['input'] = (array) $config['input']; } $config['input'] = array_merge($_REQUEST, $config['input']); $config['input'] = new F0FInput($config['input']); } } else { $config['input'] = new F0FInput; } if (empty($component)) { $component = $config['input']->get('option', 'com_foobar'); } $config['option'] = $component; $needsAView = true; if (array_key_exists('view', $config)) { if (!empty($config['view'])) { $needsAView = false; } } if ($needsAView) { $config['view'] = strtolower($type); } $config['input']->set('option', $config['option']); // Get the component directories $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component); $filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem'); // Try to load the requested model class if (!class_exists($modelClass)) { $include_paths = self::addIncludePath(); $extra_paths = array( $componentPaths['main'] . '/models', $componentPaths['alt'] . '/models' ); $include_paths = array_merge($extra_paths, $include_paths); // Try to load the model file $path = $filesystem->pathFind( $include_paths, self::_createFileName('model', array('name' => $type)) ); if ($path) { require_once $path; } } // Fallback to the Default model class, e.g. FoobarModelDefault if (!class_exists($modelClass)) { $modelClass = $prefix . 'Default'; if (!class_exists($modelClass)) { $include_paths = self::addIncludePath(); $extra_paths = array( $componentPaths['main'] . '/models', $componentPaths['alt'] . '/models' ); $include_paths = array_merge($extra_paths, $include_paths); // Try to load the model file $path = $filesystem->pathFind( $include_paths, self::_createFileName('model', array('name' => 'default')) ); if ($path) { require_once $path; } } } // Fallback to the generic F0FModel model class if (!class_exists($modelClass)) { $modelClass = 'F0FModel'; } $result = new $modelClass($config); return $result; } /** * Adds a behavior to the model * * @param string $name The name of the behavior * @param array $config Optional Behavior configuration * * @return boolean True if the behavior is found and added */ public function addBehavior($name, $config = array()) { // Sanity check: this objects needs a non-null behavior handler if (!is_object($this->modelDispatcher)) { return false; } // Sanity check: this objects needs a behavior handler of the correct class type if (!($this->modelDispatcher instanceof F0FModelDispatcherBehavior)) { return false; } // First look for ComponentnameModelViewnameBehaviorName (e.g. FoobarModelItemsBehaviorFilter) $option_name = str_replace('com_', '', $this->option); $behaviorClass = ucfirst($option_name) . 'Model' . F0FInflector::pluralize($this->name) . 'Behavior' . ucfirst(strtolower($name)); if (class_exists($behaviorClass)) { $behavior = new $behaviorClass($this->modelDispatcher, $config); return true; } // Then look for ComponentnameModelBehaviorName (e.g. FoobarModelBehaviorFilter) $option_name = str_replace('com_', '', $this->option); $behaviorClass = ucfirst($option_name) . 'ModelBehavior' . ucfirst(strtolower($name)); if (class_exists($behaviorClass)) { $behavior = new $behaviorClass($this->modelDispatcher, $config); return true; } // Then look for F0FModelBehaviorName (e.g. F0FModelBehaviorFilter) $behaviorClassAlt = 'F0FModelBehavior' . ucfirst(strtolower($name)); if (class_exists($behaviorClassAlt)) { $behavior = new $behaviorClassAlt($this->modelDispatcher, $config); return true; } // Nothing found? Return false. return false; } /** * Returns a new instance of a model, with the state reset to defaults * * @param string $type Model type, e.g. 'Items' * @param string $prefix Model prefix, e.g. 'FoobarModel' * @param array $config Model configuration variables * * @return F0FModel */ public static function &getTmpInstance($type, $prefix = '', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } if (!array_key_exists('savestate', $config)) { $config['savestate'] = false; } $ret = self::getAnInstance($type, $prefix, $config) ->getClone() ->clearState() ->clearInput() ->reset() ->savestate(0) ->limitstart(0) ->limit(0); return $ret; } /** * Add a directory where F0FModel should search for models. You may * either pass a string or an array of directories. * * @param mixed $path A path or array[sting] of paths to search. * @param string $prefix A prefix for models. * * @return array An array with directory elements. If prefix is equal to '', all directories are returned. * * @since 12.2 */ public static function addIncludePath($path = '', $prefix = '') { static $paths; if (!isset($paths)) { $paths = array(); } if (!isset($paths[$prefix])) { $paths[$prefix] = array(); } if (!isset($paths[''])) { $paths[''] = array(); } if (!empty($path)) { $filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem'); if (!in_array($path, $paths[$prefix])) { array_unshift($paths[$prefix], $filesystem->pathClean($path)); } if (!in_array($path, $paths[''])) { array_unshift($paths[''], $filesystem->pathClean($path)); } } return $paths[$prefix]; } /** * Adds to the stack of model table paths in LIFO order. * * @param mixed $path The directory as a string or directories as an array to add. * * @return void * * @since 12.2 */ public static function addTablePath($path) { F0FTable::addIncludePath($path); } /** * Create the filename for a resource * * @param string $type The resource type to create the filename for. * @param array $parts An associative array of filename information. * * @return string The filename * * @since 12.2 */ protected static function _createFileName($type, $parts = array()) { $filename = ''; switch ($type) { case 'model': $filename = strtolower($parts['name']) . '.php'; break; } return $filename; } /** * Public class constructor * * @param array $config The configuration array */ public function __construct($config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } // Get the input if (array_key_exists('input', $config)) { if ($config['input'] instanceof F0FInput) { $this->input = $config['input']; } else { $this->input = new F0FInput($config['input']); } } else { $this->input = new F0FInput; } // Load the configuration provider $this->configProvider = new F0FConfigProvider; // Load the behavior dispatcher $this->modelDispatcher = new F0FModelDispatcherBehavior; // Set the $name/$_name variable $component = $this->input->getCmd('option', 'com_foobar'); if (array_key_exists('option', $config)) { $component = $config['option']; } // Set the $name variable $this->input->set('option', $component); $component = $this->input->getCmd('option', 'com_foobar'); if (array_key_exists('option', $config)) { $component = $config['option']; } $this->input->set('option', $component); $bareComponent = str_replace('com_', '', strtolower($component)); // Get the view name $className = get_class($this); if ($className == 'F0FModel') { if (array_key_exists('view', $config)) { $view = $config['view']; } if (empty($view)) { $view = $this->input->getCmd('view', 'cpanel'); } } else { if (array_key_exists('view', $config)) { $view = $config['view']; } if (empty($view)) { $eliminatePart = ucfirst($bareComponent) . 'Model'; $view = strtolower(str_replace($eliminatePart, '', $className)); } } if (array_key_exists('name', $config)) { $name = $config['name']; } else { $name = $view; } $this->name = $name; $this->option = $component; // Set the model state if (array_key_exists('state', $config)) { $this->state = $config['state']; } else { $this->state = new F0FUtilsObject; } // Set the model dbo if (array_key_exists('dbo', $config)) { $this->_db = $config['dbo']; } else { $this->_db = F0FPlatform::getInstance()->getDbo(); } // Set the default view search path if (array_key_exists('table_path', $config)) { $this->addTablePath($config['table_path']); } else { $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($this->option); $path = $componentPaths['admin'] . '/tables'; $altPath = $this->configProvider->get($this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.table_path', null); if ($altPath) { $path = $componentPaths['main'] . '/' . $altPath; } $this->addTablePath($path); } // Assign the correct table if (array_key_exists('table', $config)) { $this->table = $config['table']; } else { $table = $this->configProvider->get( $this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.table', F0FInflector::singularize($view) ); $this->table = $table; } // Set the internal state marker - used to ignore setting state from the request if (!empty($config['ignore_request']) || !is_null( $this->configProvider->get( $this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.ignore_request', null ) )) { $this->__state_set = true; } // Get and store the pagination request variables $defaultSaveState = array_key_exists('savestate', $config) ? $config['savestate'] : -999; $this->populateSavestate($defaultSaveState); if (F0FPlatform::getInstance()->isCli()) { $limit = 20; $limitstart = 0; } else { $app = JFactory::getApplication(); if (method_exists($app, 'getCfg')) { $default_limit = $app->getCfg('list_limit'); } else { $default_limit = 20; } $limit = $this->getUserStateFromRequest($component . '.' . $view . '.limit', 'limit', $default_limit, 'int', $this->_savestate); $limitstart = $this->getUserStateFromRequest($component . '.' . $view . '.limitstart', 'limitstart', 0, 'int', $this->_savestate); } $this->setState('limit', $limit); $this->setState('limitstart', $limitstart); // Get the ID or list of IDs from the request or the configuration if (array_key_exists('cid', $config)) { $cid = $config['cid']; } elseif ($cid = $this->configProvider->get( $this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.cid', null ) ) { $cid = explode(',', $cid); } else { $cid = $this->input->get('cid', array(), 'array'); } if (array_key_exists('id', $config)) { $id = $config['id']; } elseif ($id = $this->configProvider->get( $this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.id', null ) ) { $id = explode(',', $id); $id = array_shift($id); } else { $id = $this->input->getInt('id', 0); } if (is_array($cid) && !empty($cid)) { $this->setIds($cid); } else { $this->setId($id); } // Populate the event names from the $config array $configKey = $this->option . '.views.' . F0FInflector::singularize($view) . '.config.'; // Assign after delete event handler if (isset($config['event_after_delete'])) { $this->event_after_delete = $config['event_after_delete']; } else { $this->event_after_delete = $this->configProvider->get( $configKey . 'event_after_delete', $this->event_after_delete ); } // Assign after save event handler if (isset($config['event_after_save'])) { $this->event_after_save = $config['event_after_save']; } else { $this->event_after_save = $this->configProvider->get( $configKey . 'event_after_save', $this->event_after_save ); } // Assign before delete event handler if (isset($config['event_before_delete'])) { $this->event_before_delete = $config['event_before_delete']; } else { $this->event_before_delete = $this->configProvider->get( $configKey . 'event_before_delete', $this->event_before_delete ); } // Assign before save event handler if (isset($config['event_before_save'])) { $this->event_before_save = $config['event_before_save']; } else { $this->event_before_save = $this->configProvider->get( $configKey . 'event_before_save', $this->event_before_save ); } // Assign state change event handler if (isset($config['event_change_state'])) { $this->event_change_state = $config['event_change_state']; } else { $this->event_change_state = $this->configProvider->get( $configKey . 'event_change_state', $this->event_change_state ); } // Assign cache clean event handler if (isset($config['event_clean_cache'])) { $this->event_clean_cache = $config['event_clean_cache']; } else { $this->event_clean_cache = $this->configProvider->get( $configKey . 'event_clean_cache', $this->event_clean_cache ); } // Apply model behaviors if (isset($config['behaviors'])) { $behaviors = (array) $config['behaviors']; } elseif ($behaviors = $this->configProvider->get($configKey . 'behaviors', null)) { $behaviors = explode(',', $behaviors); } else { $behaviors = $this->default_behaviors; } if (is_array($behaviors) && count($behaviors)) { foreach ($behaviors as $behavior) { $this->addBehavior($behavior); } } } /** * Sets the list of IDs from the request data * * @return F0FModel */ public function setIDsFromRequest() { // Get the ID or list of IDs from the request or the configuration $cid = $this->input->get('cid', array(), 'array'); $id = $this->input->getInt('id', 0); $kid = $this->input->getInt($this->getTable($this->table)->getKeyName(), 0); if (is_array($cid) && !empty($cid)) { $this->setIds($cid); } else { if (empty($id)) { $this->setId($kid); } else { $this->setId($id); } } return $this; } /** * Sets the ID and resets internal data * * @param integer $id The ID to use * * @throws InvalidArgumentException * * @return F0FModel */ public function setId($id = 0) { // If this is an array extract the first item if (is_array($id)) { F0FPlatform::getInstance()->logDeprecated('Passing arrays to F0FModel::setId is deprecated. Use setIds() instead.'); $id = array_shift($id); } // No string or no integer? What are you trying to do??? if (!is_string($id) && !is_numeric($id)) { throw new InvalidArgumentException(sprintf('%s::setId()', get_class($this))); } $this->reset(); $this->id = (int) $id; $this->id_list = array($this->id); return $this; } /** * Returns the currently set ID * * @return integer */ public function getId() { return $this->id; } /** * Sets a list of IDs for batch operations from an array and resets the model * * @param array $idlist An array of item IDs to be set to the model's state * * @return F0FModel */ public function setIds($idlist) { $this->reset(); $this->id_list = array(); $this->id = 0; if (is_array($idlist) && !empty($idlist)) { foreach ($idlist as $value) { // Protect vs fatal error (objects) and wrong behavior (nested array) if(!is_object($value) && !is_array($value)) { $this->id_list[] = (int) $value; } } if(count($this->id_list)) { $this->id = $this->id_list[0]; } } return $this; } /** * Returns the list of IDs for batch operations * * @return array An array of integers */ public function getIds() { return $this->id_list; } /** * Resets the model, like it was freshly loaded * * @return F0FModel */ public function reset() { $this->id = 0; $this->id_list = null; $this->record = null; $this->list = null; $this->pagination = null; $this->total = null; $this->otable = null; return $this; } /** * Clears the model state, but doesn't touch the internal lists of records, * record tables or record id variables. To clear these values, please use * reset(). * * @return F0FModel */ public function clearState() { $this->state = new F0FUtilsObject; return $this; } /** * Clears the input array. * * @return F0FModel */ public function clearInput() { $defSource = array(); $this->input = new F0FInput($defSource); return $this; } /** * Set the internal input field * * @param $input * * @return F0FModel */ public function setInput($input) { if (!($input instanceof F0FInput)) { if (!is_array($input)) { $input = (array) $input; } $input = array_merge($_REQUEST, $input); $input = new F0FInput($input); } $this->input = $input; return $this; } /** * Resets the saved state for this view * * @return F0FModel */ public function resetSavedState() { JFactory::getApplication()->setUserState(substr($this->getHash(), 0, -1), null); return $this; } /** * Method to load a row for editing from the version history table. * * @param integer $version_id Key to the version history table. * @param F0FTable &$table Content table object being loaded. * @param string $alias The type_alias in #__content_types * * @return boolean False on failure or error, true otherwise. * * @since 2.3 */ public function loadhistory($version_id, F0FTable &$table, $alias) { // Only attempt to check the row in if it exists. if ($version_id) { $user = JFactory::getUser(); // Get an instance of the row to checkout. $historyTable = JTable::getInstance('Contenthistory'); if (!$historyTable->load($version_id)) { $this->setError($historyTable->getError()); return false; } $rowArray = JArrayHelper::fromObject(json_decode($historyTable->version_data)); $typeId = JTable::getInstance('Contenttype')->getTypeId($alias); if ($historyTable->ucm_type_id != $typeId) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_HISTORY_ID_MISMATCH')); $key = $table->getKeyName(); if (isset($rowArray[$key])) { $table->checkIn($rowArray[$key]); } return false; } } $this->setState('save_date', $historyTable->save_date); $this->setState('version_note', $historyTable->version_note); return $table->bind($rowArray); } /** * Returns a single item. It uses the id set with setId, or the first ID in * the list of IDs for batch operations * * @param integer $id Force a primary key ID to the model. Use null to use the id from the state. * * @return F0FTable A copy of the item's F0FTable array */ public function &getItem($id = null) { if (!is_null($id)) { $this->record = null; $this->setId($id); } if (empty($this->record)) { $table = $this->getTable($this->table); $table->load($this->id); $this->record = $table; // Do we have saved data? $session = JFactory::getSession(); if ($this->_savestate) { $serialized = $session->get($this->getHash() . 'savedata', null); if (!empty($serialized)) { $data = @unserialize($serialized); if ($data !== false) { $k = $table->getKeyName(); if (!array_key_exists($k, $data)) { $data[$k] = null; } if ($data[$k] != $this->id) { $session->set($this->getHash() . 'savedata', null); } else { $this->record->bind($data); } } } } $this->onAfterGetItem($this->record); } return $this->record; } /** * Alias for getItemList * * @param boolean $overrideLimits Should I override set limits? * @param string $group The group by clause * @codeCoverageIgnore * * @return array */ public function &getList($overrideLimits = false, $group = '') { return $this->getItemList($overrideLimits, $group); } /** * Returns a list of items * * @param boolean $overrideLimits Should I override set limits? * @param string $group The group by clause * * @return array */ public function &getItemList($overrideLimits = false, $group = '') { if (empty($this->list)) { $query = $this->buildQuery($overrideLimits); if (!$overrideLimits) { $limitstart = $this->getState('limitstart'); $limit = $this->getState('limit'); $this->list = $this->_getList((string) $query, $limitstart, $limit, $group); } else { $this->list = $this->_getList((string) $query, 0, 0, $group); } } return $this->list; } /** * Returns a F0FDatabaseIterator over a list of items. * * THERE BE DRAGONS. Unlike the getItemList() you have a few restrictions: * - The onProcessList event does not run when you get an iterator * - The Iterator returns F0FTable instances. By default, $this->table is used. If you have JOINs, GROUPs or a * complex query in general you will need to create a custom F0FTable subclass and pass its type in $tableType. * * The getIterator() method is a great way to sift through a large amount of records which would otherwise not fit * in memory since it only keeps one record in PHP memory at a time. It works best with simple models, returning * all the contents of a single database table. * * @param boolean $overrideLimits Should I ignore set limits? * @param string $tableClass The table class for the iterator, e.g. FoobarTableBar. Leave empty to use * the default Table class for this Model. * * @return F0FDatabaseIterator */ public function &getIterator($overrideLimits = false, $tableClass = null) { // Get the table name (required by the Iterator) if (empty($tableClass)) { $name = $this->table; if (empty($name)) { $name = F0FInflector::singularize($this->getName()); } $bareComponent = str_replace('com_', '', $this->option); $prefix = ucfirst($bareComponent) . 'Table'; $tableClass = $prefix . ucfirst($name); } // Get the query $query = $this->buildQuery($overrideLimits); // Apply limits if ($overrideLimits) { $limitStart = 0; $limit = 0; } else { $limitStart = $this->getState('limitstart'); $limit = $this->getState('limit'); } // This is required to prevent one relation from killing the db cursor used in a different relation... $oldDb = $this->getDbo(); $oldDb->disconnect(); // YES, WE DO NEED TO DISCONNECT BEFORE WE CLONE THE DB OBJECT. ARGH! $db = clone $oldDb; // Execute the query, get a db cursor and return the iterator $db->setQuery($query, $limitStart, $limit); $cursor = $db->execute(); $iterator = F0FDatabaseIterator::getIterator($db->name, $cursor, null, $tableClass); return $iterator; } /** * A cross-breed between getItem and getItemList. It runs the complete query, * like getItemList does. However, instead of returning an array of ad-hoc * objects, it binds the data from the first item fetched on the list to an * instance of the table object and returns that table object instead. * * @param boolean $overrideLimits Should I override set limits? * * @return F0FTable */ public function &getFirstItem($overrideLimits = false) { /** * We have to clone the instance, or when multiple getFirstItem calls occur, * we'll update EVERY instance created */ $table = clone $this->getTable($this->table); $list = $this->getItemList($overrideLimits); if (!empty($list)) { $firstItem = array_shift($list); $table->bind($firstItem); } unset($list); return $table; } /** * Binds the data to the model and tries to save it * * @param array|object $data The source data array or object * * @return boolean True on success */ public function save($data) { $this->otable = null; $table = $this->getTable($this->table); if (is_object($data)) { $data = clone($data); } $key = $table->getKeyName(); if (array_key_exists($key, (array) $data)) { $aData = (array) $data; $oid = $aData[$key]; $table->load($oid); } if ($data instanceof F0FTable) { $allData = $data->getData(); } elseif (is_object($data)) { $allData = (array) $data; } else { $allData = $data; } // Get the form if there is any $form = $this->getForm($allData, false); if ($form instanceof F0FForm) { // Make sure that $allData has for any field a key $fieldset = $form->getFieldset(); foreach ($fieldset as $nfield => $fldset) { if (!array_key_exists($nfield, $allData)) { $field = $form->getField($fldset->fieldname, $fldset->group); $type = strtolower($field->type); switch ($type) { case 'checkbox': $allData[$nfield] = 0; break; default: $allData[$nfield] = ''; break; } } } $serverside_validate = strtolower($form->getAttribute('serverside_validate')); $validateResult = true; if (in_array($serverside_validate, array('true', 'yes', '1', 'on'))) { $validateResult = $this->validateForm($form, $allData); } if ($validateResult === false) { if ($this->_savestate) { $session = JFactory::getSession(); $hash = $this->getHash() . 'savedata'; $session->set($hash, serialize($allData)); } return false; } } if (!$this->onBeforeSave($allData, $table)) { if ($this->_savestate) { $session = JFactory::getSession(); $hash = $this->getHash() . 'savedata'; $session->set($hash, serialize($allData)); } return false; } else { // If onBeforeSave successful, refetch the possibly modified data if ($data instanceof F0FTable) { $data->bind($allData); } elseif (is_object($data)) { $data = (object) $allData; } else { $data = $allData; } } if (!$table->save($data)) { foreach ($table->getErrors() as $error) { if (!empty($error)) { $this->setError($error); $session = JFactory::getSession(); $tableprops = $table->getProperties(true); unset($tableprops['input']); unset($tableprops['config']['input']); unset($tableprops['config']['db']); unset($tableprops['config']['dbo']); if ($this->_savestate) { $hash = $this->getHash() . 'savedata'; $session->set($hash, serialize($tableprops)); } } } return false; } else { $this->id = $table->$key; // Remove the session data if ($this->_savestate) { JFactory::getSession()->set($this->getHash() . 'savedata', null); } } $this->onAfterSave($table); $this->otable = $table; return true; } /** * Copy one or more records * * @return boolean True on success */ public function copy() { if (is_array($this->id_list) && !empty($this->id_list)) { $table = $this->getTable($this->table); if (!$this->onBeforeCopy($table)) { return false; } if (!$table->copy($this->id_list)) { $this->setError($table->getError()); return false; } else { // Call our internal event $this->onAfterCopy($table); // @todo Should we fire the content plugin? } } return true; } /** * Returns the table object after the last save() operation * * @return F0FTable */ public function getSavedTable() { return $this->otable; } /** * Deletes one or several items * * @return boolean True on success */ public function delete() { if (is_array($this->id_list) && !empty($this->id_list)) { $table = $this->getTable($this->table); foreach ($this->id_list as $id) { if (!$this->onBeforeDelete($id, $table)) { continue; } if (!$table->delete($id)) { $this->setError($table->getError()); return false; } else { $this->onAfterDelete($id); } } } return true; } /** * Toggles the published state of one or several items * * @param integer $publish The publishing state to set (e.g. 0 is unpublished) * @param integer $user The user ID performing this action * * @return boolean True on success */ public function publish($publish = 1, $user = null) { if (is_array($this->id_list) && !empty($this->id_list)) { if (empty($user)) { $oUser = F0FPlatform::getInstance()->getUser(); $user = $oUser->id; } $table = $this->getTable($this->table); if (!$this->onBeforePublish($table)) { return false; } if (!$table->publish($this->id_list, $publish, $user)) { $this->setError($table->getError()); return false; } else { // Call our internal event $this->onAfterPublish($table); // Call the plugin events F0FPlatform::getInstance()->importPlugin('content'); $name = $this->name; $context = $this->option . '.' . $name; // @TODO should we do anything with this return value? $result = F0FPlatform::getInstance()->runPlugins($this->event_change_state, array($context, $this->id_list, $publish)); } } return true; } /** * Checks out the current item * * @return boolean */ public function checkout() { $table = $this->getTable($this->table); $status = $table->checkout(F0FPlatform::getInstance()->getUser()->id, $this->id); if (!$status) { $this->setError($table->getError()); } return $status; } /** * Checks in the current item * * @return boolean */ public function checkin() { $table = $this->getTable($this->table); $status = $table->checkin($this->id); if (!$status) { $this->setError($table->getError()); } return $status; } /** * Tells you if the current item is checked out or not * * @return boolean */ public function isCheckedOut() { $table = $this->getTable($this->table); $status = $table->isCheckedOut($this->id); if (!$status) { $this->setError($table->getError()); } return $status; } /** * Increments the hit counter * * @return boolean */ public function hit() { $table = $this->getTable($this->table); if (!$this->onBeforeHit($table)) { return false; } $status = $table->hit($this->id); if (!$status) { $this->setError($table->getError()); } else { $this->onAfterHit($table); } return $status; } /** * Moves the current item up or down in the ordering list * * @param string $dirn The direction and magnitude to use (2 means move up by 2 positions, -3 means move down three positions) * * @return boolean True on success */ public function move($dirn) { $table = $this->getTable($this->table); $id = $this->getId(); $status = $table->load($id); if (!$status) { $this->setError($table->getError()); } if (!$status) { return false; } if (!$this->onBeforeMove($table)) { return false; } $status = $table->move($dirn); if (!$status) { $this->setError($table->getError()); } else { $this->onAfterMove($table); } return $status; } /** * Reorders all items in the table * * @return boolean */ public function reorder() { $table = $this->getTable($this->table); if (!$this->onBeforeReorder($table)) { return false; } $status = $table->reorder($this->getReorderWhere()); if (!$status) { $this->setError($table->getError()); } else { if (!$this->onAfterReorder($table)) { return false; } } return $status; } /** * Get a pagination object * * @return JPagination */ public function getPagination() { if (empty($this->pagination)) { // Import the pagination library JLoader::import('joomla.html.pagination'); // Prepare pagination values $total = $this->getTotal(); $limitstart = $this->getState('limitstart'); $limit = $this->getState('limit'); // Create the pagination object $this->pagination = new JPagination($total, $limitstart, $limit); } return $this->pagination; } /** * Get the number of all items * * @return integer */ public function getTotal() { if (is_null($this->total)) { $query = $this->buildCountQuery(); if ($query === false) { $subquery = $this->buildQuery(false); $subquery->clear('order'); $query = $this->_db->getQuery(true) ->select('COUNT(*)') ->from("(" . (string) $subquery . ") AS a"); } $this->_db->setQuery((string) $query); $this->total = $this->_db->loadResult(); } return $this->total; } /** * Returns a record count for the query * * @param string $query The query. * * @return integer Number of rows for query * * @since 12.2 */ protected function _getListCount($query) { return $this->getTotal(); } /** * Get a filtered state variable * * @param string $key The name of the state variable * @param mixed $default The default value to use * @param string $filter_type Filter type * * @return mixed The variable's value */ public function getState($key = null, $default = null, $filter_type = 'raw') { if (empty($key)) { return $this->_real_getState(); } // Get the savestate status $value = $this->_real_getState($key); if (is_null($value)) { $value = $this->getUserStateFromRequest($this->getHash() . $key, $key, $value, 'none', $this->_savestate); if (is_null($value)) { return $default; } } if (strtoupper($filter_type) == 'RAW') { return $value; } else { JLoader::import('joomla.filter.filterinput'); $filter = new JFilterInput; return $filter->clean($value, $filter_type); } } /** * Method to get model state variables * * @param string $property Optional parameter name * @param mixed $default Optional default value * * @return object The property where specified, the state object where omitted * * @since 12.2 */ protected function _real_getState($property = null, $default = null) { if (!$this->__state_set) { // Protected method to auto-populate the model state. $this->populateState(); // Set the model state set flag to true. $this->__state_set = true; } return $property === null ? $this->state : $this->state->get($property, $default); } /** * Returns a hash for this component and view, e.g. "foobar.items.", used * for determining the keys of the variables which will be placed in the * session storage. * * @return string The hash */ public function getHash() { $option = $this->input->getCmd('option', 'com_foobar'); $view = F0FInflector::pluralize($this->input->getCmd('view', 'cpanel')); return "$option.$view."; } /** * Gets the value of a user state variable. * * @param string $key The key of the user state variable. * @param string $request The name of the variable passed in a request. * @param string $default The default value for the variable if not found. Optional. * @param string $type Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional. * @param boolean $setUserState Should I save the variable in the user state? Default: true. Optional. * * @return string The request user state. */ protected function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $setUserState = true) { return F0FPlatform::getInstance()->getUserStateFromRequest($key, $request, $this->input, $default, $type, $setUserState); } /** * Returns an object list * * @param string $query The query * @param integer $limitstart Offset from start * @param integer $limit The number of records * @param string $group The group by clause * * @return array Array of objects */ protected function &_getList($query, $limitstart = 0, $limit = 0, $group = '') { $this->_db->setQuery($query, $limitstart, $limit); $result = $this->_db->loadObjectList($group); $this->onProcessList($result); return $result; } /** * Method to get a table object, load it if necessary. * * @param string $name The table name. Optional. * @param string $prefix The class prefix. Optional. * @param array $options Configuration array for model. Optional. * * @throws Exception * * @return F0FTable A F0FTable object */ public function getTable($name = '', $prefix = null, $options = array()) { if (empty($name)) { $name = $this->table; if (empty($name)) { $name = F0FInflector::singularize($this->getName()); } } if (empty($prefix)) { $bareComponent = str_replace('com_', '', $this->option); $prefix = ucfirst($bareComponent) . 'Table'; } if (empty($options)) { $options = array('input' => $this->input); } if ($table = $this->_createTable($name, $prefix, $options)) { return $table; } F0FPlatform::getInstance()->raiseError(0, JText::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name)); return null; } /** * Method to load and return a model object. * * @param string $name The name of the view * @param string $prefix The class prefix. Optional. * @param array $config The configuration array to pass to the table * * @return F0FTable Table object or boolean false if failed */ protected function &_createTable($name, $prefix = 'Table', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } $result = null; // Clean the model name $name = preg_replace('/[^A-Z0-9_]/i', '', $name); $prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix); // Make sure we are returning a DBO object if (!array_key_exists('dbo', $config)) { $config['dbo'] = $this->getDBO(); } $instance = F0FTable::getAnInstance($name, $prefix, $config); return $instance; } /** * Creates the WHERE part of the reorder query * * @return string */ public function getReorderWhere() { return ''; } /** * Builds the SELECT query * * @param boolean $overrideLimits Are we requested to override the set limits? * * @return F0FDatabaseQuery */ public function buildQuery($overrideLimits = false) { $table = $this->getTable(); $tableName = $table->getTableName(); $tableKey = $table->getKeyName(); $db = $this->getDbo(); $query = $db->getQuery(true); // Call the behaviors $this->modelDispatcher->trigger('onBeforeBuildQuery', array(&$this, &$query)); $alias = $this->getTableAlias(); if ($alias) { $alias = ' AS ' . $db->qn($alias); } else { $alias = ''; } $select = $this->getTableAlias() ? $db->qn($this->getTableAlias()) . '.*' : $db->qn($tableName) . '.*'; $query->select($select)->from($db->qn($tableName) . $alias); if (!$overrideLimits) { $order = $this->getState('filter_order', null, 'cmd'); if (!in_array($order, array_keys($table->getData()))) { $order = $tableKey; } $order = $db->qn($order); if ($alias) { $order = $db->qn($this->getTableAlias()) . '.' . $order; } $dir = strtoupper($this->getState('filter_order_Dir', 'ASC', 'cmd')); $dir = in_array($dir, array('DESC', 'ASC')) ? $dir : 'ASC'; // If the table cache is broken you may end up with an empty order by. if (!empty($order) && ($order != $db->qn(''))) { $query->order($order . ' ' . $dir); } } // Call the behaviors $this->modelDispatcher->trigger('onAfterBuildQuery', array(&$this, &$query)); return $query; } /** * Returns a list of the fields of the table associated with this model * * @return array */ public function getTableFields() { $tableName = $this->getTable()->getTableName(); if (version_compare(JVERSION, '3.0', 'ge')) { $fields = $this->getDbo()->getTableColumns($tableName, true); } else { $fieldsArray = $this->getDbo()->getTableFields($tableName, true); $fields = array_shift($fieldsArray); } return $fields; } /** * Get the alias set for this model's table * * @return string The table alias */ public function getTableAlias() { return $this->getTable($this->table)->getTableAlias(); } /** * Builds the count query used in getTotal() * * @return boolean */ public function buildCountQuery() { return false; } /** * Clones the model object and returns the clone * * @return F0FModel */ public function &getClone() { $clone = clone($this); return $clone; } /** * Magic getter; allows to use the name of model state keys as properties * * @param string $name The name of the variable to get * * @return mixed The value of the variable */ public function __get($name) { return $this->getState($name); } /** * Magic setter; allows to use the name of model state keys as properties * * @param string $name The name of the variable * @param mixed $value The value to set the variable to * * @return void */ public function __set($name, $value) { return $this->setState($name, $value); } /** * Magic caller; allows to use the name of model state keys as methods to * set their values. * * @param string $name The name of the state variable to set * @param mixed $arguments The value to set the state variable to * * @return F0FModel Reference to self */ public function __call($name, $arguments) { $arg1 = array_shift($arguments); $this->setState($name, $arg1); return $this; } /** * Sets the model state auto-save status. By default the model is set up to * save its state to the session. * * @param boolean $newState True to save the state, false to not save it. * * @return F0FModel Reference to self */ public function &savestate($newState) { $this->_savestate = $newState ? true : false; return $this; } /** * Initialises the _savestate variable * * @param integer $defaultSaveState The default value for the savestate * * @return void */ public function populateSavestate($defaultSaveState = -999) { if (is_null($this->_savestate)) { $savestate = $this->input->getInt('savestate', $defaultSaveState); if ($savestate == -999) { $savestate = true; } $this->savestate($savestate); } } /** * Method to auto-populate the model state. * * This method should only be called once per instantiation and is designed * to be called on the first call to the getState() method unless the model * configuration flag to ignore the request is set. * * @return void * * @note Calling getState in this method will result in recursion. * @since 12.2 */ protected function populateState() { } /** * Applies view access level filtering for the specified user. Useful to * filter a front-end items listing. * * @param integer $userID The user ID to use. Skip it to use the currently logged in user. * * @return F0FModel Reference to self */ public function applyAccessFiltering($userID = null) { $user = F0FPlatform::getInstance()->getUser($userID); $table = $this->getTable(); $accessField = $table->getColumnAlias('access'); $this->setState($accessField, $user->getAuthorisedViewLevels()); return $this; } /** * A method for getting the form from the model. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * @param boolean $source The name of the form. If not set we'll try the form_name state variable or fall back to default. * * @return mixed A F0FForm object on success, false on failure * * @since 2.0 */ public function getForm($data = array(), $loadData = true, $source = null) { $this->_formData = $data; if (empty($source)) { $source = $this->getState('form_name', null); } if (empty($source)) { $source = 'form.' . $this->name; } $name = $this->input->getCmd('option', 'com_foobar') . '.' . $this->name . '.' . $source; $options = array( 'control' => false, 'load_data' => $loadData, ); $this->onBeforeLoadForm($name, $source, $options); $form = $this->loadForm($name, $source, $options); if ($form instanceof F0FForm) { $this->onAfterLoadForm($form, $name, $source, $options); } return $form; } /** * Method to get a form object. * * @param string $name The name of the form. * @param string $source The form filename (e.g. form.browse) * @param array $options Optional array of options for the form creation. * @param boolean $clear Optional argument to force load a new form. * @param bool|string $xpath An optional xpath to search for the fields. * * @return mixed F0FForm object on success, False on error. * * @throws Exception * * @see F0FForm * @since 2.0 */ protected function loadForm($name, $source, $options = array(), $clear = false, $xpath = false) { // Handle the optional arguments. $options['control'] = isset($options['control']) ? $options['control'] : false; // Create a signature hash. $hash = md5($source . serialize($options)); // Check if we can use a previously loaded form. if (isset($this->_forms[$hash]) && !$clear) { return $this->_forms[$hash]; } // Try to find the name and path of the form to load $formFilename = $this->findFormFilename($source); // No form found? Quit! if ($formFilename === false) { return false; } // Set up the form name and path $source = basename($formFilename, '.xml'); F0FForm::addFormPath(dirname($formFilename)); // Set up field paths $option = $this->input->getCmd('option', 'com_foobar'); $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($option); $view = $this->name; $file_root = $componentPaths['main']; $alt_file_root = $componentPaths['alt']; F0FForm::addFieldPath($file_root . '/fields'); F0FForm::addFieldPath($file_root . '/models/fields'); F0FForm::addFieldPath($alt_file_root . '/fields'); F0FForm::addFieldPath($alt_file_root . '/models/fields'); F0FForm::addHeaderPath($file_root . '/fields/header'); F0FForm::addHeaderPath($file_root . '/models/fields/header'); F0FForm::addHeaderPath($alt_file_root . '/fields/header'); F0FForm::addHeaderPath($alt_file_root . '/models/fields/header'); // Get the form. try { $form = F0FForm::getInstance($name, $source, $options, false, $xpath); if (isset($options['load_data']) && $options['load_data']) { // Get the data for the form. $data = $this->loadFormData(); } else { $data = array(); } // Allows data and form manipulation before preprocessing the form $this->onBeforePreprocessForm($form, $data); // Allow for additional modification of the form, and events to be triggered. // We pass the data because plugins may require it. $this->preprocessForm($form, $data); // Allows data and form manipulation After preprocessing the form $this->onAfterPreprocessForm($form, $data); // Load the data into the form after the plugins have operated. $form->bind($data); } catch (Exception $e) { // The above try-catch statement will catch EVERYTHING, even PhpUnit exceptions while testing if(stripos(get_class($e), 'phpunit') !== false) { throw $e; } else { $this->setError($e->getMessage()); return false; } } // Store the form for later. $this->_forms[$hash] = $form; return $form; } /** * Guesses the best candidate for the path to use for a particular form. * * @param string $source The name of the form file to load, without the .xml extension. * @param array $paths The paths to look into. You can declare this to override the default F0F paths. * * @return mixed A string if the path and filename of the form to load is found, false otherwise. * * @since 2.0 */ public function findFormFilename($source, $paths = array()) { // TODO Should we read from internal variables instead of the input? With a temp instance we have no input $option = $this->input->getCmd('option', 'com_foobar'); $view = $this->name; $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($option); $file_root = $componentPaths['main']; $alt_file_root = $componentPaths['alt']; $template_root = F0FPlatform::getInstance()->getTemplateOverridePath($option); if (empty($paths)) { // Set up the paths to look into // PLEASE NOTE: If you ever change this, please update Model Unit tests, too, since we have to // copy these default folders (we have to add the protocol for the virtual filesystem) $paths = array( // In the template override $template_root . '/' . $view, $template_root . '/' . F0FInflector::singularize($view), $template_root . '/' . F0FInflector::pluralize($view), // In this side of the component $file_root . '/views/' . $view . '/tmpl', $file_root . '/views/' . F0FInflector::singularize($view) . '/tmpl', $file_root . '/views/' . F0FInflector::pluralize($view) . '/tmpl', // In the other side of the component $alt_file_root . '/views/' . $view . '/tmpl', $alt_file_root . '/views/' . F0FInflector::singularize($view) . '/tmpl', $alt_file_root . '/views/' . F0FInflector::pluralize($view) . '/tmpl', // In the models/forms of this side $file_root . '/models/forms', // In the models/forms of the other side $alt_file_root . '/models/forms', ); } $paths = array_unique($paths); // Set up the suffixes to look into $suffixes = array(); $temp_suffixes = F0FPlatform::getInstance()->getTemplateSuffixes(); if (!empty($temp_suffixes)) { foreach ($temp_suffixes as $suffix) { $suffixes[] = $suffix . '.xml'; } } $suffixes[] = '.xml'; // Look for all suffixes in all paths $result = false; $filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem'); foreach ($paths as $path) { foreach ($suffixes as $suffix) { $filename = $path . '/' . $source . $suffix; if ($filesystem->fileExists($filename)) { $result = $filename; break; } } if ($result) { break; } } return $result; } /** * Method to get the data that should be injected in the form. * * @return array The default data is an empty array. * * @since 2.0 */ protected function loadFormData() { if (empty($this->_formData)) { return array(); } else { return $this->_formData; } } /** * Method to allow derived classes to preprocess the form. * * @param F0FForm $form A F0FForm object. * @param mixed &$data The data expected for the form. * @param string $group The name of the plugin group to import (defaults to "content"). * * @return void * * @see F0FFormField * @since 2.0 * @throws Exception if there is an error in the form event. */ protected function preprocessForm(F0FForm &$form, &$data, $group = 'content') { // Import the appropriate plugin group. F0FPlatform::getInstance()->importPlugin($group); // Trigger the form preparation event. $results = F0FPlatform::getInstance()->runPlugins('onContentPrepareForm', array($form, $data)); // Check for errors encountered while preparing the form. if (count($results) && in_array(false, $results, true)) { // Get the last error. $dispatcher = F0FUtilsObservableDispatcher::getInstance(); $error = $dispatcher->getError(); if (!($error instanceof Exception)) { throw new Exception($error); } } } /** * Method to validate the form data. * * @param F0FForm $form The form to validate against. * @param array $data The data to validate. * @param string $group The name of the field group to validate. * * @return mixed Array of filtered data if valid, false otherwise. * * @see JFormRule * @see JFilterInput * @since 2.0 */ public function validateForm($form, $data, $group = null) { // Filter and validate the form data. $data = $form->filter($data); $return = $form->validate($data, $group); // Check for an error. if ($return instanceof Exception) { $this->setError($return->getMessage()); return false; } // Check the validation results. if ($return === false) { // Get the validation messages from the form. foreach ($form->getErrors() as $message) { if ($message instanceof Exception) { $this->setError($message->getMessage()); } else { $this->setError($message); } } return false; } return $data; } /** * Allows the manipulation before the form is loaded * * @param string &$name The name of the form. * @param string &$source The form source. Can be XML string if file flag is set to false. * @param array &$options Optional array of options for the form creation. * @codeCoverageIgnore * * @return void */ public function onBeforeLoadForm(&$name, &$source, &$options) { } /** * Allows the manipulation after the form is loaded * * @param F0FForm $form A F0FForm object. * @param string &$name The name of the form. * @param string &$source The form source. Can be XML string if file flag is set to false. * @param array &$options Optional array of options for the form creation. * @codeCoverageIgnore * * @return void */ public function onAfterLoadForm(F0FForm &$form, &$name, &$source, &$options) { } /** * Allows data and form manipulation before preprocessing the form * * @param F0FForm $form A F0FForm object. * @param array &$data The data expected for the form. * @codeCoverageIgnore * * @return void */ public function onBeforePreprocessForm(F0FForm &$form, &$data) { } /** * Allows data and form manipulation after preprocessing the form * * @param F0FForm $form A F0FForm object. * @param array &$data The data expected for the form. * @codeCoverageIgnore * * @return void */ public function onAfterPreprocessForm(F0FForm &$form, &$data) { } /** * This method can be overriden to automatically do something with the * list results array. You are supposed to modify the list which was passed * in the parameters; DO NOT return a new array! * * @param array &$resultArray An array of objects, each row representing a record * * @return void */ protected function onProcessList(&$resultArray) { } /** * This method runs after an item has been gotten from the database in a read * operation. You can modify it before it's returned to the MVC triad for * further processing. * * @param F0FTable &$record The table instance we fetched * * @return void */ protected function onAfterGetItem(&$record) { try { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterGetItem', array(&$this, &$record)); } catch (Exception $e) { // Oops, an exception occured! $this->setError($e->getMessage()); } } /** * This method runs before the $data is saved to the $table. Return false to * stop saving. * * @param array &$data The data to save * @param F0FTable &$table The table to save the data to * * @return boolean Return false to prevent saving, true to allow it */ protected function onBeforeSave(&$data, &$table) { // Let's import the plugin only if we're not in CLI (content plugin needs a user) F0FPlatform::getInstance()->importPlugin('content'); try { // Do I have a new record? $key = $table->getKeyName(); $pk = (!empty($data[$key])) ? $data[$key] : 0; $this->_isNewRecord = $pk <= 0; // Bind the data $table->bind($data); // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforeSave', array(&$this, &$data)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } // Call the plugin $name = $this->name; $result = F0FPlatform::getInstance()->runPlugins($this->event_before_save, array($this->option . '.' . $name, &$table, $this->_isNewRecord)); if (in_array(false, $result, true)) { // Plugin failed, return false $this->setError($table->getError()); return false; } } catch (Exception $e) { // Oops, an exception occured! $this->setError($e->getMessage()); return false; } return true; } /** * This method runs after the data is saved to the $table. * * @param F0FTable &$table The table which was saved * * @return boolean */ protected function onAfterSave(&$table) { // Let's import the plugin only if we're not in CLI (content plugin needs a user) F0FPlatform::getInstance()->importPlugin('content'); try { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterSave', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } $name = $this->name; F0FPlatform::getInstance()->runPlugins($this->event_after_save, array($this->option . '.' . $name, &$table, $this->_isNewRecord)); return true; } catch (Exception $e) { // Oops, an exception occured! $this->setError($e->getMessage()); return false; } } /** * This method runs before the record with key value of $id is deleted from $table * * @param integer &$id The ID of the record being deleted * @param F0FTable &$table The table instance used to delete the record * * @return boolean */ protected function onBeforeDelete(&$id, &$table) { // Let's import the plugin only if we're not in CLI (content plugin needs a user) F0FPlatform::getInstance()->importPlugin('content'); try { $table->load($id); // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforeDelete', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } $name = $this->name; $context = $this->option . '.' . $name; $result = F0FPlatform::getInstance()->runPlugins($this->event_before_delete, array($context, $table)); if (in_array(false, $result, true)) { // Plugin failed, return false $this->setError($table->getError()); return false; } $this->_recordForDeletion = clone $table; } catch (Exception $e) { // Oops, an exception occured! $this->setError($e->getMessage()); return false; } return true; } /** * This method runs after a record with key value $id is deleted * * @param integer $id The id of the record which was deleted * * @return boolean Return false to raise an error, true otherwise */ protected function onAfterDelete($id) { F0FPlatform::getInstance()->importPlugin('content'); // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterDelete', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } try { $name = $this->name; $context = $this->option . '.' . $name; $result = F0FPlatform::getInstance()->runPlugins($this->event_after_delete, array($context, $this->_recordForDeletion)); unset($this->_recordForDeletion); } catch (Exception $e) { // Oops, an exception occured! $this->setError($e->getMessage()); return false; } } /** * This method runs before a record is copied * * @param F0FTable &$table The table instance of the record being copied * * @return boolean True to allow the copy */ protected function onBeforeCopy(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforeCopy', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs after a record has been copied * * @param F0FTable &$table The table instance of the record which was copied * * @return boolean True to allow the copy */ protected function onAfterCopy(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterCopy', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs before a record is published * * @param F0FTable &$table The table instance of the record being published * * @return boolean True to allow the operation */ protected function onBeforePublish(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforePublish', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs after a record has been published * * @param F0FTable &$table The table instance of the record which was published * * @return boolean True to allow the operation */ protected function onAfterPublish(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterPublish', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs before a record is hit * * @param F0FTable &$table The table instance of the record being hit * * @return boolean True to allow the operation */ protected function onBeforeHit(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforeHit', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs after a record has been hit * * @param F0FTable &$table The table instance of the record which was hit * * @return boolean True to allow the operation */ protected function onAfterHit(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterHit', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs before a record is moved * * @param F0FTable &$table The table instance of the record being moved * * @return boolean True to allow the operation */ protected function onBeforeMove(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforeMove', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs after a record has been moved * * @param F0FTable &$table The table instance of the record which was moved * * @return boolean True to allow the operation */ protected function onAfterMove(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterMove', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs before a table is reordered * * @param F0FTable &$table The table instance being reordered * * @return boolean True to allow the operation */ protected function onBeforeReorder(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onBeforeReorder', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * This method runs after a table is reordered * * @param F0FTable &$table The table instance which was reordered * * @return boolean True to allow the operation */ protected function onAfterReorder(&$table) { // Call the behaviors $result = $this->modelDispatcher->trigger('onAfterReorder', array(&$this)); if (in_array(false, $result, true)) { // Behavior failed, return false return false; } return true; } /** * Method to get the database driver object * * @return F0FDatabaseDriver */ public function getDbo() { return $this->_db; } /** * Method to get the model name * * The model name. By default parsed using the classname or it can be set * by passing a $config['name'] in the class constructor * * @return string The name of the model * * @throws Exception */ public function getName() { if (empty($this->name)) { $r = null; if (!preg_match('/Model(.*)/i', get_class($this), $r)) { throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500); } $this->name = strtolower($r[1]); } return $this->name; } /** * Method to set the database driver object * * @param F0FDatabaseDriver $db A F0FDatabaseDriver based object * * @return void */ public function setDbo($db) { $this->_db = $db; } /** * Method to set model state variables * * @param string $property The name of the property. * @param mixed $value The value of the property to set or null. * * @return mixed The previous value of the property or null if not set. */ public function setState($property, $value = null) { return $this->state->set($property, $value); } /** * Clean the cache * * @param string $group The cache group * @param integer $client_id The ID of the client * * @return void */ protected function cleanCache($group = null, $client_id = 0) { $conf = JFactory::getConfig(); $platformDirs = F0FPlatform::getInstance()->getPlatformBaseDirs(); $options = array( 'defaultgroup' => ($group) ? $group : (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')), 'cachebase' => ($client_id) ? $platformDirs['admin'] . '/cache' : $conf->get('cache_path', $platformDirs['public'] . '/cache')); $cache = JCache::getInstance('callback', $options); $cache->clean(); // Trigger the onContentCleanCache event. F0FPlatform::getInstance()->runPlugins($this->event_clean_cache, $options); } /** * Set a behavior param * * @param string $name The name of the param * @param mixed $value The param value to set * * @return FOFModel */ public function setBehaviorParam($name, $value) { $this->_behaviorParams[$name] = $value; return $this; } /** * Get a behavior param * * @param string $name The name of the param * @param mixed $default The default value returned if not set * * @return mixed */ public function getBehaviorParam($name, $default = null) { return isset($this->_behaviorParams[$name]) ? $this->_behaviorParams[$name] : $default; } /** * Set or get the backlisted filters * * @param mixed $list A filter or list of filters to backlist. If null return the list of backlisted filter * @param boolean $reset Reset the blacklist if true * * @return void|array Return an array of value if $list is null */ public function blacklistFilters($list = null, $reset = false) { if (!isset($list)) { return $this->getBehaviorParam('blacklistFilters', array()); } if (is_string($list)) { $list = (array) $list; } if (!$reset) { $list = array_unique(array_merge($this->getBehaviorParam('blacklistFilters', array()), $list)); } $this->setBehaviorParam('blacklistFilters', $list); } } PK �s!]���: : base.phpnu &1i� <?php /** * @package Joomla.Platform * @subpackage Model * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE */ defined('JPATH_PLATFORM') or die; use Joomla\Registry\Registry; /** * Joomla Platform Base Model Class * * @since 3.0.0 * @deprecated 4.0 Use the default MVC library */ abstract class JModelBase implements JModel { /** * The model state. * * @var Registry * @since 3.0.0 */ protected $state; /** * Instantiate the model. * * @param Registry $state The model state. * * @since 3.0.0 */ public function __construct(Registry $state = null) { // Setup the model. $this->state = isset($state) ? $state : $this->loadState(); } /** * Get the model state. * * @return Registry The state object. * * @since 3.0.0 */ public function getState() { return $this->state; } /** * Set the model state. * * @param Registry $state The state object. * * @return void * * @since 3.0.0 */ public function setState(Registry $state) { $this->state = $state; } /** * Load the model state. * * @return Registry The state object. * * @since 3.0.0 */ protected function loadState() { return new Registry; } } PK �s!]�s\�� � database.phpnu &1i� <?php /** * @package Joomla.Platform * @subpackage Model * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE */ defined('JPATH_PLATFORM') or die; use Joomla\Registry\Registry; /** * Joomla Platform Database Model Class * * @since 3.0.0 * @deprecated 4.0 Use the default MVC library */ abstract class JModelDatabase extends JModelBase { /** * The database driver. * * @var JDatabaseDriver * @since 3.0.0 */ protected $db; /** * Instantiate the model. * * @param Registry $state The model state. * @param JDatabaseDriver $db The database adapter. * * @since 3.0.0 */ public function __construct(Registry $state = null, JDatabaseDriver $db = null) { parent::__construct($state); // Setup the model. $this->db = isset($db) ? $db : $this->loadDb(); } /** * Get the database driver. * * @return JDatabaseDriver The database driver. * * @since 3.0.0 */ public function getDb() { return $this->db; } /** * Set the database driver. * * @param JDatabaseDriver $db The database driver. * * @return void * * @since 3.0.0 */ public function setDb(JDatabaseDriver $db) { $this->db = $db; } /** * Load the database driver. * * @return JDatabaseDriver The database driver. * * @since 3.0.0 */ protected function loadDb() { return JFactory::getDbo(); } } PK tt!]�^4�C C behavior.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class. It defines the events which are * called by a Model. * * @codeCoverageIgnore * @package FrameworkOnFramework * @since 2.1 */ abstract class F0FModelBehavior extends F0FUtilsObservableEvent { /** * This event runs before saving data in the model * * @param F0FModel &$model The model which calls this event * @param array &$data The data to save * * @return void */ public function onBeforeSave(&$model, &$data) { } /** * This event runs before deleting a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onBeforeDelete(&$model) { } /** * This event runs before copying a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onBeforeCopy(&$model) { } /** * This event runs before publishing a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onBeforePublish(&$model) { } /** * This event runs before registering a hit on a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onBeforeHit(&$model) { } /** * This event runs before moving a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onBeforeMove(&$model) { } /** * This event runs before changing the records' order in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onBeforeReorder(&$model) { } /** * This event runs when we are building the query used to fetch a record * list in a model * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The query being built * * @return void */ public function onBeforeBuildQuery(&$model, &$query) { } /** * This event runs after saving a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterSave(&$model) { } /** * This event runs after deleting a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterDelete(&$model) { } /** * This event runs after copying a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterCopy(&$model) { } /** * This event runs after publishing a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterPublish(&$model) { } /** * This event runs after registering a hit on a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterHit(&$model) { } /** * This event runs after moving a record in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterMove(&$model) { } /** * This event runs after reordering records in a model * * @param F0FModel &$model The model which calls this event * * @return void */ public function onAfterReorder(&$model) { } /** * This event runs after we have built the query used to fetch a record * list in a model * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The query being built * * @return void */ public function onAfterBuildQuery(&$model, &$query) { } /** * This event runs after getting a single item * * @param F0FModel &$model The model which calls this event * @param F0FTable &$record The record loaded by this model * * @return void */ public function onAfterGetItem(&$model, &$record) { } } PK tt!]�X9)� � field/boolean.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelFieldBoolean extends F0FModelFieldNumber { /** * Is it a null or otherwise empty value? * * @param mixed $value The value to test for emptiness * * @return boolean */ public function isEmpty($value) { return is_null($value) || ($value === ''); } } PK tt!]jv�.� � field/date.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelFieldDate extends F0FModelFieldText { /** * Returns the default search method for this field. * * @return string */ public function getDefaultSearchMethod() { return 'exact'; } /** * Perform a between limits match. When $include is true * the condition tested is: * $from <= VALUE <= $to * When $include is false the condition tested is: * $from < VALUE < $to * * @param mixed $from The lowest value to compare to * @param mixed $to The higherst value to compare to * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ public function between($from, $to, $include = true) { if ($this->isEmpty($from) || $this->isEmpty($to)) { return ''; } $extra = ''; if ($include) { $extra = '='; } $sql = '((' . $this->getFieldName() . ' >' . $extra . ' "' . $from . '") AND '; $sql .= '(' . $this->getFieldName() . ' <' . $extra . ' "' . $to . '"))'; return $sql; } /** * Perform an outside limits match. When $include is true * the condition tested is: * (VALUE <= $from) || (VALUE >= $to) * When $include is false the condition tested is: * (VALUE < $from) || (VALUE > $to) * * @param mixed $from The lowest value of the excluded range * @param mixed $to The higherst value of the excluded range * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ public function outside($from, $to, $include = false) { if ($this->isEmpty($from) || $this->isEmpty($to)) { return ''; } $extra = ''; if ($include) { $extra = '='; } $sql = '((' . $this->getFieldName() . ' <' . $extra . ' "' . $from . '") OR '; $sql .= '(' . $this->getFieldName() . ' >' . $extra . ' "' . $to . '"))'; return $sql; } /** * Interval date search * * @param string $value The value to search * @param string|array|object $interval The interval. Can be (+1 MONTH or array('value' => 1, 'unit' => 'MONTH', 'sign' => '+')) * @param boolean $include If the borders should be included * * @return string the sql string */ public function interval($value, $interval, $include = true) { if ($this->isEmpty($value) || $this->isEmpty($interval)) { return ''; } $interval = $this->getInterval($interval); if ($interval['sign'] == '+') { $function = 'DATE_ADD'; } else { $function = 'DATE_SUB'; } $extra = ''; if ($include) { $extra = '='; } $sql = '(' . $this->getFieldName() . ' >' . $extra . ' ' . $function; $sql .= '(' . $this->getFieldName() . ', INTERVAL ' . $interval['value'] . ' ' . $interval['unit'] . '))'; return $sql; } /** * Perform a between limits match. When $include is true * the condition tested is: * $from <= VALUE <= $to * When $include is false the condition tested is: * $from < VALUE < $to * * @param mixed $from The lowest value to compare to * @param mixed $to The higherst value to compare to * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ public function range($from, $to, $include = true) { if ($this->isEmpty($from) && $this->isEmpty($to)) { return ''; } $extra = ''; if ($include) { $extra = '='; } if ($from) $sql[] = '(' . $this->getFieldName() . ' >' . $extra . ' "' . $from . '")'; if ($to) $sql[] = '(' . $this->getFieldName() . ' <' . $extra . ' "' . $to . '")'; $sql = '(' . implode(' AND ', $sql) . ')'; return $sql; } /** * Parses an interval –which may be given as a string, array or object– into * a standardised hash array that can then be used bu the interval() method. * * @param string|array|object $interval The interval expression to parse * * @return array The parsed, hash array form of the interval */ protected function getInterval($interval) { if (is_string($interval)) { if (strlen($interval) > 2) { $interval = explode(" ", $interval); $sign = ($interval[0] == '-') ? '-' : '+'; $value = (int) substr($interval[0], 1); $interval = array( 'unit' => $interval[1], 'value' => $value, 'sign' => $sign ); } else { $interval = array( 'unit' => 'MONTH', 'value' => 1, 'sign' => '+' ); } } else { $interval = (array) $interval; } return $interval; } } PK tt!]�;�ۈ � field/text.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelFieldText extends F0FModelField { /** * Constructor * * @param F0FDatabaseDriver $db The database object * @param object $field The field informations as taken from the db */ public function __construct($db, $field, $table_alias = false) { parent::__construct($db, $field, $table_alias); $this->null_value = ''; } /** * Returns the default search method for this field. * * @return string */ public function getDefaultSearchMethod() { return 'partial'; } /** * Perform a partial match (search in string) * * @param mixed $value The value to compare to * * @return string The SQL where clause for this search */ public function partial($value) { if ($this->isEmpty($value)) { return ''; } return '(' . $this->getFieldName() . ' LIKE ' . $this->_db->quote('%' . $value . '%') . ')'; } /** * Perform an exact match (match string) * * @param mixed $value The value to compare to * * @return string The SQL where clause for this search */ public function exact($value) { if ($this->isEmpty($value)) { return ''; } return '(' . $this->getFieldName() . ' LIKE ' . $this->_db->quote($value) . ')'; } /** * Dummy method; this search makes no sense for text fields * * @param mixed $from Ignored * @param mixed $to Ignored * @param boolean $include Ignored * * @return string Empty string */ public function between($from, $to, $include = true) { return ''; } /** * Dummy method; this search makes no sense for text fields * * @param mixed $from Ignored * @param mixed $to Ignored * @param boolean $include Ignored * * @return string Empty string */ public function outside($from, $to, $include = false) { return ''; } /** * Dummy method; this search makes no sense for text fields * * @param mixed $value Ignored * @param mixed $interval Ignored * @param boolean $include Ignored * * @return string Empty string */ public function interval($value, $interval, $include = true) { return ''; } /** * Dummy method; this search makes no sense for text fields * * @param mixed $from Ignored * @param mixed $to Ignored * @param boolean $include Ignored * * @return string Empty string */ public function range($from, $to, $include = false) { return ''; } /** * Dummy method; this search makes no sense for text fields * * @param mixed $from Ignored * @param mixed $to Ignored * @param boolean $include Ignored * * @return string Empty string */ public function modulo($from, $to, $include = false) { return ''; } } PK tt!]�ퟷ field/number.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelFieldNumber extends F0FModelField { /** * The partial match is mapped to an exact match * * @param mixed $value The value to compare to * * @return string The SQL where clause for this search */ public function partial($value) { return $this->exact($value); } /** * Perform a between limits match. When $include is true * the condition tested is: * $from <= VALUE <= $to * When $include is false the condition tested is: * $from < VALUE < $to * * @param mixed $from The lowest value to compare to * @param mixed $to The higherst value to compare to * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ public function between($from, $to, $include = true) { if ($this->isEmpty($from) || $this->isEmpty($to)) { return ''; } $extra = ''; if ($include) { $extra = '='; } $sql = '((' . $this->getFieldName() . ' >' . $extra . ' ' . $from . ') AND '; $sql .= '(' . $this->getFieldName() . ' <' . $extra . ' ' . $to . '))'; return $sql; } /** * Perform an outside limits match. When $include is true * the condition tested is: * (VALUE <= $from) || (VALUE >= $to) * When $include is false the condition tested is: * (VALUE < $from) || (VALUE > $to) * * @param mixed $from The lowest value of the excluded range * @param mixed $to The higherst value of the excluded range * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ public function outside($from, $to, $include = false) { if ($this->isEmpty($from) || $this->isEmpty($to)) { return ''; } $extra = ''; if ($include) { $extra = '='; } $sql = '((' . $this->getFieldName() . ' <' . $extra . ' ' . $from . ') OR '; $sql .= '(' . $this->getFieldName() . ' >' . $extra . ' ' . $to . '))'; return $sql; } /** * Perform an interval match. It's similar to a 'between' match, but the * from and to values are calculated based on $value and $interval: * $value - $interval < VALUE < $value + $interval * * @param integer|float $value The center value of the search space * @param integer|float $interval The width of the search space * @param boolean $include Should I include the boundaries in the search? * * @return string The SQL where clause */ public function interval($value, $interval, $include = true) { if ($this->isEmpty($value)) { return ''; } $from = $value - $interval; $to = $value + $interval; $extra = ''; if ($include) { $extra = '='; } $sql = '((' . $this->getFieldName() . ' >' . $extra . ' ' . $from . ') AND '; $sql .= '(' . $this->getFieldName() . ' <' . $extra . ' ' . $to . '))'; return $sql; } /** * Perform a range limits match. When $include is true * the condition tested is: * $from <= VALUE <= $to * When $include is false the condition tested is: * $from < VALUE < $to * * @param mixed $from The lowest value to compare to * @param mixed $to The higherst value to compare to * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ public function range($from, $to, $include = true) { if ($this->isEmpty($from) && $this->isEmpty($to)) { return ''; } $extra = ''; if ($include) { $extra = '='; } if ($from) $sql[] = '(' . $this->getFieldName() . ' >' . $extra . ' ' . $from . ')'; if ($to) $sql[] = '(' . $this->getFieldName() . ' <' . $extra . ' ' . $to . ')'; $sql = '(' . implode(' AND ', $sql) . ')'; return $sql; } /** * Perform an interval match. It's similar to a 'between' match, but the * from and to values are calculated based on $value and $interval: * $value - $interval < VALUE < $value + $interval * * @param integer|float $value The starting value of the search space * @param integer|float $interval The interval period of the search space * @param boolean $include Should I include the boundaries in the search? * * @return string The SQL where clause */ public function modulo($value, $interval, $include = true) { if ($this->isEmpty($value) || $this->isEmpty($interval)) { return ''; } $extra = ''; if ($include) { $extra = '='; } $sql = '(' . $this->getFieldName() . ' >' . $extra . ' ' . $value . ' AND '; $sql .= '(' . $this->getFieldName() . ' - ' . $value . ') % ' . $interval . ' = 0)'; return $sql; } } PK tt!].�<� dispatcher/behavior.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior dispatcher class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelDispatcherBehavior extends F0FUtilsObservableDispatcher { } PK tt!]���� � field.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ abstract class F0FModelField { protected $_db = null; /** * The column name of the table field * * @var string */ protected $name = ''; /** * The column type of the table field * * @var string */ protected $type = ''; /** * The alias of the table used for filtering * * @var string */ protected $table_alias = false; /** * The null value for this type * * @var mixed */ public $null_value = null; /** * Constructor * * @param F0FDatabaseDriver $db The database object * @param object $field The field informations as taken from the db * @param string $table_alias The table alias to use when filtering */ public function __construct($db, $field, $table_alias = false) { $this->_db = $db; $this->name = $field->name; $this->type = $field->type; $this->filterzero = $field->filterzero; $this->table_alias = $table_alias; } /** * Is it a null or otherwise empty value? * * @param mixed $value The value to test for emptiness * * @return boolean */ public function isEmpty($value) { return (($value === $this->null_value) || empty($value)) && !($this->filterzero && $value === "0"); } /** * Returns the default search method for a field. This always returns 'exact' * and you are supposed to override it in specialised classes. The possible * values are exact, partial, between and outside, unless something * different is returned by getSearchMethods(). * * @see self::getSearchMethods() * * @return string */ public function getDefaultSearchMethod() { return 'exact'; } /** * Return the search methods available for this field class, * * @return array */ public function getSearchMethods() { $ignore = array('isEmpty', 'getField', 'getFieldType', '__construct', 'getDefaultSearchMethod', 'getSearchMethods'); $class = new ReflectionClass(__CLASS__); $methods = $class->getMethods(ReflectionMethod::IS_PUBLIC); $tmp = array(); foreach ($methods as $method) { $tmp[] = $method->name; } $methods = $tmp; if ($methods = array_diff($methods, $ignore)) { return $methods; } return array(); } /** * Perform an exact match (equality matching) * * @param mixed $value The value to compare to * * @return string The SQL where clause for this search */ public function exact($value) { if ($this->isEmpty($value)) { return ''; } if (is_array($value)) { $db = F0FPlatform::getInstance()->getDbo(); $value = array_map(array($db, 'quote'), $value); return '(' . $this->getFieldName() . ' IN (' . implode(',', $value) . '))'; } else { return $this->search($value, '='); } } /** * Perform a partial match (usually: search in string) * * @param mixed $value The value to compare to * * @return string The SQL where clause for this search */ abstract public function partial($value); /** * Perform a between limits match (usually: search for a value between * two numbers or a date between two preset dates). When $include is true * the condition tested is: * $from <= VALUE <= $to * When $include is false the condition tested is: * $from < VALUE < $to * * @param mixed $from The lowest value to compare to * @param mixed $to The higherst value to compare to * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ abstract public function between($from, $to, $include = true); /** * Perform an outside limits match (usually: search for a value outside an * area or a date outside a preset period). When $include is true * the condition tested is: * (VALUE <= $from) || (VALUE >= $to) * When $include is false the condition tested is: * (VALUE < $from) || (VALUE > $to) * * @param mixed $from The lowest value of the excluded range * @param mixed $to The higherst value of the excluded range * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ abstract public function outside($from, $to, $include = false); /** * Perform an interval search (usually: a date interval check) * * @param string $from The value to search * @param string|array|object $interval The interval * * @return string The SQL where clause for this search */ abstract public function interval($from, $interval); /** * Perform a between limits match (usually: search for a value between * two numbers or a date between two preset dates). When $include is true * the condition tested is: * $from <= VALUE <= $to * When $include is false the condition tested is: * $from < VALUE < $to * * @param mixed $from The lowest value to compare to * @param mixed $to The higherst value to compare to * @param boolean $include Should we include the boundaries in the search? * * @return string The SQL where clause for this search */ abstract public function range($from, $to, $include = true); /** * Perform an modulo search * * @param integer|float $value The starting value of the search space * @param integer|float $interval The interval period of the search space * @param boolean $include Should I include the boundaries in the search? * * @return string The SQL where clause */ abstract public function modulo($from, $interval, $include = true); /** * Return the SQL where clause for a search * * @param mixed $value The value to search for * @param string $operator The operator to use * * @return string The SQL where clause for this search */ public function search($value, $operator = '=') { if ($this->isEmpty($value)) { return ''; } return '(' . $this->getFieldName() . ' ' . $operator . ' ' . $this->_db->quote($value) . ')'; } /** * Get the field name with the given table alias * * @return string The field name */ public function getFieldName() { $name = $this->_db->qn($this->name); if ($this->table_alias) { $name = $this->_db->qn($this->table_alias) . '.' . $name; } return $name; } /** * Creates a field Object based on the field column type * * @param object $field The field informations * @param array $config The field configuration (like the db object to use) * * @return F0FModelField The Field object */ public static function getField($field, $config = array()) { $type = $field->type; $classType = self::getFieldType($type); $className = 'F0FModelField' . $classType; if (class_exists($className)) { if (isset($config['dbo'])) { $db = $config['dbo']; } else { $db = F0FPlatform::getInstance()->getDbo(); } if (isset($config['table_alias'])) { $table_alias = $config['table_alias']; } else { $table_alias = false; } $field = new $className($db, $field, $table_alias); return $field; } return false; } /** * Get the classname based on the field Type * * @param string $type The type of the field * * @return string the class suffix */ public static function getFieldType($type) { switch ($type) { case 'varchar': case 'text': case 'smalltext': case 'longtext': case 'char': case 'mediumtext': case 'character varying': case 'nvarchar': case 'nchar': $type = 'Text'; break; case 'date': case 'datetime': case 'time': case 'year': case 'timestamp': case 'timestamp without time zone': case 'timestamp with time zone': $type = 'Date'; break; case 'tinyint': case 'smallint': $type = 'Boolean'; break; default: $type = 'Number'; break; } return $type; } } PK tt!]¦=� � behavior/language.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class to filter front-end access to items * based on the language. * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelBehaviorLanguage extends F0FModelBehavior { /** * This event runs before we have built the query used to fetch a record * list in a model. It is used to blacklist the language filter * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The model which calls this event * * @return void */ public function onBeforeBuildQuery(&$model, &$query) { if (F0FPlatform::getInstance()->isFrontend()) { $model->blacklistFilters('language'); } } /** * This event runs after we have built the query used to fetch a record * list in a model. It is used to apply automatic query filters. * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The model which calls this event * * @return void */ public function onAfterBuildQuery(&$model, &$query) { // This behavior only applies to the front-end. if (!F0FPlatform::getInstance()->isFrontend()) { return; } // Get the name of the language field $table = $model->getTable(); $languageField = $table->getColumnAlias('language'); // Make sure the access field actually exists if (!in_array($languageField, $table->getKnownFields())) { return; } // Make sure it is a multilingual site and get a list of languages $app = JFactory::getApplication(); $hasLanguageFilter = method_exists($app, 'getLanguageFilter'); if ($hasLanguageFilter) { $hasLanguageFilter = $app->getLanguageFilter(); } if (!$hasLanguageFilter) { return; } $lang_filter_plugin = JPluginHelper::getPlugin('system', 'languagefilter'); $lang_filter_params = new JRegistry($lang_filter_plugin->params); $languages = array('*'); if ($lang_filter_params->get('remove_default_prefix')) { // Get default site language $lg = F0FPlatform::getInstance()->getLanguage(); $languages[] = $lg->getTag(); } else { $languages[] = JFactory::getApplication()->input->getCmd('language', '*'); } // Filter out double languages $languages = array_unique($languages); // And filter the query output by these languages $db = F0FPlatform::getInstance()->getDbo(); // Alias $alias = $model->getTableAlias(); $alias = $alias ? $db->qn($alias) . '.' : ''; $languages = array_map(array($db, 'quote'), $languages); $query->where($alias . $db->qn($languageField) . ' IN (' . implode(',', $languages) . ')'); } /** * The event runs after F0FModel has called F0FTable and retrieved a single * item from the database. It is used to apply automatic filters. * * @param F0FModel &$model The model which was called * @param F0FTable &$record The record loaded from the databae * * @return void */ public function onAfterGetItem(&$model, &$record) { if ($record instanceof F0FTable) { $fieldName = $record->getColumnAlias('language'); // Make sure the field actually exists if (!in_array($fieldName, $record->getKnownFields())) { return; } // Make sure it is a multilingual site and get a list of languages $app = JFactory::getApplication(); $hasLanguageFilter = method_exists($app, 'getLanguageFilter'); if ($hasLanguageFilter) { $hasLanguageFilter = $app->getLanguageFilter(); } if (!$hasLanguageFilter) { return; } $lang_filter_plugin = JPluginHelper::getPlugin('system', 'languagefilter'); $lang_filter_params = new JRegistry($lang_filter_plugin->params); $languages = array('*'); if ($lang_filter_params->get('remove_default_prefix')) { // Get default site language $lg = F0FPlatform::getInstance()->getLanguage(); $languages[] = $lg->getTag(); } else { $languages[] = JFactory::getApplication()->input->getCmd('language', '*'); } // Filter out double languages $languages = array_unique($languages); if (!in_array($record->$fieldName, $languages)) { $record = null; } } } } PK tt!]�:\� � behavior/private.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class to filter front-end access to items * craeted by the currently logged in user only. * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelBehaviorPrivate extends F0FModelBehavior { /** * This event runs after we have built the query used to fetch a record * list in a model. It is used to apply automatic query filters. * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The model which calls this event * * @return void */ public function onAfterBuildQuery(&$model, &$query) { // This behavior only applies to the front-end. if (!F0FPlatform::getInstance()->isFrontend()) { return; } // Get the name of the access field $table = $model->getTable(); $createdField = $table->getColumnAlias('created_by'); // Make sure the access field actually exists if (!in_array($createdField, $table->getKnownFields())) { return; } // Get the current user's id $user_id = F0FPlatform::getInstance()->getUser()->id; // And filter the query output by the user id $db = F0FPlatform::getInstance()->getDbo(); $alias = $model->getTableAlias(); $alias = $alias ? $db->qn($alias) . '.' : ''; $query->where($alias . $db->qn($createdField) . ' = ' . $db->q($user_id)); } /** * The event runs after F0FModel has called F0FTable and retrieved a single * item from the database. It is used to apply automatic filters. * * @param F0FModel &$model The model which was called * @param F0FTable &$record The record loaded from the databae * * @return void */ public function onAfterGetItem(&$model, &$record) { if ($record instanceof F0FTable) { $keyName = $record->getKeyName(); if ($record->$keyName === null) { return; } $fieldName = $record->getColumnAlias('created_by'); // Make sure the field actually exists if (!in_array($fieldName, $record->getKnownFields())) { return; } $user_id = F0FPlatform::getInstance()->getUser()->id; if ($record->$fieldName != $user_id) { $record = null; } } } } PK tt!]�E��[ [ behavior/access.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class to filter front-end access to items * based on the viewing access levels. * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelBehaviorAccess extends F0FModelBehavior { /** * This event runs after we have built the query used to fetch a record * list in a model. It is used to apply automatic query filters. * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The model which calls this event * * @return void */ public function onAfterBuildQuery(&$model, &$query) { // This behavior only applies to the front-end. if (!F0FPlatform::getInstance()->isFrontend()) { return; } // Get the name of the access field $table = $model->getTable(); $accessField = $table->getColumnAlias('access'); // Make sure the field actually exists if (!in_array($accessField, $table->getKnownFields())) { return; } $model->applyAccessFiltering(null); } /** * The event runs after F0FModel has called F0FTable and retrieved a single * item from the database. It is used to apply automatic filters. * * @param F0FModel &$model The model which was called * @param F0FTable &$record The record loaded from the databae * * @return void */ public function onAfterGetItem(&$model, &$record) { if ($record instanceof F0FTable) { $fieldName = $record->getColumnAlias('access'); // Make sure the field actually exists if (!in_array($fieldName, $record->getKnownFields())) { return; } // Get the user $user = F0FPlatform::getInstance()->getUser(); // Filter by authorised access levels if (!in_array($record->$fieldName, $user->getAuthorisedViewLevels())) { $record = null; } } } } PK tt!]�vE�e e behavior/filters.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelBehaviorFilters extends F0FModelBehavior { /** * This event runs after we have built the query used to fetch a record * list in a model. It is used to apply automatic query filters. * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The model which calls this event * * @return void */ public function onAfterBuildQuery(&$model, &$query) { $table = $model->getTable(); $tableName = $table->getTableName(); $tableKey = $table->getKeyName(); $db = $model->getDBO(); $filterzero = $model->getState('_emptynonzero', null); $fields = $model->getTableFields(); $backlist = $model->blacklistFilters(); foreach ($fields as $fieldname => $fieldtype) { if (in_array($fieldname, $backlist)) { continue; } $field = new stdClass; $field->name = $fieldname; $field->type = $fieldtype; $field->filterzero = $filterzero; $filterName = ($field->name == $tableKey) ? 'id' : $field->name; $filterState = $model->getState($filterName, null); $field = F0FModelField::getField($field, array('dbo' => $db, 'table_alias' => $model->getTableAlias())); if ((is_array($filterState) && ( array_key_exists('value', $filterState) || array_key_exists('from', $filterState) || array_key_exists('to', $filterState) )) || is_object($filterState)) { $options = new JRegistry($filterState); } else { $options = new JRegistry; $options->set('value', $filterState); } $methods = $field->getSearchMethods(); $method = $options->get('method', $field->getDefaultSearchMethod()); if (!in_array($method, $methods)) { $method = 'exact'; } switch ($method) { case 'between': case 'outside': case 'range' : $sql = $field->$method($options->get('from', null), $options->get('to')); break; case 'interval': case 'modulo': $sql = $field->$method($options->get('value', null), $options->get('interval')); break; case 'exact': case 'partial': case 'search': default: $sql = $field->$method($options->get('value', null)); break; } if ($sql) { $query->where($sql); } } } } PK tt!]�Njn� � behavior/enabled.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class to filter front-end access to items * that are enabled. * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelBehaviorEnabled extends F0FModelBehavior { /** * This event runs after we have built the query used to fetch a record * list in a model. It is used to apply automatic query filters. * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The model which calls this event * * @return void */ public function onAfterBuildQuery(&$model, &$query) { // This behavior only applies to the front-end. if (!F0FPlatform::getInstance()->isFrontend()) { return; } // Get the name of the enabled field $table = $model->getTable(); $enabledField = $table->getColumnAlias('enabled'); // Make sure the field actually exists if (!in_array($enabledField, $table->getKnownFields())) { return; } // Filter by enabled fields only $db = F0FPlatform::getInstance()->getDbo(); // Alias $alias = $model->getTableAlias(); $alias = $alias ? $db->qn($alias) . '.' : ''; $query->where($alias . $db->qn($enabledField) . ' = ' . $db->q(1)); } /** * The event runs after F0FModel has called F0FTable and retrieved a single * item from the database. It is used to apply automatic filters. * * @param F0FModel &$model The model which was called * @param F0FTable &$record The record loaded from the databae * * @return void */ public function onAfterGetItem(&$model, &$record) { if ($record instanceof F0FTable) { $fieldName = $record->getColumnAlias('enabled'); // Make sure the field actually exists if (!in_array($fieldName, $record->getKnownFields())) { return; } if ($record->$fieldName != 1) { $record = null; } } } } PK tt!]�C��Z Z behavior/emptynonzero.phpnu &1i� <?php /** * @package FrameworkOnFramework * @subpackage model * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // Protect from unauthorized access defined('F0F_INCLUDED') or die; /** * FrameworkOnFramework model behavior class * * @package FrameworkOnFramework * @since 2.1 */ class F0FModelBehaviorEmptynonzero extends F0FModelBehavior { /** * This event runs when we are building the query used to fetch a record * list in a model * * @param F0FModel &$model The model which calls this event * @param F0FDatabaseQuery &$query The query being built * * @return void */ public function onBeforeBuildQuery(&$model, &$query) { $model->setState('_emptynonzero', '1'); } } PK ٌ!]��b b component.phpnu &1i� <?php /** * @package Joomla.Administrator * @subpackage com_config * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Model for component configuration * * @since 3.2 */ class ConfigModelComponent extends ConfigModelForm { /** * Method to auto-populate the model state. * * Note. Calling getState in this method will result in recursion. * * @return void * * @since 3.2 */ protected function populateState() { $input = JFactory::getApplication()->input; // Set the component (option) we are dealing with. $component = $input->get('component'); $state = $this->loadState(); $state->set('component.option', $component); // Set an alternative path for the configuration file. if ($path = $input->getString('path')) { $path = JPath::clean(JPATH_SITE . '/' . $path); JPath::check($path); $state->set('component.path', $path); } $this->setState($state); } /** * Method to get a form object. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * * @return mixed A JForm object on success, false on failure * * @since 3.2 */ public function getForm($data = array(), $loadData = true) { $state = $this->getState(); $option = $state->get('component.option'); if ($path = $state->get('component.path')) { // Add the search path for the admin component config.xml file. JForm::addFormPath($path); } else { // Add the search path for the admin component config.xml file. JForm::addFormPath(JPATH_ADMINISTRATOR . '/components/' . $option); } // Get the form. $form = $this->loadForm( 'com_config.component', 'config', array('control' => 'jform', 'load_data' => $loadData), false, '/config' ); if (empty($form)) { return false; } $lang = JFactory::getLanguage(); $lang->load($option, JPATH_BASE, null, false, true) || $lang->load($option, JPATH_BASE . "/components/$option", null, false, true); return $form; } /** * Get the component information. * * @return object * * @since 3.2 */ public function getComponent() { $state = $this->getState(); $option = $state->get('component.option'); // Load common and local language files. $lang = JFactory::getLanguage(); $lang->load($option, JPATH_BASE, null, false, true) || $lang->load($option, JPATH_BASE . "/components/$option", null, false, true); $result = JComponentHelper::getComponent($option); return $result; } /** * Method to save the configuration data. * * @param array $data An array containing all global config data. * * @return boolean True on success, false on failure. * * @since 3.2 * @throws RuntimeException */ public function save($data) { $table = JTable::getInstance('extension'); $dispatcher = JEventDispatcher::getInstance(); $context = $this->option . '.' . $this->name; JPluginHelper::importPlugin('extension'); // Check super user group. if (isset($data['params']) && !JFactory::getUser()->authorise('core.admin')) { $form = $this->getForm(array(), false); foreach ($form->getFieldsets() as $fieldset) { foreach ($form->getFieldset($fieldset->name) as $field) { if ($field->type === 'UserGroupList' && isset($data['params'][$field->fieldname]) && (int) $field->getAttribute('checksuperusergroup', 0) === 1 && JAccess::checkGroup($data['params'][$field->fieldname], 'core.admin')) { throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); } } } } // Save the rules. if (isset($data['params']) && isset($data['params']['rules'])) { if (!JFactory::getUser()->authorise('core.admin', $data['option'])) { throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); } $rules = new JAccessRules($data['params']['rules']); $asset = JTable::getInstance('asset'); if (!$asset->loadByName($data['option'])) { $root = JTable::getInstance('asset'); $root->loadByName('root.1'); $asset->name = $data['option']; $asset->title = $data['option']; $asset->setLocation($root->id, 'last-child'); } $asset->rules = (string) $rules; if (!$asset->check() || !$asset->store()) { throw new RuntimeException($asset->getError()); } // We don't need this anymore unset($data['option']); unset($data['params']['rules']); } // Load the previous Data if (!$table->load($data['id'])) { throw new RuntimeException($table->getError()); } unset($data['id']); // Bind the data. if (!$table->bind($data)) { throw new RuntimeException($table->getError()); } // Check the data. if (!$table->check()) { throw new RuntimeException($table->getError()); } $result = $dispatcher->trigger('onExtensionBeforeSave', array($context, $table, false)); // Store the data. if (in_array(false, $result, true) || !$table->store()) { throw new RuntimeException($table->getError()); } // Trigger the after save event. $dispatcher->trigger('onExtensionAfterSave', array($context, $table, false)); // Clean the component cache. $this->cleanCache('_system', 0); $this->cleanCache('_system', 1); return true; } } PK ٌ!]���� � field/filters.phpnu &1i� <?php /** * @package Joomla.Administrator * @subpackage com_config * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Text Filters form field. * * @since 1.6 */ class JFormFieldFilters extends JFormField { /** * The form field type. * * @var string * @since 1.6 */ public $type = 'Filters'; /** * Method to get the field input markup. * * TODO: Add access check. * * @return string The field input markup. * * @since 1.6 */ protected function getInput() { // Load Framework JHtml::_('jquery.framework'); // Add translation string for notification JText::script('COM_CONFIG_TEXT_FILTERS_NOTE'); // Add Javascript $doc = JFactory::getDocument(); $doc->addScriptDeclaration(' jQuery( document ).ready(function( $ ) { $("#filter-config select").change(function() { var currentFilter = $(this).children("option:selected").val(); if($(this).children("option:selected").val() === "NONE") { var child = $("#filter-config select[data-parent=" + $(this).attr("data-id") + "]"); while(child.length !== 0) { if(child.children("option:selected").val() !== "NONE") { alert(Joomla.JText._("COM_CONFIG_TEXT_FILTERS_NOTE")); break; } child = $("#filter-config select[data-parent=" + child.attr("data-id") + "]"); } return; } var parent = $("#filter-config select[data-id=" + $(this).attr("data-parent") + "]"); while(parent.length !== 0) { if(parent.children("option:selected").val() === "NONE") { alert(Joomla.JText._("COM_CONFIG_TEXT_FILTERS_NOTE")); break; } parent = $("#filter-config select[data-id=" + parent.attr("data-parent") + "]") } }); }); '); // Get the available user groups. $groups = $this->getUserGroups(); // Build the form control. $html = array(); // Open the table. $html[] = '<table id="filter-config" class="table table-striped">'; // The table heading. $html[] = ' <thead>'; $html[] = ' <tr>'; $html[] = ' <th>'; $html[] = ' <span class="acl-action">' . JText::_('JGLOBAL_FILTER_GROUPS_LABEL') . '</span>'; $html[] = ' </th>'; $html[] = ' <th>'; $html[] = ' <span class="acl-action">' . JText::_('JGLOBAL_FILTER_TYPE_LABEL') . '</span>'; $html[] = ' </th>'; $html[] = ' <th>'; $html[] = ' <span class="acl-action">' . JText::_('JGLOBAL_FILTER_TAGS_LABEL') . '</span>'; $html[] = ' </th>'; $html[] = ' <th>'; $html[] = ' <span class="acl-action">' . JText::_('JGLOBAL_FILTER_ATTRIBUTES_LABEL') . '</span>'; $html[] = ' </th>'; $html[] = ' </tr>'; $html[] = ' </thead>'; // The table body. $html[] = ' <tbody>'; foreach ($groups as $group) { if (!isset($this->value[$group->value])) { $this->value[$group->value] = array('filter_type' => 'BL', 'filter_tags' => '', 'filter_attributes' => ''); } $group_filter = $this->value[$group->value]; $group_filter['filter_tags'] = !empty($group_filter['filter_tags']) ? $group_filter['filter_tags'] : ''; $group_filter['filter_attributes'] = !empty($group_filter['filter_attributes']) ? $group_filter['filter_attributes'] : ''; $html[] = ' <tr>'; $html[] = ' <td class="acl-groups left">'; $html[] = ' ' . JLayoutHelper::render('joomla.html.treeprefix', array('level' => $group->level + 1)) . $group->text; $html[] = ' </td>'; $html[] = ' <td>'; $html[] = ' <select' . ' name="' . $this->name . '[' . $group->value . '][filter_type]"' . ' id="' . $this->id . $group->value . '_filter_type"' . ' data-parent="' . ($group->parent) . '" ' . ' data-id="' . ($group->value) . '" ' . ' class="novalidate"' . '>'; $html[] = ' <option value="BL"' . ($group_filter['filter_type'] == 'BL' ? ' selected="selected"' : '') . '>' . JText::_('COM_CONFIG_FIELD_FILTERS_DEFAULT_BLACK_LIST') . '</option>'; $html[] = ' <option value="CBL"' . ($group_filter['filter_type'] == 'CBL' ? ' selected="selected"' : '') . '>' . JText::_('COM_CONFIG_FIELD_FILTERS_CUSTOM_BLACK_LIST') . '</option>'; $html[] = ' <option value="WL"' . ($group_filter['filter_type'] == 'WL' ? ' selected="selected"' : '') . '>' . JText::_('COM_CONFIG_FIELD_FILTERS_WHITE_LIST') . '</option>'; $html[] = ' <option value="NH"' . ($group_filter['filter_type'] == 'NH' ? ' selected="selected"' : '') . '>' . JText::_('COM_CONFIG_FIELD_FILTERS_NO_HTML') . '</option>'; $html[] = ' <option value="NONE"' . ($group_filter['filter_type'] == 'NONE' ? ' selected="selected"' : '') . '>' . JText::_('COM_CONFIG_FIELD_FILTERS_NO_FILTER') . '</option>'; $html[] = ' </select>'; $html[] = ' </td>'; $html[] = ' <td>'; $html[] = ' <input' . ' name="' . $this->name . '[' . $group->value . '][filter_tags]"' . ' type="text"' . ' id="' . $this->id . $group->value . '_filter_tags" class="novalidate"' . ' value="' . htmlspecialchars($group_filter['filter_tags'], ENT_QUOTES) . '"' . '/>'; $html[] = ' </td>'; $html[] = ' <td>'; $html[] = ' <input' . ' name="' . $this->name . '[' . $group->value . '][filter_attributes]"' . ' type="text"' . ' id="' . $this->id . $group->value . '_filter_attributes" class="novalidate"' . ' value="' . htmlspecialchars($group_filter['filter_attributes'], ENT_QUOTES) . '"' . '/>'; $html[] = ' </td>'; $html[] = ' </tr>'; } $html[] = ' </tbody>'; // Close the table. $html[] = '</table>'; // Add notes $html[] = '<div class="alert">'; $html[] = '<p>' . JText::_('JGLOBAL_FILTER_TYPE_DESC') . '</p>'; $html[] = '<p>' . JText::_('JGLOBAL_FILTER_TAGS_DESC') . '</p>'; $html[] = '<p>' . JText::_('JGLOBAL_FILTER_ATTRIBUTES_DESC') . '</p>'; $html[] = '</div>'; return implode("\n", $html); } /** * A helper to get the list of user groups. * * @return array * * @since 1.6 */ protected function getUserGroups() { // Get a database object. $db = JFactory::getDbo(); // Get the user groups from the database. $query = $db->getQuery(true); $query->select('a.id AS value, a.title AS text, COUNT(DISTINCT b.id) AS level, a.parent_id as parent'); $query->from('#__usergroups AS a'); $query->join('LEFT', '#__usergroups AS b on a.lft > b.lft AND a.rgt < b.rgt'); $query->group('a.id, a.title, a.lft'); $query->order('a.lft ASC'); $db->setQuery($query); $options = $db->loadObjectList(); return $options; } } PK ٌ!]3(2�$ $ field/configcomponents.phpnu &1i� <?php /** * @package Joomla.Administrator * @subpackage com_config * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Utilities\ArrayHelper; JFormHelper::loadFieldClass('List'); /** * Text Filters form field. * * @since 3.7.0 */ class JFormFieldConfigComponents extends JFormFieldList { /** * The form field type. * * @var string * @since 3.7.0 */ public $type = 'ConfigComponents'; /** * Method to get a list of options for a list input. * * @return array An array of JHtml options. * * @since 3.7.0 */ protected function getOptions() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('name AS text, element AS value') ->from('#__extensions') ->where('enabled >= 1') ->where('type =' . $db->quote('component')); $items = $db->setQuery($query)->loadObjectList(); if ($items) { $lang = JFactory::getLanguage(); foreach ($items as &$item) { // Load language $extension = $item->value; if (JFile::exists(JPATH_ADMINISTRATOR . '/components/' . $extension . '/config.xml')) { $source = JPATH_ADMINISTRATOR . '/components/' . $extension; $lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true) || $lang->load("$extension.sys", $source, null, false, true); // Translate component name $item->text = JText::_($item->text); } else { $item = null; } } // Sort by component name $items = ArrayHelper::sortObjects(array_filter($items), 'text', 1, true, true); } // Merge any additional options in the XML definition. $options = array_merge(parent::getOptions(), $items); return $options; } } PK ٌ!]�Fl�v �v form/application.xmlnu &1i� <?xml version="1.0" encoding="utf-8"?> <form> <fieldset name="cache" label="COM_CONFIG_CACHE_SETTINGS_LABEL"> <field name="cache_handler" type="cachehandler" label="COM_CONFIG_FIELD_CACHE_HANDLER_LABEL" description="COM_CONFIG_FIELD_CACHE_HANDLER_DESC" default="" filter="word" /> <field name="cache_path" type="text" label="COM_CONFIG_FIELD_CACHE_PATH_LABEL" description="COM_CONFIG_FIELD_CACHE_PATH_DESC" showon="cache_handler:file" filter="string" size="50" /> <field name="memcache_persist" type="radio" label="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_DESC" class="btn-group btn-group-yesno" default="1" showon="cache_handler:memcache" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="memcache_compress" type="radio" label="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_DESC" class="btn-group btn-group-yesno" default="0" showon="cache_handler:memcache" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="memcache_server_host" type="text" label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC" default="localhost" showon="cache_handler:memcache" filter="string" size="25" /> <field name="memcache_server_port" type="number" label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC" showon="cache_handler:memcache" min="0" max="65535" default="11211" filter="integer" validate="number" size="5" /> <field name="memcached_persist" type="radio" label="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_DESC" class="btn-group btn-group-yesno" default="1" showon="cache_handler:memcached" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="memcached_compress" type="radio" label="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_DESC" class="btn-group btn-group-yesno" default="0" showon="cache_handler:memcached" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="memcached_server_host" type="text" label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC" default="localhost" showon="cache_handler:memcached" filter="string" size="25" /> <field name="memcached_server_port" type="number" label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC" showon="cache_handler:memcached" min="0" max="65535" default="11211" filter="integer" validate="number" size="5" /> <field name="redis_persist" type="radio" label="COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL" description="COM_CONFIG_FIELD_REDIS_PERSISTENT_DESC" class="btn-group btn-group-yesno" default="1" filter="integer" showon="cache_handler:redis" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="redis_server_host" type="text" label="COM_CONFIG_FIELD_REDIS_HOST_LABEL" description="COM_CONFIG_FIELD_REDIS_HOST_DESC" default="localhost" filter="string" showon="cache_handler:redis" size="25" /> <field name="redis_server_port" type="number" label="COM_CONFIG_FIELD_REDIS_PORT_LABEL" description="COM_CONFIG_FIELD_REDIS_PORT_DESC" showon="cache_handler:redis" min="1" max="65535" default="6379" filter="integer" validate="number" size="5" /> <field name="redis_server_auth" type="password" label="COM_CONFIG_FIELD_REDIS_AUTH_LABEL" description="COM_CONFIG_FIELD_REDIS_AUTH_DESC" filter="raw" showon="cache_handler:redis" autocomplete="off" size="30" hint="***************" lock="true" /> <field name="redis_server_db" type="number" label="COM_CONFIG_FIELD_REDIS_DB_LABEL" description="COM_CONFIG_FIELD_REDIS_DB_DESC" default="0" filter="integer" showon="cache_handler:redis" size="4" /> <field name="cachetime" type="number" label="COM_CONFIG_FIELD_CACHE_TIME_LABEL" description="COM_CONFIG_FIELD_CACHE_TIME_DESC" min="1" default="15" filter="integer" validate="number" size="6" /> <field name="cache_platformprefix" type="radio" label="COM_CONFIG_FIELD_CACHE_PLATFORMPREFIX_LABEL" description="COM_CONFIG_FIELD_CACHE_PLATFORMPREFIX_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="caching" type="list" label="COM_CONFIG_FIELD_CACHE_LABEL" description="COM_CONFIG_FIELD_CACHE_DESC" default="2" filter="integer" > <option value="0">COM_CONFIG_FIELD_VALUE_CACHE_OFF</option> <option value="1">COM_CONFIG_FIELD_VALUE_CACHE_CONSERVATIVE</option> <option value="2">COM_CONFIG_FIELD_VALUE_CACHE_PROGRESSIVE</option> </field> </fieldset> <fieldset name="memcache" label="COM_CONFIG_MEMCACHE_SETTINGS_LABEL"> </fieldset> <fieldset name="database" label="CONFIG_DATABASE_SETTINGS_LABEL"> <field name="dbtype" type="databaseconnection" label="COM_CONFIG_FIELD_DATABASE_TYPE_LABEL" description="COM_CONFIG_FIELD_DATABASE_TYPE_DESC" supported="mysql,mysqli,pgsql,pdomysql,postgresql,sqlsrv,sqlazure" filter="string" /> <field name="host" type="text" label="COM_CONFIG_FIELD_DATABASE_HOST_LABEL" description="COM_CONFIG_FIELD_DATABASE_HOST_DESC" required="true" filter="string" size="30" /> <field name="user" type="text" label="COM_CONFIG_FIELD_DATABASE_USERNAME_LABEL" description="COM_CONFIG_FIELD_DATABASE_USERNAME_DESC" required="true" filter="string" size="30" /> <field name="password" type="password" label="COM_CONFIG_FIELD_DATABASE_PASSWORD_LABEL" description="COM_CONFIG_FIELD_DATABASE_PASSWORD_DESC" filter="raw" autocomplete="off" size="30" lock="true" /> <field name="db" type="text" label="COM_CONFIG_FIELD_DATABASE_NAME_LABEL" description="COM_CONFIG_FIELD_DATABASE_NAME_DESC" required="true" filter="string" size="30" /> <field name="dbprefix" type="text" label="COM_CONFIG_FIELD_DATABASE_PREFIX_LABEL" description="COM_CONFIG_FIELD_DATABASE_PREFIX_DESC" default="jos_" filter="string" size="10" /> </fieldset> <fieldset name="debug" label="CONFIG_DEBUG_SETTINGS_LABEL"> <field name="debug" type="radio" label="COM_CONFIG_FIELD_DEBUG_SYSTEM_LABEL" description="COM_CONFIG_FIELD_DEBUG_SYSTEM_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="debug_lang" type="radio" label="COM_CONFIG_FIELD_DEBUG_LANG_LABEL" description="COM_CONFIG_FIELD_DEBUG_LANG_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="debug_lang_const" type="radio" label="COM_CONFIG_FIELD_DEBUG_CONST_LANG_LABEL" description="COM_CONFIG_FIELD_DEBUG_CONST_LANG_DESC" class="btn-group btn-group-yesno" default="1" filter="integer" showon="debug_lang:1" > <option value="0">COM_CONFIG_FIELD_DEBUG_CONST</option> <option value="1">COM_CONFIG_FIELD_DEBUG_VALUE</option> </field> </fieldset> <fieldset name="ftp" label="CONFIG_FTP_SETTINGS_LABEL"> <field name="ftp_enable" type="radio" label="COM_CONFIG_FIELD_FTP_ENABLE_LABEL" description="COM_CONFIG_FIELD_FTP_ENABLE_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="ftp_host" type="text" label="COM_CONFIG_FIELD_FTP_HOST_LABEL" description="COM_CONFIG_FIELD_FTP_HOST_DESC" filter="string" showon="ftp_enable:1" size="14" /> <field name="ftp_port" type="number" label="COM_CONFIG_FIELD_FTP_PORT_LABEL" description="COM_CONFIG_FIELD_FTP_PORT_DESC" showon="ftp_enable:1" min="1" max="65535" hint="21" validate="number" filter="integer" size="5" /> <field name="ftp_user" type="text" label="COM_CONFIG_FIELD_FTP_USERNAME_LABEL" description="COM_CONFIG_FIELD_FTP_USERNAME_DESC" filter="string" showon="ftp_enable:1" autocomplete="off" size="25" /> <field name="ftp_pass" type="password" label="COM_CONFIG_FIELD_FTP_PASSWORD_LABEL" description="COM_CONFIG_FIELD_FTP_PASSWORD_DESC" filter="raw" showon="ftp_enable:1" autocomplete="off" size="25" lock="true" /> <field name="ftp_root" type="text" label="COM_CONFIG_FIELD_FTP_ROOT_LABEL" description="COM_CONFIG_FIELD_FTP_ROOT_DESC" showon="ftp_enable:1" filter="string" size="50" /> </fieldset> <fieldset name="proxy" label="CONFIG_PROXY_SETTINGS_LABEL"> <field name="behind_loadbalancer" type="radio" label="COM_CONFIG_FIELD_LOADBALANCER_ENABLE_LABEL" description="COM_CONFIG_FIELD_LOADBALANCER_ENABLE_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="proxy_enable" type="radio" label="COM_CONFIG_FIELD_PROXY_ENABLE_LABEL" description="COM_CONFIG_FIELD_PROXY_ENABLE_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="proxy_host" type="text" label="COM_CONFIG_FIELD_PROXY_HOST_LABEL" description="COM_CONFIG_FIELD_PROXY_HOST_DESC" filter="string" showon="proxy_enable:1" size="14" /> <field name="proxy_port" type="number" label="COM_CONFIG_FIELD_PROXY_PORT_LABEL" description="COM_CONFIG_FIELD_PROXY_PORT_DESC" showon="proxy_enable:1" min="1" max="65535" hint="8080" validate="number" filter="integer" size="5" /> <field name="proxy_user" type="text" label="COM_CONFIG_FIELD_PROXY_USERNAME_LABEL" description="COM_CONFIG_FIELD_PROXY_USERNAME_DESC" filter="string" showon="proxy_enable:1" autocomplete="off" size="25" /> <field name="proxy_pass" type="password" label="COM_CONFIG_FIELD_PROXY_PASSWORD_LABEL" description="COM_CONFIG_FIELD_PROXY_PASSWORD_DESC" filter="raw" showon="proxy_enable:1" autocomplete="off" size="25" lock="true" /> </fieldset> <fieldset name="locale" label="CONFIG_LOCATION_SETTINGS_LABEL"> <field name="offset" type="timezone" label="COM_CONFIG_FIELD_SERVER_TIMEZONE_LABEL" description="COM_CONFIG_FIELD_SERVER_TIMEZONE_DESC" default="UTC" > <option value="UTC">JLIB_FORM_VALUE_TIMEZONE_UTC</option> </field> </fieldset> <fieldset name="mail" label="CONFIG_MAIL_SETTINGS_LABEL"> <field name="mailonline" type="radio" label="COM_CONFIG_FIELD_MAIL_MAILONLINE_LABEL" description="COM_CONFIG_FIELD_MAIL_MAILONLINE_DESC" class="btn-group btn-group-yesno" default="1" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="massmailoff" type="radio" label="COM_CONFIG_FIELD_MAIL_MASSMAILOFF_LABEL" description="COM_CONFIG_FIELD_MAIL_MASSMAILOFF_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" showon="mailonline:1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="mailfrom" type="email" label="COM_CONFIG_FIELD_MAIL_FROM_EMAIL_LABEL" description="COM_CONFIG_FIELD_MAIL_FROM_EMAIL_DESC" filter="string" size="30" validate="email" showon="mailonline:1" /> <field name="fromname" type="text" label="COM_CONFIG_FIELD_MAIL_FROM_NAME_LABEL" description="COM_CONFIG_FIELD_MAIL_FROM_NAME_DESC" filter="string" size="30" showon="mailonline:1" /> <field name="replyto" type="email" label="COM_CONFIG_FIELD_MAIL_REPLY_TO_EMAIL_LABEL" description="COM_CONFIG_FIELD_MAIL_REPLY_TO_EMAIL_DESC" filter="string" size="30" validate="email" showon="mailonline:1" /> <field name="replytoname" type="text" label="COM_CONFIG_FIELD_MAIL_REPLY_TO_NAME_LABEL" description="COM_CONFIG_FIELD_MAIL_REPLY_TO_NAME_DESC" filter="string" size="30" showon="mailonline:1" /> <field name="mailer" type="list" label="COM_CONFIG_FIELD_MAIL_MAILER_LABEL" description="COM_CONFIG_FIELD_MAIL_MAILER_DESC" default="mail" filter="word" showon="mailonline:1" > <option value="mail">COM_CONFIG_FIELD_VALUE_PHP_MAIL</option> <option value="sendmail">COM_CONFIG_FIELD_VALUE_SENDMAIL</option> <option value="smtp">COM_CONFIG_FIELD_VALUE_SMTP</option> </field> <field name="sendmail" type="text" label="COM_CONFIG_FIELD_MAIL_SENDMAIL_PATH_LABEL" description="COM_CONFIG_FIELD_MAIL_SENDMAIL_PATH_DESC" default="/usr/sbin/sendmail" showon="mailonline:1[AND]mailer:sendmail" filter="string" size="30" /> <field name="smtphost" type="text" label="COM_CONFIG_FIELD_MAIL_SMTP_HOST_LABEL" description="COM_CONFIG_FIELD_MAIL_SMTP_HOST_DESC" default="localhost" showon="mailonline:1[AND]mailer:smtp" filter="string" size="30" /> <field name="smtpport" type="number" label="COM_CONFIG_FIELD_MAIL_SMTP_PORT_LABEL" description="COM_CONFIG_FIELD_MAIL_SMTP_PORT_DESC" showon="mailonline:1[AND]mailer:smtp" min="1" max="65535" default="25" hint="25" validate="number" filter="integer" size="5" /> <field name="smtpsecure" type="list" label="COM_CONFIG_FIELD_MAIL_SMTP_SECURE_LABEL" description="COM_CONFIG_FIELD_MAIL_SMTP_SECURE_DESC" default="none" showon="mailonline:1[AND]mailer:smtp" filter="word" > <option value="none">COM_CONFIG_FIELD_VALUE_NONE</option> <option value="ssl">COM_CONFIG_FIELD_VALUE_SSL</option> <option value="tls">COM_CONFIG_FIELD_VALUE_TLS</option> </field> <field name="smtpauth" type="radio" label="COM_CONFIG_FIELD_MAIL_SMTP_AUTH_LABEL" description="COM_CONFIG_FIELD_MAIL_SMTP_AUTH_DESC" class="btn-group btn-group-yesno" default="0" showon="mailonline:1[AND]mailer:smtp" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="smtpuser" type="text" label="COM_CONFIG_FIELD_MAIL_SMTP_USERNAME_LABEL" description="COM_CONFIG_FIELD_MAIL_SMTP_USERNAME_DESC" showon="mailonline:1[AND]mailer:smtp[AND]smtpauth:1" filter="string" autocomplete="off" size="30" /> <field name="smtppass" type="password" label="COM_CONFIG_FIELD_MAIL_SMTP_PASSWORD_LABEL" description="COM_CONFIG_FIELD_MAIL_SMTP_PASSWORD_DESC" showon="mailonline:1[AND]mailer:smtp[AND]smtpauth:1" filter="raw" autocomplete="off" size="30" lock="true" /> </fieldset> <fieldset name="metadata" label="COM_CONFIG_METADATA_SETTINGS"> <field name="MetaDesc" type="textarea" label="COM_CONFIG_FIELD_METADESC_LABEL" description="COM_CONFIG_FIELD_METADESC_DESC" filter="string" cols="60" rows="3" /> <field name="MetaKeys" type="textarea" label="COM_CONFIG_FIELD_METAKEYS_LABEL" description="COM_CONFIG_FIELD_METAKEYS_DESC" filter="string" cols="60" rows="3" /> <field name="robots" type="list" label="JFIELD_METADATA_ROBOTS_LABEL" description="JFIELD_METADATA_ROBOTS_DESC" default="" > <option value="">index, follow</option> <option value="noindex, follow"></option> <option value="index, nofollow"></option> <option value="noindex, nofollow"></option> </field> <field name="MetaRights" type="textarea" label="JFIELD_META_RIGHTS_LABEL" description="JFIELD_META_RIGHTS_DESC" filter="string" cols="60" rows="2" /> <field name="MetaAuthor" type="radio" label="COM_CONFIG_FIELD_METAAUTHOR_LABEL" description="COM_CONFIG_FIELD_METAAUTHOR_DESC" class="btn-group btn-group-yesno" default="1" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="MetaVersion" type="radio" label="COM_CONFIG_FIELD_METAVERSION_LABEL" description="COM_CONFIG_FIELD_METAVERSION_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> </fieldset> <fieldset name="seo" label="CONFIG_SEO_SETTINGS_LABEL"> <field name="sef" type="radio" label="COM_CONFIG_FIELD_SEF_URL_LABEL" description="COM_CONFIG_FIELD_SEF_URL_DESC" class="btn-group btn-group-yesno" default="1" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="sef_rewrite" type="radio" label="COM_CONFIG_FIELD_SEF_REWRITE_LABEL" description="COM_CONFIG_FIELD_SEF_REWRITE_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" showon="sef:1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="sef_suffix" type="radio" label="COM_CONFIG_FIELD_SEF_SUFFIX_LABEL" description="COM_CONFIG_FIELD_SEF_SUFFIX_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" showon="sef:1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="unicodeslugs" type="radio" label="COM_CONFIG_FIELD_UNICODESLUGS_LABEL" description="COM_CONFIG_FIELD_UNICODESLUGS_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" showon="sef:1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="sitename_pagetitles" type="list" label="COM_CONFIG_FIELD_SITENAME_PAGETITLES_LABEL" description="COM_CONFIG_FIELD_SITENAME_PAGETITLES_DESC" default="0" filter="integer" > <option value="2">COM_CONFIG_FIELD_VALUE_AFTER</option> <option value="1">COM_CONFIG_FIELD_VALUE_BEFORE</option> <option value="0">JNO</option> </field> </fieldset> <fieldset name="server" label="CONFIG_SERVER_SETTINGS_LABEL"> <field name="tmp_path" type="text" label="COM_CONFIG_FIELD_TEMP_PATH_LABEL" description="COM_CONFIG_FIELD_TEMP_PATH_DESC" filter="string" size="50" /> <field name="gzip" type="radio" label="COM_CONFIG_FIELD_GZIP_COMPRESSION_LABEL" description="COM_CONFIG_FIELD_GZIP_COMPRESSION_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="error_reporting" type="list" label="COM_CONFIG_FIELD_ERROR_REPORTING_LABEL" description="COM_CONFIG_FIELD_ERROR_REPORTING_DESC" default="default" filter="cmd" > <option value="default">COM_CONFIG_FIELD_VALUE_SYSTEM_DEFAULT</option> <option value="none">COM_CONFIG_FIELD_VALUE_NONE</option> <option value="simple">COM_CONFIG_FIELD_VALUE_SIMPLE</option> <option value="maximum">COM_CONFIG_FIELD_VALUE_MAXIMUM</option> <option value="development">COM_CONFIG_FIELD_VALUE_DEVELOPMENT</option> </field> <field name="force_ssl" type="list" label="COM_CONFIG_FIELD_FORCE_SSL_LABEL" description="COM_CONFIG_FIELD_FORCE_SSL_DESC" default="-1" filter="integer" > <option value="0">COM_CONFIG_FIELD_VALUE_NONE</option> <option value="1">COM_CONFIG_FIELD_VALUE_ADMINISTRATOR_ONLY</option> <option value="2">COM_CONFIG_FIELD_VALUE_ENTIRE_SITE</option> </field> </fieldset> <fieldset name="session" label="CONFIG_SESSION_SETTINGS_LABEL"> <field name="session_handler" type="sessionhandler" label="COM_CONFIG_FIELD_SESSION_HANDLER_LABEL" description="COM_CONFIG_FIELD_SESSION_HANDLER_DESC" default="none" filter="word" /> <field name="session_memcache_server_host" type="text" label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC" default="localhost" filter="string" showon="session_handler:memcache" size="25" /> <field name="session_memcache_server_port" type="number" label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC" showon="session_handler:memcache" min="1" max="65535" default="11211" validate="number" filter="integer" size="5" /> <field name="session_memcached_server_host" type="text" label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC" default="localhost" filter="string" showon="session_handler:memcached" size="25" /> <field name="session_memcached_server_port" type="number" label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL" description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC" showon="session_handler:memcached" min="1" max="65535" default="11211" validate="number" filter="integer" size="5" /> <field name="session_redis_persist" type="radio" label="COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL" description="COM_CONFIG_FIELD_REDIS_PERSISTENT_DESC" class="btn-group btn-group-yesno" default="1" filter="integer" showon="session_handler:redis" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="session_redis_server_host" type="text" label="COM_CONFIG_FIELD_REDIS_HOST_LABEL" description="COM_CONFIG_FIELD_REDIS_HOST_DESC" default="localhost" filter="string" showon="session_handler:redis" size="25" /> <field name="session_redis_server_port" type="number" label="COM_CONFIG_FIELD_REDIS_PORT_LABEL" description="COM_CONFIG_FIELD_REDIS_PORT_DESC" showon="session_handler:redis" min="1" max="65535" default="6379" validate="number" filter="integer" size="5" /> <field name="session_redis_server_auth" type="password" label="COM_CONFIG_FIELD_REDIS_AUTH_LABEL" description="COM_CONFIG_FIELD_REDIS_AUTH_DESC" filter="raw" showon="session_handler:redis" autocomplete="off" size="30" lock="true" /> <field name="session_redis_server_db" type="number" label="COM_CONFIG_FIELD_REDIS_DB_LABEL" description="COM_CONFIG_FIELD_REDIS_DB_DESC" default="0" filter="integer" showon="session_handler:redis" size="4" /> <field name="lifetime" type="number" label="COM_CONFIG_FIELD_SESSION_TIME_LABEL" description="COM_CONFIG_FIELD_SESSION_TIME_DESC" min="1" max="16383" default="15" filter="integer" validate="number" size="6" /> <field name="shared_session" type="radio" label="COM_CONFIG_FIELD_SHARED_SESSION_LABEL" description="COM_CONFIG_FIELD_SHARED_SESSION_DESC" class="btn-group btn-group-yesno" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> </fieldset> <fieldset name="site" label="CONFIG_SITE_SETTINGS_LABEL"> <field name="sitename" type="text" label="COM_CONFIG_FIELD_SITE_NAME_LABEL" description="COM_CONFIG_FIELD_SITE_NAME_DESC" required="true" filter="string" size="50" /> <field name="offline" type="radio" label="COM_CONFIG_FIELD_SITE_OFFLINE_LABEL" description="COM_CONFIG_FIELD_SITE_OFFLINE_DESC" class="btn-group btn-group-yesno btn-group-reversed" default="0" filter="integer" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="display_offline_message" type="list" label="COM_CONFIG_FIELD_SITE_DISPLAY_MESSAGE_LABEL" description="COM_CONFIG_FIELD_SITE_DISPLAY_MESSAGE_DESC" default="1" filter="integer" showon="offline:1" > <option value="0">JHIDE</option> <option value="1">COM_CONFIG_FIELD_VALUE_DISPLAY_OFFLINE_MESSAGE_CUSTOM</option> <option value="2">COM_CONFIG_FIELD_VALUE_DISPLAY_OFFLINE_MESSAGE_LANGUAGE</option> </field> <field name="offline_message" type="textarea" label="COM_CONFIG_FIELD_OFFLINE_MESSAGE_LABEL" description="COM_CONFIG_FIELD_OFFLINE_MESSAGE_DESC" filter="safehtml" cols="60" rows="2" showon="offline:1[AND]display_offline_message:1" /> <field name="offline_image" type="media" label="COM_CONFIG_FIELD_OFFLINE_IMAGE_LABEL" description="COM_CONFIG_FIELD_OFFLINE_IMAGE_DESC" showon="offline:1" /> <field name="frontediting" type="list" label="COM_CONFIG_FRONTEDITING_LABEL" description="COM_CONFIG_FRONTEDITING_DESC" default="1" filter="integer" > <option value="2">COM_CONFIG_FRONTEDITING_MENUSANDMODULES</option> <option value="1">COM_CONFIG_FRONTEDITING_MODULES</option> <option value="0">JNONE</option> </field> <field name="editor" type="plugins" label="COM_CONFIG_FIELD_DEFAULT_EDITOR_LABEL" description="COM_CONFIG_FIELD_DEFAULT_EDITOR_DESC" folder="editors" default="tinymce" filter="cmd" /> <field name="captcha" type="plugins" label="COM_CONFIG_FIELD_DEFAULT_CAPTCHA_LABEL" description="COM_CONFIG_FIELD_DEFAULT_CAPTCHA_DESC" folder="captcha" default="0" filter="cmd" > <option value="0">JOPTION_DO_NOT_USE</option> </field> <field name="access" type="accesslevel" label="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_LABEL" description="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_DESC" default="1" filter="integer" /> <field name="list_limit" type="list" label="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_LABEL" description="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_DESC" default="20" filter="integer" > <option value="5">J5</option> <option value="10">J10</option> <option value="15">J15</option> <option value="20">J20</option> <option value="25">J25</option> <option value="30">J30</option> <option value="50">J50</option> <option value="100">J100</option> <option value="200">J200</option> <option value="500">J500</option> </field> <field name="feed_limit" type="list" label="COM_CONFIG_FIELD_DEFAULT_FEED_LIMIT_LABEL" description="COM_CONFIG_FIELD_DEFAULT_FEED_LIMIT_DESC" default="10" filter="integer" > <option value="5">J5</option> <option value="10">J10</option> <option value="15">J15</option> <option value="20">J20</option> <option value="25">J25</option> <option value="30">J30</option> <option value="50">J50</option> <option value="100">J100</option> </field> <field name="feed_email" type="list" label="COM_CONFIG_FIELD_FEED_EMAIL_LABEL" description="COM_CONFIG_FIELD_FEED_EMAIL_DESC" default="none" filter="word" > <option value="author">COM_CONFIG_FIELD_VALUE_AUTHOR_EMAIL</option> <option value="site">COM_CONFIG_FIELD_VALUE_SITE_EMAIL</option> <option value="none">COM_CONFIG_FIELD_VALUE_NO_EMAIL</option> </field> </fieldset> <fieldset name="system" label="CONFIG_SYSTEM_SETTINGS_LABEL"> <field name="log_path" type="text" label="COM_CONFIG_FIELD_LOG_PATH_LABEL" description="COM_CONFIG_FIELD_LOG_PATH_DESC" required="true" filter="string" size="50" /> </fieldset> <fieldset name="cookie" label="CONFIG_COOKIE_SETTINGS_LABEL"> <field name="cookie_domain" type="text" label="COM_CONFIG_FIELD_COOKIE_DOMAIN_LABEL" description="COM_CONFIG_FIELD_COOKIE_DOMAIN_DESC" filter="string" size="40" /> <field name="cookie_path" type="text" label="COM_CONFIG_FIELD_COOKIE_PATH_LABEL" description="COM_CONFIG_FIELD_COOKIE_PATH_DESC" filter="string" size="40" /> </fieldset> <fieldset name="permissions" label="CONFIG_PERMISSION_SETTINGS_LABEL"> <field name="rules" type="rules" label="FIELD_RULES_LABEL" translate_label="false" validate="rules" filter="rules" > <action name="core.login.site" title="JACTION_LOGIN_SITE" description="COM_CONFIG_ACTION_LOGIN_SITE_DESC" /> <action name="core.login.admin" title="JACTION_LOGIN_ADMIN" description="COM_CONFIG_ACTION_LOGIN_ADMIN_DESC" /> <action name="core.login.offline" title="JACTION_LOGIN_OFFLINE" description="COM_CONFIG_ACTION_LOGIN_OFFLINE_DESC" /> <action name="core.admin" title="JACTION_ADMIN_GLOBAL" description="COM_CONFIG_ACTION_ADMIN_DESC" /> <action name="core.options" title="JACTION_OPTIONS" description="COM_CONFIG_ACTION_OPTIONS_DESC" /> <action name="core.manage" title="JACTION_MANAGE" description="COM_CONFIG_ACTION_MANAGE_DESC" /> <action name="core.create" title="JACTION_CREATE" description="COM_CONFIG_ACTION_CREATE_DESC" /> <action name="core.delete" title="JACTION_DELETE" description="COM_CONFIG_ACTION_DELETE_DESC" /> <action name="core.edit" title="JACTION_EDIT" description="COM_CONFIG_ACTION_EDIT_DESC" /> <action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CONFIG_ACTION_EDITSTATE_DESC" /> <action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CONFIG_ACTION_EDITOWN_DESC" /> <action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_CONFIG_ACTION_EDITVALUE_DESC" /> </field> </fieldset> <fieldset name="filters" label="COM_CONFIG_TEXT_FILTERS" description="COM_CONFIG_TEXT_FILTERS_DESC"> <field name="filters" type="filters" label="COM_CONFIG_TEXT_FILTERS" filter="" /> </fieldset> <fieldset> <field name="asset_id" type="hidden" /> </fieldset> </form> PK ٌ!]Q@?�r r application.phpnu &1i� <?php /** * @package Joomla.Administrator * @subpackage com_config * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; /** * Model for the global configuration * * @since 3.2 */ class ConfigModelApplication extends ConfigModelForm { /** * Array of protected password fields from the configuration.php * * @var array * @since 3.9.23 */ private $protectedConfigurationFields = array('password', 'secret', 'ftp_pass', 'smtppass', 'redis_server_auth', 'session_redis_server_auth'); /** * Method to get a form object. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * * @return mixed A JForm object on success, false on failure * * @since 1.6 */ public function getForm($data = array(), $loadData = true) { // Get the form. $form = $this->loadForm('com_config.application', 'application', array('control' => 'jform', 'load_data' => $loadData)); if (empty($form)) { return false; } return $form; } /** * Method to get the configuration data. * * This method will load the global configuration data straight from * JConfig. If configuration data has been saved in the session, that * data will be merged into the original data, overwriting it. * * @return array An array containing all global config data. * * @since 1.6 */ public function getData() { // Get the config data. $config = new JConfig; $data = ArrayHelper::fromObject($config); // Get the correct driver at runtime $data['dbtype'] = JFactory::getDbo()->getName(); // Prime the asset_id for the rules. $data['asset_id'] = 1; // Get the text filter data $params = JComponentHelper::getParams('com_config'); $data['filters'] = ArrayHelper::fromObject($params->get('filters')); // If no filter data found, get from com_content (update of 1.6/1.7 site) if (empty($data['filters'])) { $contentParams = JComponentHelper::getParams('com_content'); $data['filters'] = ArrayHelper::fromObject($contentParams->get('filters')); } // Check for data in the session. $temp = JFactory::getApplication()->getUserState('com_config.config.global.data'); // Merge in the session data. if (!empty($temp)) { // $temp can sometimes be an object, and we need it to be an array if (is_object($temp)) { $temp = ArrayHelper::fromObject($temp); } $data = array_merge($data, $temp); } return $data; } /** * Method to save the configuration data. * * @param array $data An array containing all global config data. * * @return boolean True on success, false on failure. * * @since 1.6 */ public function save($data) { $app = JFactory::getApplication(); $dispatcher = JEventDispatcher::getInstance(); $config = JFactory::getConfig(); // Try to load the values from the configuration file foreach ($this->protectedConfigurationFields as $fieldKey) { if (!isset($data[$fieldKey])) { $data[$fieldKey] = $config->get($fieldKey); } } // Check that we aren't setting wrong database configuration $options = array( 'driver' => $data['dbtype'], 'host' => $data['host'], 'user' => $data['user'], 'password' => $data['password'], 'database' => $data['db'], 'prefix' => $data['dbprefix'] ); try { JDatabaseDriver::getInstance($options)->getVersion(); } catch (Exception $e) { $app->enqueueMessage(JText::_('JLIB_DATABASE_ERROR_DATABASE_CONNECT'), 'error'); return false; } // Check if we can set the Force SSL option if ((int) $data['force_ssl'] !== 0 && (int) $data['force_ssl'] !== (int) JFactory::getConfig()->get('force_ssl', '0')) { try { // Make an HTTPS request to check if the site is available in HTTPS. $host = JUri::getInstance()->getHost(); $options = new \Joomla\Registry\Registry; $options->set('userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0'); // Do not check for valid server certificate here, leave this to the user, moreover disable using a proxy if any is configured. $options->set('transport.curl', array( CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_PROXY => null, CURLOPT_PROXYUSERPWD => null, ) ); $response = JHttpFactory::getHttp($options)->get('https://' . $host . JUri::root(true) . '/', array('Host' => $host), 10); // If available in HTTPS check also the status code. if (!in_array($response->code, array(200, 503, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 401), true)) { throw new RuntimeException(JText::_('COM_CONFIG_ERROR_SSL_NOT_AVAILABLE_HTTP_CODE')); } } catch (RuntimeException $e) { $data['force_ssl'] = 0; // Also update the user state $app->setUserState('com_config.config.global.data.force_ssl', 0); // Inform the user $app->enqueueMessage(JText::sprintf('COM_CONFIG_ERROR_SSL_NOT_AVAILABLE', $e->getMessage()), 'warning'); } } // Save the rules if (isset($data['rules'])) { $rules = new JAccessRules($data['rules']); // Check that we aren't removing our Super User permission // Need to get groups from database, since they might have changed $myGroups = JAccess::getGroupsByUser(JFactory::getUser()->get('id')); $myRules = $rules->getData(); $hasSuperAdmin = $myRules['core.admin']->allow($myGroups); if (!$hasSuperAdmin) { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_REMOVING_SUPER_ADMIN'), 'error'); return false; } $asset = JTable::getInstance('asset'); if ($asset->loadByName('root.1')) { $asset->rules = (string) $rules; if (!$asset->check() || !$asset->store()) { $app->enqueueMessage($asset->getError(), 'error'); return; } } else { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_ROOT_ASSET_NOT_FOUND'), 'error'); return false; } unset($data['rules']); } // Save the text filters if (isset($data['filters'])) { $registry = new Registry(array('filters' => $data['filters'])); $extension = JTable::getInstance('extension'); // Get extension_id $extensionId = $extension->find(array('name' => 'com_config')); if ($extension->load((int) $extensionId)) { $extension->params = (string) $registry; if (!$extension->check() || !$extension->store()) { $app->enqueueMessage($extension->getError(), 'error'); return; } } else { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CONFIG_EXTENSION_NOT_FOUND'), 'error'); return false; } unset($data['filters']); } // Get the previous configuration. $prev = new JConfig; $prev = ArrayHelper::fromObject($prev); // Merge the new data in. We do this to preserve values that were not in the form. $data = array_merge($prev, $data); /* * Perform miscellaneous options based on configuration settings/changes. */ // Escape the offline message if present. if (isset($data['offline_message'])) { $data['offline_message'] = JFilterOutput::ampReplace($data['offline_message']); } // Purge the database session table if we are changing to the database handler. if ($prev['session_handler'] != 'database' && $data['session_handler'] == 'database') { $table = JTable::getInstance('session'); $table->purge(-1); } // Set the shared session configuration if (isset($data['shared_session'])) { $currentShared = isset($prev['shared_session']) ? $prev['shared_session'] : '0'; // Has the user enabled shared sessions? if ($data['shared_session'] == 1 && $currentShared == 0) { // Generate a random shared session name $data['session_name'] = JUserHelper::genRandomPassword(16); } // Has the user disabled shared sessions? if ($data['shared_session'] == 0 && $currentShared == 1) { // Remove the session name value unset($data['session_name']); } } if (empty($data['cache_handler'])) { $data['caching'] = 0; } /* * Look for a custom cache_path * First check if a path is given in the submitted data, then check if a path exists in the previous data, otherwise use the default */ if (!empty($data['cache_path'])) { $path = $data['cache_path']; } elseif (!empty($prev['cache_path'])) { $path = $prev['cache_path']; } else { $path = JPATH_SITE . '/cache'; } // Give a warning if the cache-folder can not be opened if ($data['caching'] > 0 && $data['cache_handler'] == 'file' && @opendir($path) == false) { $error = true; // If a custom path is in use, try using the system default instead of disabling cache if ($path !== JPATH_SITE . '/cache' && @opendir(JPATH_SITE . '/cache') != false) { try { JLog::add( JText::sprintf('COM_CONFIG_ERROR_CUSTOM_CACHE_PATH_NOTWRITABLE_USING_DEFAULT', $path, JPATH_SITE . '/cache'), JLog::WARNING, 'jerror' ); } catch (RuntimeException $logException) { $app->enqueueMessage( JText::sprintf('COM_CONFIG_ERROR_CUSTOM_CACHE_PATH_NOTWRITABLE_USING_DEFAULT', $path, JPATH_SITE . '/cache'), 'warning' ); } $path = JPATH_SITE . '/cache'; $error = false; $data['cache_path'] = ''; } if ($error) { try { JLog::add(JText::sprintf('COM_CONFIG_ERROR_CACHE_PATH_NOTWRITABLE', $path), JLog::WARNING, 'jerror'); } catch (RuntimeException $exception) { $app->enqueueMessage(JText::sprintf('COM_CONFIG_ERROR_CACHE_PATH_NOTWRITABLE', $path), 'warning'); } $data['caching'] = 0; } } // Did the user remove their custom cache path? Don't save the variable to the config if (empty($data['cache_path'])) { unset($data['cache_path']); } // Clean the cache if disabled but previously enabled or changing cache handlers; these operations use the `$prev` data already in memory if ((!$data['caching'] && $prev['caching']) || $data['cache_handler'] !== $prev['cache_handler']) { try { JFactory::getCache()->clean(); } catch (JCacheExceptionConnecting $exception) { try { JLog::add(JText::_('COM_CONFIG_ERROR_CACHE_CONNECTION_FAILED'), JLog::WARNING, 'jerror'); } catch (RuntimeException $logException) { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CACHE_CONNECTION_FAILED'), 'warning'); } } catch (JCacheExceptionUnsupported $exception) { try { JLog::add(JText::_('COM_CONFIG_ERROR_CACHE_DRIVER_UNSUPPORTED'), JLog::WARNING, 'jerror'); } catch (RuntimeException $logException) { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CACHE_DRIVER_UNSUPPORTED'), 'warning'); } } } // Create the new configuration object. $config = new Registry($data); // Overwrite the old FTP credentials with the new ones. $temp = JFactory::getConfig(); $temp->set('ftp_enable', $data['ftp_enable']); $temp->set('ftp_host', $data['ftp_host']); $temp->set('ftp_port', $data['ftp_port']); $temp->set('ftp_user', $data['ftp_user']); $temp->set('ftp_pass', $data['ftp_pass']); $temp->set('ftp_root', $data['ftp_root']); // Clear cache of com_config component. $this->cleanCache('_system', 0); $this->cleanCache('_system', 1); $result = $dispatcher->trigger('onApplicationBeforeSave', array($config)); // Store the data. if (in_array(false, $result, true)) { throw new RuntimeException(JText::_('COM_CONFIG_ERROR_UNKNOWN_BEFORE_SAVING')); } // Write the configuration file. $result = $this->writeConfigFile($config); // Trigger the after save event. $dispatcher->trigger('onApplicationAfterSave', array($config)); return $result; } /** * Method to unset the root_user value from configuration data. * * This method will load the global configuration data straight from * JConfig and remove the root_user value for security, then save the configuration. * * @return boolean True on success, false on failure. * * @since 1.6 */ public function removeroot() { $dispatcher = JEventDispatcher::getInstance(); // Get the previous configuration. $prev = new JConfig; $prev = ArrayHelper::fromObject($prev); // Create the new configuration object, and unset the root_user property unset($prev['root_user']); $config = new Registry($prev); $result = $dispatcher->trigger('onApplicationBeforeSave', array($config)); // Store the data. if (in_array(false, $result, true)) { throw new RuntimeException(JText::_('COM_CONFIG_ERROR_UNKNOWN_BEFORE_SAVING')); } // Write the configuration file. $result = $this->writeConfigFile($config); // Trigger the after save event. $dispatcher->trigger('onApplicationAfterSave', array($config)); return $result; } /** * Method to write the configuration to a file. * * @param Registry $config A Registry object containing all global config data. * * @return boolean True on success, false on failure. * * @since 2.5.4 * @throws RuntimeException */ private function writeConfigFile(Registry $config) { jimport('joomla.filesystem.path'); jimport('joomla.filesystem.file'); // Set the configuration file path. $file = JPATH_CONFIGURATION . '/configuration.php'; // Get the new FTP credentials. $ftp = JClientHelper::getCredentials('ftp', true); $app = JFactory::getApplication(); // Attempt to make the file writeable if using FTP. if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0644')) { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTWRITABLE'), 'notice'); } // Attempt to write the configuration file as a PHP class named JConfig. $configuration = $config->toString('PHP', array('class' => 'JConfig', 'closingtag' => false)); if (!JFile::write($file, $configuration)) { throw new RuntimeException(JText::_('COM_CONFIG_ERROR_WRITE_FAILED')); } // Invalidates the cached configuration file if (function_exists('opcache_invalidate')) { opcache_invalidate($file); } // Attempt to make the file unwriteable if NOT using FTP. if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0444')) { $app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTUNWRITABLE'), 'notice'); } return true; } /** * Method to store the permission values in the asset table. * * This method will get an array with permission key value pairs and transform it * into json and update the asset table in the database. * * @param string $permission Need an array with Permissions (component, rule, value and title) * * @return array A list of result data. * * @since 3.5 */ public function storePermissions($permission = null) { $app = JFactory::getApplication(); $user = JFactory::getUser(); if (is_null($permission)) { // Get data from input. $permission = array( 'component' => $app->input->get('comp'), 'action' => $app->input->get('action'), 'rule' => $app->input->get('rule'), 'value' => $app->input->get('value'), 'title' => $app->input->get('title', '', 'RAW') ); } // We are creating a new item so we don't have an item id so don't allow. if (substr($permission['component'], -6) === '.false') { $app->enqueueMessage(JText::_('JLIB_RULES_SAVE_BEFORE_CHANGE_PERMISSIONS'), 'error'); return false; } // Check if the user is authorized to do this. if (!$user->authorise('core.admin', $permission['component'])) { $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); return false; } $permission['component'] = empty($permission['component']) ? 'root.1' : $permission['component']; // Current view is global config? $isGlobalConfig = $permission['component'] === 'root.1'; // Check if changed group has Super User permissions. $isSuperUserGroupBefore = JAccess::checkGroup($permission['rule'], 'core.admin'); // Check if current user belongs to changed group. $currentUserBelongsToGroup = in_array((int) $permission['rule'], $user->groups) ? true : false; // Get current user groups tree. $currentUserGroupsTree = JAccess::getGroupsByUser($user->id, true); // Check if current user belongs to changed group. $currentUserSuperUser = $user->authorise('core.admin'); // If user is not Super User cannot change the permissions of a group it belongs to. if (!$currentUserSuperUser && $currentUserBelongsToGroup) { $app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_CHANGE_OWN_GROUPS'), 'error'); return false; } // If user is not Super User cannot change the permissions of a group it belongs to. if (!$currentUserSuperUser && in_array((int) $permission['rule'], $currentUserGroupsTree)) { $app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_CHANGE_OWN_PARENT_GROUPS'), 'error'); return false; } // If user is not Super User cannot change the permissions of a Super User Group. if (!$currentUserSuperUser && $isSuperUserGroupBefore && !$currentUserBelongsToGroup) { $app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_CHANGE_SUPER_USER'), 'error'); return false; } // If user is not Super User cannot change the Super User permissions in any group it belongs to. if ($isSuperUserGroupBefore && $currentUserBelongsToGroup && $permission['action'] === 'core.admin') { $app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_DEMOTE_SELF'), 'error'); return false; } try { $asset = JTable::getInstance('asset'); $result = $asset->loadByName($permission['component']); if ($result === false) { $data = array($permission['action'] => array($permission['rule'] => $permission['value'])); $rules = new JAccessRules($data); $asset->rules = (string) $rules; $asset->name = (string) $permission['component']; $asset->title = (string) $permission['title']; // Get the parent asset id so we have a correct tree. $parentAsset = JTable::getInstance('Asset'); if (strpos($asset->name, '.') !== false) { $assetParts = explode('.', $asset->name); $parentAsset->loadByName($assetParts[0]); $parentAssetId = $parentAsset->id; } else { $parentAssetId = $parentAsset->getRootId(); } /** * @to do: incorrect ACL stored * When changing a permission of an item that doesn't have a row in the asset table the row a new row is created. * This works fine for item <-> component <-> global config scenario and component <-> global config scenario. * But doesn't work properly for item <-> section(s) <-> component <-> global config scenario, * because a wrong parent asset id (the component) is stored. * Happens when there is no row in the asset table (ex: deleted or not created on update). */ $asset->setLocation($parentAssetId, 'last-child'); } else { // Decode the rule settings. $temp = json_decode($asset->rules, true); // Check if a new value is to be set. if (isset($permission['value'])) { // Check if we already have an action entry. if (!isset($temp[$permission['action']])) { $temp[$permission['action']] = array(); } // Check if we already have a rule entry. if (!isset($temp[$permission['action']][$permission['rule']])) { $temp[$permission['action']][$permission['rule']] = array(); } // Set the new permission. $temp[$permission['action']][$permission['rule']] = (int) $permission['value']; // Check if we have an inherited setting. if ($permission['value'] === '') { unset($temp[$permission['action']][$permission['rule']]); } // Check if we have any rules. if (!$temp[$permission['action']]) { unset($temp[$permission['action']]); } } else { // There is no value so remove the action as it's not needed. unset($temp[$permission['action']]); } $asset->rules = json_encode($temp, JSON_FORCE_OBJECT); } if (!$asset->check() || !$asset->store()) { $app->enqueueMessage(JText::_('JLIB_UNKNOWN'), 'error'); return false; } } catch (Exception $e) { $app->enqueueMessage($e->getMessage(), 'error'); return false; } // All checks done. $result = array( 'text' => '', 'class' => '', 'result' => true, ); // Show the current effective calculated permission considering current group, path and cascade. try { // Get the asset id by the name of the component. $query = $this->db->getQuery(true) ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__assets')) ->where($this->db->quoteName('name') . ' = ' . $this->db->quote($permission['component'])); $this->db->setQuery($query); $assetId = (int) $this->db->loadResult(); // Fetch the parent asset id. $parentAssetId = null; /** * @to do: incorrect info * When creating a new item (not saving) it uses the calculated permissions from the component (item <-> component <-> global config). * But if we have a section too (item <-> section(s) <-> component <-> global config) this is not correct. * Also, currently it uses the component permission, but should use the calculated permissions for achild of the component/section. */ // If not in global config we need the parent_id asset to calculate permissions. if (!$isGlobalConfig) { // In this case we need to get the component rules too. $query->clear() ->select($this->db->quoteName('parent_id')) ->from($this->db->quoteName('#__assets')) ->where($this->db->quoteName('id') . ' = ' . $assetId); $this->db->setQuery($query); $parentAssetId = (int) $this->db->loadResult(); } // Get the group parent id of the current group. $query->clear() ->select($this->db->quoteName('parent_id')) ->from($this->db->quoteName('#__usergroups')) ->where($this->db->quoteName('id') . ' = ' . (int) $permission['rule']); $this->db->setQuery($query); $parentGroupId = (int) $this->db->loadResult(); // Count the number of child groups of the current group. $query->clear() ->select('COUNT(' . $this->db->quoteName('id') . ')') ->from($this->db->quoteName('#__usergroups')) ->where($this->db->quoteName('parent_id') . ' = ' . (int) $permission['rule']); $this->db->setQuery($query); $totalChildGroups = (int) $this->db->loadResult(); } catch (Exception $e) { $app->enqueueMessage($e->getMessage(), 'error'); return false; } // Clear access statistics. JAccess::clearStatics(); // After current group permission is changed we need to check again if the group has Super User permissions. $isSuperUserGroupAfter = JAccess::checkGroup($permission['rule'], 'core.admin'); // Get the rule for just this asset (non-recursive) and get the actual setting for the action for this group. $assetRule = JAccess::getAssetRules($assetId, false, false)->allow($permission['action'], $permission['rule']); // Get the group, group parent id, and group global config recursive calculated permission for the chosen action. $inheritedGroupRule = JAccess::checkGroup($permission['rule'], $permission['action'], $assetId); if (!empty($parentAssetId)) { $inheritedGroupParentAssetRule = JAccess::checkGroup($permission['rule'], $permission['action'], $parentAssetId); } else { $inheritedGroupParentAssetRule = null; } $inheritedParentGroupRule = !empty($parentGroupId) ? JAccess::checkGroup($parentGroupId, $permission['action'], $assetId) : null; // Current group is a Super User group, so calculated setting is "Allowed (Super User)". if ($isSuperUserGroupAfter) { $result['class'] = 'label label-success'; $result['text'] = '<span class="icon-lock icon-white" aria-hidden="true"></span>' . JText::_('JLIB_RULES_ALLOWED_ADMIN'); } // Not super user. else { // First get the real recursive calculated setting and add (Inherited) to it. // If recursive calculated setting is "Denied" or null. Calculated permission is "Not Allowed (Inherited)". if ($inheritedGroupRule === null || $inheritedGroupRule === false) { $result['class'] = 'label label-important'; $result['text'] = JText::_('JLIB_RULES_NOT_ALLOWED_INHERITED'); } // If recursive calculated setting is "Allowed". Calculated permission is "Allowed (Inherited)". else { $result['class'] = 'label label-success'; $result['text'] = JText::_('JLIB_RULES_ALLOWED_INHERITED'); } // Second part: Overwrite the calculated permissions labels if there is an explicit permission in the current group. /** * @todo: incorrect info * If a component has a permission that doesn't exists in global config (ex: frontend editing in com_modules) by default * we get "Not Allowed (Inherited)" when we should get "Not Allowed (Default)". */ // If there is an explicit permission "Not Allowed". Calculated permission is "Not Allowed". if ($assetRule === false) { $result['class'] = 'label label-important'; $result['text'] = JText::_('JLIB_RULES_NOT_ALLOWED'); } // If there is an explicit permission is "Allowed". Calculated permission is "Allowed". elseif ($assetRule === true) { $result['class'] = 'label label-success'; $result['text'] = JText::_('JLIB_RULES_ALLOWED'); } // Third part: Overwrite the calculated permissions labels for special cases. // Global configuration with "Not Set" permission. Calculated permission is "Not Allowed (Default)". if (empty($parentGroupId) && $isGlobalConfig === true && $assetRule === null) { $result['class'] = 'label label-important'; $result['text'] = JText::_('JLIB_RULES_NOT_ALLOWED_DEFAULT'); } /** * Component/Item with explicit "Denied" permission at parent Asset (Category, Component or Global config) configuration. * Or some parent group has an explicit "Denied". * Calculated permission is "Not Allowed (Locked)". */ elseif ($inheritedGroupParentAssetRule === false || $inheritedParentGroupRule === false) { $result['class'] = 'label label-important'; $result['text'] = '<span class="icon-lock icon-white" aria-hidden="true"></span>' . JText::_('JLIB_RULES_NOT_ALLOWED_LOCKED'); } } // If removed or added super user from group, we need to refresh the page to recalculate all settings. if ($isSuperUserGroupBefore != $isSuperUserGroupAfter) { $app->enqueueMessage(JText::_('JLIB_RULES_NOTICE_RECALCULATE_GROUP_PERMISSIONS'), 'notice'); } // If this group has child groups, we need to refresh the page to recalculate the child settings. if ($totalChildGroups > 0) { $app->enqueueMessage(JText::_('JLIB_RULES_NOTICE_RECALCULATE_GROUP_CHILDS_PERMISSIONS'), 'notice'); } return $result; } /** * Method to send a test mail which is called via an AJAX request * * @return boolean * * @since 3.5 * @throws Exception */ public function sendTestMail() { // Set the new values to test with the current settings $app = JFactory::getApplication(); $input = $app->input; $smtppass = $input->get('smtppass', null, 'RAW'); $app->set('smtpauth', $input->get('smtpauth')); $app->set('smtpuser', $input->get('smtpuser', '', 'STRING')); $app->set('smtphost', $input->get('smtphost')); $app->set('smtpsecure', $input->get('smtpsecure')); $app->set('smtpport', $input->get('smtpport')); $app->set('mailfrom', $input->get('mailfrom', '', 'STRING')); $app->set('fromname', $input->get('fromname', '', 'STRING')); $app->set('mailer', $input->get('mailer')); $app->set('mailonline', $input->get('mailonline')); // Use smtppass only if it was submitted if ($smtppass !== null) { $app->set('smtppass', $smtppass); } $mail = JFactory::getMailer(); // Prepare email and send try to send it $mailSubject = JText::sprintf('COM_CONFIG_SENDMAIL_SUBJECT', $app->get('sitename')); $mailBody = JText::sprintf('COM_CONFIG_SENDMAIL_BODY', JText::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer))); if ($mail->sendMail($app->get('mailfrom'), $app->get('fromname'), $app->get('mailfrom'), $mailSubject, $mailBody) === true) { $methodName = JText::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer)); // If JMail send the mail using PHP Mail as fallback. if ($mail->Mailer != $app->get('mailer')) { $app->enqueueMessage(JText::sprintf('COM_CONFIG_SENDMAIL_SUCCESS_FALLBACK', $app->get('mailfrom'), $methodName), 'warning'); } else { $app->enqueueMessage(JText::sprintf('COM_CONFIG_SENDMAIL_SUCCESS', $app->get('mailfrom'), $methodName), 'message'); } return true; } $app->enqueueMessage(JText::_('COM_CONFIG_SENDMAIL_ERROR'), 'error'); return false; } } PK �s!]�\��� � model.phpnu &1i� PK �s!]���: : ! base.phpnu &1i� PK �s!]�s\�� � y& database.phpnu &1i� PK tt!]�^4�C C �, behavior.phpnu &1i� PK tt!]�X9)� � > field/boolean.phpnu &1i� PK tt!]jv�.� � A field/date.phpnu &1i� PK tt!]�;�ۈ � U field/text.phpnu &1i� PK tt!]�ퟷ �a field/number.phpnu &1i� PK tt!].�<� $v dispatcher/behavior.phpnu &1i� PK tt!]���� � mx field.phpnu &1i� PK tt!]¦=� � Z� behavior/language.phpnu &1i� PK tt!]�:\� � � behavior/private.phpnu &1i� PK tt!]�E��[ [ � behavior/access.phpnu &1i� PK tt!]�vE�e e �� behavior/filters.phpnu &1i� PK tt!]�Njn� � [� behavior/enabled.phpnu &1i� PK tt!]�C��Z Z #� behavior/emptynonzero.phpnu &1i� PK ٌ!]��b b �� component.phpnu &1i� PK ٌ!]���� � e� field/filters.phpnu &1i� PK ٌ!]3(2�$ $ � field/configcomponents.phpnu &1i� PK ٌ!]�Fl�v �v form/application.xmlnu &1i� PK ٌ!]Q@?�r r 9� application.phpnu &1i� PK � ��
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка