/** * Returns the alternate view template paths (a.k.a. template overrides in Joomla!-speak) for the given View name * * @param string $viewName The name of the view triggering this event * * @return array The template override paths */ public function onGetViewTemplatePaths($viewName) { $container = $this->subject->getContainer(); $application_name = $container->application_name; $component_name = 'com_' . strtolower($application_name); // That's the path in the site's current template containing template overrides $overridePath = Helper::getTemplateOverridePath($component_name, true); // The alternative view name (pluralised if the view is singular, singularised if the view is plural) $altViewName = Inflector::isPlural($viewName) ? Inflector::singularize($viewName) : Inflector::pluralize($viewName); // Remember, each path is pushed to the TOP of the path stack. This means that the least important directory // must go FIRST so that it ends add being added LAST. return array($overridePath . '/' . $altViewName, $overridePath . '/' . $viewName); }
/** * Checks if the current user has enough privileges for the requested ACL * area. * * @param string $area The ACL area, e.g. core.manage. * * @return bool True if the user has the ACL privilege specified */ protected function checkACL($controller_name, $area) { // If the area is one of false, 0, no or 403 we cancel the action if (in_array(strtolower($area), array('false', '0', 'no', '403'))) { return false; } // If the area is one of true, 1, yes we proceed with the action if (in_array(strtolower($area), array('true', '1', 'yes'))) { return true; } // If no ACL area is specified we proceed with the action if (empty($area)) { return true; } // Get the controller, model and table $container = $this->subject->getContainer(); $application_name = $container->application_name; $component_name = 'com_' . strtolower($application_name); /** @var DataController $controller */ $controller = Controller::getInstance($application_name, $controller_name, $container); $model = $controller->getModel(); // If it's not a data model or it's not assets tracked just perform a regular ACL check on the component if (!$model instanceof DataModel || !$model->getState('_isAssetsTracked', false)) { return Helper::authorise($area, $component_name); } // Initialise $ids = null; // Get the IDs in the request $ids = $controller->getIDsFromRequest($model, false); // If there are no IDs there is no asset tracking, fall back to the generic ACL check if (empty($ids)) { return Helper::authorise($area, $component_name); } // This should never happen unless you screw up overriding getIDsFromRequest in your model... if (!is_array($ids)) { $ids = array($ids); } // Check the asset permissions of each record $resource = Inflector::singularize($controller_name); $isEditState = $area == 'core.edit.state'; foreach ($ids as $id) { $asset = $component_name . '.' . $resource . '.' . $id; // Dedicated permission found, check it! if (Helper::authorise($area, $asset)) { return true; } // No dedicated permissions. Fallback on edit.own. if (!$isEditState && Helper::authorise('core.edit.own', $asset) && $model->hasField('created_by')) { // Load the record $model->find(array('id' => $id)); // Make sure the record can be loaded if ($model->getId()) { // Now test the owner is the user. $owner_id = (int) $model->created_by; // If I am the owner the test is successful if ($owner_id == \JFactory::getUser()->id) { return true; } } } } return false; }
/** * Returns a new model object. Unless overridden by the $config array, it will * try to automatically populate its state from the request variables. * * By default the new model instance is created with persistent state, unless * you pass $config['modelTemporaryInstance'] = false * * @param string $appName The application name * @param string $modelName The model name * @param Container $container Configuration variables to the model * * @return static * * @throws \RuntimeException If the Model is not found */ public static function getInstance($appName = null, $modelName = '', $container = null) { if (empty($appName) && !is_object($container)) { $app = Application::getInstance(); $appName = $app->getName(); $container = $app->getContainer(); } elseif (empty($appName) && is_object($container)) { $appName = $container->application_name; } elseif (!empty($appName) && !is_object($container)) { $container = Application::getInstance($appName)->getContainer(); } $config = isset($container['mvc_config']) ? $container['mvc_config'] : array(); if (empty($modelName)) { $modelName = $container->input->getCmd('view', ''); } // Try to load the Model class $classes = array('\\' . ucfirst($appName) . '\\Model\\' . ucfirst($modelName), '\\' . ucfirst($appName) . '\\Model\\' . ucfirst(Inflector::pluralize($modelName)), '\\' . ucfirst($appName) . '\\Model\\DefaultModel'); foreach ($classes as $className) { if (class_exists($className)) { break; } } if (!class_exists($className)) { throw new \RuntimeException("Model not found (app : model) = {$appName} : {$modelName}"); } /** @var Model $result */ $result = new $className($container); if (array_key_exists('modelTemporaryInstance', $config) && $config['modelTemporaryInstance']) { $result = $result->getClone()->savestate(0); } if (array_key_exists('modelClearState', $config) && $config['modelClearState']) { $result->clearState(); } if (array_key_exists('modelClearInput', $config) && $config['modelClearInput']) { $result->clearInput(); } return $result; }
/** * Creates an instance of a controller object. * * @param string $appName The application name [optional] Default: the default application * @param string $controller The controller name [optional] Default: based on the "view" input parameter * @param Container $container The DI container [optional] Default: the application container of the $appName application * * @return Controller A Controller instance * * @throws \RuntimeException When you are referring to a controller class which doesn't exist */ public static function &getInstance($appName = null, $controller = null, $container = null) { if (empty($appName) && !is_object($container)) { $app = Application::getInstance(); $appName = $app->getName(); $container = $app->getContainer(); } elseif (empty($appName) && is_object($container)) { $appName = $container->application_name; } elseif (!empty($appName) && !is_object($container)) { $container = Application::getInstance($appName)->getContainer(); } $input = $container->input; if (empty($controller)) { $controller = $input->getCmd('view', ''); } // Get the class base name, e.g. \Foobar\Controller\ $classBaseName = '\\' . ucfirst($appName) . '\\Controller\\'; // Get the class name suffixes, in the order to be searched for $classSuffixes = array($controller, Inflector::singularize($controller), Inflector::pluralize($controller), 'DefaultController'); // Look for the best classname match foreach ($classSuffixes as $suffix) { $className = $classBaseName . ucfirst($suffix); if (class_exists($className)) { // The class is loaded. We have a match! break; } } if (!class_exists($className)) { throw new \RuntimeException("Controller not found (app : controller) = {$appName} : {$controller}"); } $instance = new $className($container); return $instance; }
/** * Check the data for validity. By default it only checks for fields declared as NOT NULL * * @return static Self, for chaining * * @throws \RuntimeException When the data bound to this record is invalid */ public function check() { if (!$this->autoChecks) { return $this; } foreach ($this->knownFields as $fieldName => $field) { // Never check the key if it's empty; an empty key is normal for new records if ($fieldName == $this->idFieldName) { continue; } $value = $this->{$fieldName}; if ($field->Null == 'NO' && empty($value) && !is_numeric($value) && !in_array($fieldName, $this->fieldsSkipChecks)) { $text = $this->container->application->getName() . '_' . Inflector::singularize($this->getName()) . '_ERR_' . $fieldName . '_EMPTY'; throw new \RuntimeException(Text::_($text), 500); } } return $this; }
/** * Adds a relation to the relation manager * * @param string $name The name of the relation as known to this relation manager, e.g. 'phone' * @param string $type The relation type, e.g. 'hasOne' * @param string $foreignModelClass The class name of the foreign key's model, e.g. '\Foobar\Phones' * @param string $localKey The local table key for this relation * @param string $foreignKey The foreign key for this relation * @param string $pivotTable For many-to-many relations, the pivot (glue) table * @param string $pivotLocalKey For many-to-many relations, the pivot table's column storing the local key * @param string $pivotForeignKey For many-to-many relations, the pivot table's column storing the foreign key * * @return DataModel The parent model, for chaining * * @throws Relation\Exception\RelationTypeNotFound when $type is not known * @throws Relation\Exception\ForeignModelNotFound when $foreignModelClass doesn't exist */ public function addRelation($name, $type, $foreignModelClass = null, $localKey = null, $foreignKey = null, $pivotTable = null, $pivotLocalKey = null, $pivotForeignKey = null) { if (!isset(static::$relationTypes[$type])) { throw new DataModel\Relation\Exception\RelationTypeNotFound("Relation type '{$type}' not found"); } // Guess the foreign model class if necessary if (empty($foreignModelClass) || !class_exists($foreignModelClass, true)) { $parentClass = get_class($this->parentModel); $classNameParts = explode('\\', $parentClass); array_pop($classNameParts); $classPrefix = implode('\\', $classNameParts); $foreignModelClass = $classPrefix . '\\' . ucfirst($name); if (!class_exists($foreignModelClass, true)) { $foreignModelClass = $classPrefix . '\\' . ucfirst(Inflector::pluralize($name)); } } if (!class_exists($foreignModelClass, true)) { throw new DataModel\Relation\Exception\ForeignModelNotFound("Foreign model '{$foreignModelClass}' for relation '{$name}' not found"); } $className = static::$relationTypes[$type]; /** @var Relation $relation */ $relation = new $className($this->parentModel, $foreignModelClass, $localKey, $foreignKey, $pivotTable, $pivotLocalKey, $pivotForeignKey); $this->relations[$name] = $relation; return $this->parentModel; }
/** * Delete selected item(s) * * @return void */ public function remove() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel(); $ids = $this->getIDsFromRequest($model, false); try { $status = true; foreach ($ids as $id) { $model->find($id); $model->delete(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $router = $this->container->router; $url = !empty($customURL) ? $customURL : $router->route('index.php?view=' . Inflector::pluralize($this->view)); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $textKey = $this->container->application_name . '_LBL_' . Inflector::singularize($this->view) . '_DELETED'; $this->setRedirect($url, Text::_($textKey)); } }