From 0a56caa350aeb16fa55573799e7bc45b1465a4af Mon Sep 17 00:00:00 2001 From: Chraneco Date: Fri, 2 Dec 2011 10:49:28 +0100 Subject: [PATCH 01/17] Initial Commit for Language Overrides Manager --- .../controllers/override.json.php | 121 +++++++++ .../com_languages/controllers/override.php | 242 ++++++++++++++++++ .../com_languages/controllers/overrides.php | 61 +++++ .../controllers/strings.json.php | 60 +++++ .../com_languages/helpers/helper.php | 129 ++++++++++ .../com_languages/helpers/jsonresponse.php | 119 +++++++++ .../com_languages/helpers/languages.php | 56 ++++ .../com_languages/models/forms/override.xml | 36 +++ .../com_languages/models/override.php | 159 ++++++++++++ .../com_languages/models/overrides.php | 195 ++++++++++++++ .../com_languages/models/strings.php | 132 ++++++++++ .../installed/tmpl/default_navigation.php | 2 + .../com_languages/views/override/index.html | 1 + .../views/override/tmpl/edit.php | 89 +++++++ .../views/override/tmpl/index.html | 1 + .../views/override/view.html.php | 96 +++++++ .../com_languages/views/overrides/index.html | 1 + .../views/overrides/tmpl/default.php | 88 +++++++ .../views/overrides/tmpl/index.html | 1 + .../views/overrides/view.html.php | 84 ++++++ .../language/en-GB/en-GB.com_languages.ini | 25 +- installation/sql/mysql/joomla.sql | 15 ++ media/system/css/overrider.css | 80 ++++++ media/system/js/overrider.js | 225 ++++++++++++++++ 24 files changed, 2017 insertions(+), 1 deletion(-) create mode 100644 administrator/components/com_languages/controllers/override.json.php create mode 100644 administrator/components/com_languages/controllers/override.php create mode 100644 administrator/components/com_languages/controllers/overrides.php create mode 100644 administrator/components/com_languages/controllers/strings.json.php create mode 100644 administrator/components/com_languages/helpers/helper.php create mode 100644 administrator/components/com_languages/helpers/jsonresponse.php create mode 100644 administrator/components/com_languages/models/forms/override.xml create mode 100644 administrator/components/com_languages/models/override.php create mode 100644 administrator/components/com_languages/models/overrides.php create mode 100644 administrator/components/com_languages/models/strings.php create mode 100644 administrator/components/com_languages/views/override/index.html create mode 100644 administrator/components/com_languages/views/override/tmpl/edit.php create mode 100644 administrator/components/com_languages/views/override/tmpl/index.html create mode 100644 administrator/components/com_languages/views/override/view.html.php create mode 100644 administrator/components/com_languages/views/overrides/index.html create mode 100644 administrator/components/com_languages/views/overrides/tmpl/default.php create mode 100644 administrator/components/com_languages/views/overrides/tmpl/index.html create mode 100644 administrator/components/com_languages/views/overrides/view.html.php create mode 100644 media/system/css/overrider.css create mode 100644 media/system/js/overrider.js diff --git a/administrator/components/com_languages/controllers/override.json.php b/administrator/components/com_languages/controllers/override.json.php new file mode 100644 index 0000000000000..dd6fdb0818bea --- /dev/null +++ b/administrator/components/com_languages/controllers/override.json.php @@ -0,0 +1,121 @@ +getModel(); + $data = JRequest::getVar('jform', array(), 'post', 'array'); + $context = "$this->option.edit.$this->context"; + $task = $this->getTask(); + + // Determine the name of the primary key for the data. + if (empty($key)) { + $key = 'id'; + } + + // To avoid data collisions the urlVar may be different from the primary key. + if (empty($urlVar)) { + $urlVar = $key; + } + + $recordId = JRequest::getCmd($urlVar); + + $data[$key] = $recordId; + + $session = JFactory::getSession(); + $registry = $session->get('registry'); + + // Access check. + if (!$this->allowSave($data, $key)) { + echo new JoomJsonResponse(new Exception(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'))); + + return; + } + + // Validate the posted data. + // Sometimes the form needs some posted data, such as for plugins and modules. + $form = $model->getForm($data, false); + + if (!$form) { + echo new JoomJsonResponse(new Exception($model->getError())); + + return; + } + + // Test whether the data is valid. + $validData = $model->validate($form, $data); + + // Check for validation errors. + if ($validData === false) { + // Get the validation messages. + $errors = $model->getErrors(); + + // Push up to three validation messages out to the user. + for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) + { + if (JError::isError($errors[$i])) { + $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); + } + else { + $app->enqueueMessage($errors[$i], 'warning'); + } + } + + echo new JoomJsonResponse(new Exception('Invalid form')); + + return; + } + + // Attempt to save the data. + if (!$model->save($validData)) { + echo new JoomJsonResponse(new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()))); + + return; + } + + $this->setMessage(JText::_('COM_OVERRIDER_SAVE_SUCCESS')); + + echo new JoomJsonResponse(); + + return; + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/controllers/override.php b/administrator/components/com_languages/controllers/override.php new file mode 100644 index 0000000000000..cb35349c97f5b --- /dev/null +++ b/administrator/components/com_languages/controllers/override.php @@ -0,0 +1,242 @@ +getModel(); + $cid = JRequest::getVar('cid', array(), 'post', 'array'); + $context = "$this->option.edit.$this->context"; + $append = ''; + + // Determine the name of the primary key for the data. + if (empty($key)) { + $key = 'id'; + } + + // To avoid data collisions the urlVar may be different from the primary key. + if (empty($urlVar)) { + $urlVar = $key; + } + + // Get the previous record id (if any) and the current record id. + $recordId = (count($cid) ? $cid[0] : JRequest::getCmd($urlVar)); + + // Access check. + if (!$this->allowEdit()) { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED')); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); + + return false; + } + + // Check-out succeeded, push the new record id into the session. + //$this->holdEditId($context, $recordId); + $app->setUserState($context.'.data', null); + $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, $urlVar)); + + return true; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * @since 11.1 + */ + public function save($key = null, $urlVar = null) + { + // Check for request forgeries. + JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Initialise variables. + $app = JFactory::getApplication(); + $lang = JFactory::getLanguage(); + $model = $this->getModel(); + $data = JRequest::getVar('jform', array(), 'post', 'array'); + $context = "$this->option.edit.$this->context"; + $task = $this->getTask(); + + // Determine the name of the primary key for the data. + if (empty($key)) { + $key = 'id'; + } + + // To avoid data collisions the urlVar may be different from the primary key. + if (empty($urlVar)) { + $urlVar = $key; + } + + $recordId = JRequest::getCmd($urlVar); + + $data[$key] = $recordId; + + $session = JFactory::getSession(); + $registry = $session->get('registry'); + + // Access check. + if (!$this->allowSave($data, $key)) { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); + + return false; + } + + // Validate the posted data. + // Sometimes the form needs some posted data, such as for plugins and modules. + $form = $model->getForm($data, false); + + if (!$form) { + $app->enqueueMessage($model->getError(), 'error'); + + return false; + } + + // Require helper for filter functions called by JForm + require_once JPATH_COMPONENT.'/helpers/languages.php'; + + // Test whether the data is valid. + $validData = $model->validate($form, $data); + + // Check for validation errors. + if ($validData === false) { + // Get the validation messages. + $errors = $model->getErrors(); + + // Push up to three validation messages out to the user. + for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) + { + if (JError::isError($errors[$i])) { + $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); + } + else { + $app->enqueueMessage($errors[$i], 'warning'); + } + } + + // Save the data in the session + $app->setUserState($context.'.data', $data); + + // Redirect back to the edit screen. + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, $key), false)); + + return false; + } + + // Attempt to save the data. + if (!$model->save($validData)) { + // Save the data in the session. + $app->setUserState($context.'.data', $validData); + + // Redirect back to the edit screen. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError())); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, $key), false)); + + return false; + } + + + $this->setMessage(JText::_('COM_LANGUAGES_VIEW_OVERRIDE_SAVE_SUCCESS')); + + // Redirect the user and adjust session state based on the chosen task. + switch ($task) + { + case 'apply': + // Set the record data in the session. + $recordId = $model->getState($this->context.'.id'); + $app->setUserState($context.'.data', null); + + // Redirect back to the edit screen. + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($validData['key'], $key), false)); + break; + + case 'save2new': + // Clear the record id and data from the session. + $app->setUserState($context.'.data', null); + + // Redirect back to the edit screen. + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend(null, $key), false)); + break; + + default: + // Clear the record id and data from the session. + $app->setUserState($context.'.data', null); + + // Redirect to the list screen. + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); + break; + } + + // Invoke the postSave method to allow for the child class to access the model. + $this->postSaveHook($model, $validData); + + return true; + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * @since 11.1 + */ + public function cancel($key = null) + { + JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Initialise variables. + $app = JFactory::getApplication(); + $context = "$this->option.edit.$this->context"; + + if (empty($key)) { + $key = 'id'; + } + + $recordId = JRequest::getCmd($key); + + $app->setUserState($context.'.data', null); + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); + + return true; + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/controllers/overrides.php b/administrator/components/com_languages/controllers/overrides.php new file mode 100644 index 0000000000000..bb4f579fae6b5 --- /dev/null +++ b/administrator/components/com_languages/controllers/overrides.php @@ -0,0 +1,61 @@ +text_prefix.'_NO_ITEM_SELECTED')); + } else { + // Get the model. + $model = $this->getModel(); + + // Remove the items. + if ($model->delete($cid)) { + $this->setMessage(JText::plural($this->text_prefix.'_N_ITEMS_DELETED', count($cid))); + } else { + $this->setMessage($model->getError()); + } + } + + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false)); + } + + /** + * Proxy for getModel. + * + * @param string $name The name of the model. + * @param string $prefix The prefix for the PHP class name. + * + * @return JModel + * @since 1.6 + */ + public function getModel($name = 'Overrides', $prefix = 'OverriderModel', $config = array('ignore_request' => true)) + { + $model = parent::getModel($name, $prefix, $config); + + return $model; + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/controllers/strings.json.php b/administrator/components/com_languages/controllers/strings.json.php new file mode 100644 index 0000000000000..8943bf3d055a1 --- /dev/null +++ b/administrator/components/com_languages/controllers/strings.json.php @@ -0,0 +1,60 @@ +getModel()->refresh()); + } + + public function search() + { + echo new JoomJsonResponse($this->getModel()->search()); + } + + /** + * Proxy for getModel. + * + * @param string $name The name of the model. + * @param string $prefix The prefix for the PHP class name. + * + * @return JModel + * @since 1.6 + */ + public function getModel($name = 'Strings', $prefix = 'LanguagesModel', $config = array('ignore_request' => true)) + { + $model = parent::getModel($name, $prefix, $config); + + return $model; + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/helpers/helper.php b/administrator/components/com_languages/helpers/helper.php new file mode 100644 index 0000000000000..e03be20b3729a --- /dev/null +++ b/administrator/components/com_languages/helpers/helper.php @@ -0,0 +1,129 @@ +getUserState('com_overrider.client', 'site'); + + $clients = array( 'site' => JText::_('COM_OVERRIDER_SUBMENU_SITE'), + 'administrator' => JText::_('COM_OVERRIDER_SUBMENU_ADMINISTRATOR') + ); + + foreach($clients as $client => $title) + { + JSubMenuHelper::addEntry( $title, + 'index.php?option=com_overrider&client='.$client, + $client == $current_client + ); + } + } + + /** + * Returns a list of the actions that can be performed + * + * @param string $type The type of the content to check + * @param int $id The ID of the content (category or image) + * @return JObject An object holding the results of the check + * @since 2.0 + */ + public static function getActions() + { + static $cache = null; + + if(!empty($cache)) + { + return $cache; + } + + $user = JFactory::getUser(); + $result = new JObject(); + + $actions = array('core.admin', 'core.manage', 'core.create', 'core.edit', 'core.delete'); + + foreach($actions as $action) + { + $result->set($action, $user->authorise($action, 'com_overrider')); + } + + // Store the result for better performance + $cache = $result; + + return $result; + } + + public function parse($client = 'site', $language = 'en-GB') + { + $filename = constant('JPATH_'.strtoupper($client)).DS.'language'.DS.'overrides'.DS.$language.'.override.ini'; + + return OverriderHelper::parseFile($filename); + } + + public function parseFile($filename) + { + jimport('joomla.filesystem.file'); + + if(!JFile::exists($filename)) + { + return array(); + } + + // Capture hidden PHP errors from the parsing. + $version = phpversion(); + $php_errormsg = null; + $track_errors = ini_get('track_errors'); + ini_set('track_errors', true); + + if($version >= '5.3.1') + { + $contents = file_get_contents($filename); + $contents = str_replace('_QQ_', '"\""', $contents); + $strings = @parse_ini_string($contents); + } + else + { + $strings = @parse_ini_file($filename); + + if($version == '5.3.0' && is_array($strings)) + { + foreach($strings as $key => $string) + { + $strings[$key]=str_replace('_QQ_', '"', $string); + } + } + } + + return $strings; + } + + static function filter($value) + { + return str_replace('"', '"_QQ_"', $value); + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/helpers/jsonresponse.php b/administrator/components/com_languages/helpers/jsonresponse.php new file mode 100644 index 0000000000000..209233af8c472 --- /dev/null +++ b/administrator/components/com_languages/helpers/jsonresponse.php @@ -0,0 +1,119 @@ +success, + * so you can use both flags equivalently. + * + * var boolean + */ + public $error = false; + + /** + * The main response message + * + * var boolean + */ + public $message = null; + + /** + * Array of messages gathered in the JApplication object + * + * var array + */ + public $messages = null; + + /** + * The response data + * + * var array/object + */ + public $data = null; + + /** + * Constructor + * + * @return void + * @since 2.1 + */ + public function __construct($response = null, $message = null, $error = false) + { + $this->message = $message; + + // Get the message queue + $messages = JFactory::getApplication()->getMessageQueue(); + + // Build the sorted message list + if(is_array($messages) && count($messages)) + { + foreach($messages as $message) + { + if(isset($message['type']) && isset($message['message'])) + { + $lists[$message['type']][] = $message['message']; + } + } + } + + // If messages exist add them to the output + if(isset($lists) && is_array($lists)) + { + $this->messages = $lists; + } + + // Check if we are dealing with an error + if(JError::isError($response)) + { + // Prepare the error response + $this->success = false; + $this->error = true; + $this->message = $response->getMessage(); + } + else + { + // Prepare the response data + $this->success = !$error; + $this->error = $error; + $this->data = $response; + } + } + + /** + * Magic toString method for sending the response in JSON format + * + * @return string The response in JSON format + * @since 2.1 + */ + public function __toString() + { + return json_encode($this); + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/helpers/languages.php b/administrator/components/com_languages/helpers/languages.php index e5feac681ca0a..aaa28d5b82f6e 100644 --- a/administrator/components/com_languages/helpers/languages.php +++ b/administrator/components/com_languages/helpers/languages.php @@ -39,6 +39,11 @@ public static function addSubmenu($vName) 'index.php?option=com_languages&view=languages', $vName == 'languages' ); + JSubMenuHelper::addEntry( + JText::_('COM_LANGUAGES_SUBMENU_OVERRIDES'), + 'index.php?option=com_languages&view=overrides', + $vName == 'overrides' + ); } /** @@ -62,4 +67,55 @@ public static function getActions() return $result; } + + public function parseFile($filename) + { + jimport('joomla.filesystem.file'); + + if(!JFile::exists($filename)) + { + return array(); + } + + // Capture hidden PHP errors from the parsing. + $version = phpversion(); + $php_errormsg = null; + $track_errors = ini_get('track_errors'); + ini_set('track_errors', true); + + if($version >= '5.3.1') + { + $contents = file_get_contents($filename); + $contents = str_replace('_QQ_', '"\""', $contents); + $strings = @parse_ini_string($contents); + } + else + { + $strings = @parse_ini_file($filename); + + if($version == '5.3.0' && is_array($strings)) + { + foreach($strings as $key => $string) + { + $strings[$key]=str_replace('_QQ_', '"', $string); + } + } + } + + return $strings; + } + + static function filterKey($value) + { + $filter = JFilterInput::getInstance(null, null, 1, 1); + + return strtoupper($filter->clean($value, 'cmd')); + } + + static function filterText($value) + { + $filter = JFilterInput::getInstance(null, null, 1, 1); + + return str_replace('"', '"_QQ_"', $filter->clean($value)); + } } diff --git a/administrator/components/com_languages/models/forms/override.xml b/administrator/components/com_languages/models/forms/override.xml new file mode 100644 index 0000000000000..66fe451cda692 --- /dev/null +++ b/administrator/components/com_languages/models/forms/override.xml @@ -0,0 +1,36 @@ + +
+
+ + + + + + + +
+
\ No newline at end of file diff --git a/administrator/components/com_languages/models/override.php b/administrator/components/com_languages/models/override.php new file mode 100644 index 0000000000000..00748c865d466 --- /dev/null +++ b/administrator/components/com_languages/models/override.php @@ -0,0 +1,159 @@ +loadForm('com_languages.override', 'override', array('control' => 'jform', 'load_data' => $loadData)); + if (empty($form)) { + return false; + } + + return $form; + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_languages.edit.override.data', array()); + + if (empty($data)) { + $data = $this->getItem(); + } + + return $data; + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * @since 11.1 + */ + public function getItem($pk = null) + { + require_once JPATH_COMPONENT.'/helpers/languages.php'; + + $pk = (!empty($pk)) ? $pk : JRequest::getCmd('id'); + $filename = constant('JPATH_'.strtoupper($this->getState('filter.client'))).DS.'language'.DS.'overrides'.DS.$this->getState('filter.language', 'en-GB').'.override.ini'; + $strings = LanguagesHelper::parseFile($filename); + + $result = new stdClass(); + $result->key = ''; + $result->override = ''; + if(isset($strings[$pk])) + { + $result->key = $pk; + $result->override = $strings[$pk]; + } + + return $result; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success, False on error. + * @since 11.1 + */ + public function save($data) + { + $app = JFactory::getApplication(); + require_once JPATH_COMPONENT.'/helpers/languages.php'; + + $client = $app->getUserState('com_languages.overrides.filter.client', 0) ? 'administrator' : 'site'; + $language = $app->getUserState('com_languages.overrides.filter.language', 'en-GB'); + + $filename = constant('JPATH_'.strtoupper($client)).DS.'language'.DS.'overrides'.DS.$language.'.override.ini'; + $strings = LanguagesHelper::parseFile($filename); + + if(isset($strings[$data['id']])) + { + if($data['key'] == $data['id']) + { + $strings[$data['key']] = $data['override']; + } + else + { + unset($strings[$data['id']]); + $strings = array($data['key'] => $data['override']) + $strings; + } + } + else + { + $strings = array($data['key'] => $data['override']) + $strings; + } + + $registry = new JRegistry(); + $registry->loadObject($strings); + + if(!JFile::write($filename, $registry->toString('INI'))) + { + return false; + } + + return true; + } + + /** + * Stock method to auto-populate the model state. + * + * @return void + * @since 11.1 + */ + protected function populateState() + { + $app = JFactory::getApplication(); + + $client = $app->getUserStateFromRequest('com_languages.overrides.filter.client', 'filter_client', 0, 'int') ? 'administrator' : 'site'; + $this->setState('filter.client', $client); + + $language = $app->getUserStateFromRequest('com_languages.overrides.filter.language', 'filter_language', 'en-GB', 'cmd'); + $this->setState('filter.language', $language); + + // Load the parameters. + $value = JComponentHelper::getParams($this->option); + $this->setState('params', $value); + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/models/overrides.php b/administrator/components/com_languages/models/overrides.php new file mode 100644 index 0000000000000..98efb94a6b413 --- /dev/null +++ b/administrator/components/com_languages/models/overrides.php @@ -0,0 +1,195 @@ +filter_fields = array('key', 'text'); + } + + /** + * Retrieves the images data + * + * @access public + * @return array Array of objects containing the images data from the database + * @since 1.5.5 + */ + function getOverrides($all = false) + { + // Get a storage key. + $store = $this->getStoreId(); + + // Try to load the data from internal storage. + if(!empty($this->cache[$store])) + { + return $this->cache[$store]; + } + + $filename = constant('JPATH_'.strtoupper($this->getState('filter.client'))).DS.'language'.DS.'overrides'.DS.$this->getState('filter.language').'.override.ini'; + $strings = LanguagesHelper::parseFile($filename); + + if(!$all && $this->getTotal() > $this->getState('list.limit')) + { + $strings = array_slice($strings, $this->getStart(), $this->getState('list.limit'), true); + } + + // Add the items to the internal cache. + $this->cache[$store] = $strings; + + return $this->cache[$store]; + } + + /** + * Method to get the pagination object for the list. + * This method uses 'getTotel', 'getStart' and the current + * list limit of this view. + * + * @return object A pagination object + * @since 2.0 + */ + /*function getPagination() + { + jimport('joomla.html.pagination'); + return new JPagination($this->getTotal(), $this->getStart(), $this->getState('list.limit')); + }*/ + + /** + * Method to get the total number of images + * + * @access public + * @return int The total number of images + * @since 1.5.5 + */ + function getTotal() + { + // Get a storage key. + $store = $this->getStoreId('getTotal'); + + // Try to load the data from internal storage. + if(!empty($this->cache[$store])) + { + return $this->cache[$store]; + } + + // Add the total to the internal cache. + $this->cache[$store] = count($this->getOverrides(true)); + + return $this->cache[$store]; + } + + /** + * Method to get the starting number of items for the data set. + * + * @return int The starting number of items available in the data set. + * @since 2.0 + */ + /*public function getStart() + { + $start = $this->getState('list.start'); + $limit = $this->getState('list.limit'); + $total = $this->getTotal(); + if($start > $total - $limit) + { + $start = max(0, (int)(ceil($total / $limit) - 1) * $limit); + } + + return $start; + }*/ + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string An optional ordering field. + * @param string An optional direction (asc|desc). + * @return void + * @since 2.0 + */ + protected function populateState($ordering = null, $direction = null) + { + $client = $this->getUserStateFromRequest('com_languages.overrides.filter.client', 'filter_client', 0, 'int') ? 'administrator' : 'site'; + $this->setState('filter.client', $client); + + $language = $this->getUserStateFromRequest('com_languages.overrides.filter.language', 'filter_language', 'en-GB', 'cmd'); + $this->setState('filter.language', $language); + + // List state information. + parent::populateState('key', 'asc'); + } + + /** + * Method to delete one or more images + * + * @access public + * @return int Number of successfully deleted images, boolean false if an error occured + * @since 1.5.5 + */ + function delete($cids) + { + if(!JFactory::getUser()->authorise('core.delete', 'com_languages')) + { + $this->setError(JText::_('COM_OVERRIDES_ERROR_DELETE_NOT_PERMITTED')); + + return false; + } + + $app = JFactory::getApplication(); + + jimport('joomla.filesystem.file'); + + $app = JFactory::getApplication(); + + $filename = constant('JPATH_'.strtoupper($this->getState('filter.client'))).DS.'language'.DS.'overrides'.DS.$this->getState('filter.language').'.override.ini'; + $strings = LanguagesHelper::parseFile($filename); + + foreach($cids as $key) + { + if(isset($strings[$key])) + { + unset($strings[$key]); + } + } + + $registry = new JRegistry(); + $registry->loadObject($strings); + + $filename = constant('JPATH_'.strtoupper($app->getUserState('com_overrider.filter.client'))).DS.'language'.DS.'overrides'.DS.$app->getUserState('com_overrider.filter.language').'.override.ini'; + + JFile::write($filename, $registry->toString('INI')); + + $this->cleanCache(); + + return count($cid); + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/models/strings.php b/administrator/components/com_languages/models/strings.php new file mode 100644 index 0000000000000..d0e1802855c54 --- /dev/null +++ b/administrator/components/com_languages/models/strings.php @@ -0,0 +1,132 @@ +setUserState('com_languages.overrides.cachedtime', null); + + try + { + $this->_db->setQuery('TRUNCATE TABLE #__overrider'); + $this->_db->query(); + } + catch(JDatabaseException $e) + { + return $e; + } + + $query = $this->_db->getQuery(true) + ->insert('#__overrider') + ->columns('constant, string, file'); + + $client = $app->getUserState('com_languages.overrides.filter.client', 'site') ? 'administrator' : 'site'; + $language = $app->getUserState('com_languages.overrides.filter.language', 'en-GB'); + + $base = constant('JPATH_'.strtoupper($client)).DS; + $path = $base.'language'.DS.$language; + + $files = array(); + if(JFolder::exists($path)) + { + $files = JFolder::files($path, $language.'.*ini$', false, true); + } + + $path = $base.'components'; + $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + + $path = $base.'modules'; + $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + + $path = $base.'templates'; + $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + + $path = JPATH_ROOT.DS.'plugins'; + $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + + foreach($files as $file) + { + $strings = LanguagesHelper::parseFile($file); + if($strings && count($strings)) + { + $query->clear('values'); + foreach($strings as $key => $string) + { + $query->values($this->_db->quote($key).','.$this->_db->quote($string).','.$this->_db->quote($file)); + } + + try + { + $this->_db->setQuery($query); + $this->_db->query(); + } + catch(JDatabaseException $e) + { + return $e; + } + } + } + + $app->setUserState('com_languages.overrides.cachedtime.'.$client.'.'.$language, time()); + + return true; + } + + public function search() + { + $results = array(); + + $limitstart = JRequest::getInt('more'); + + try + { + $query = $this->_db->getQuery(true) + ->select('constant, string, file') + ->from('#__overrider') + ->where('string LIKE '.$this->_db->quote('%'.JRequest::getString('searchstring').'%')); + + $this->_db->setQuery($query, $limitstart, 10); + $results['results'] = $this->_db->loadObjectList(); + + $query->clear('select') + ->select('COUNT(id)'); + $this->_db->setQuery($query); + + if($this->_db->loadResult() > $limitstart + 10) + { + $results['more'] = $limitstart + 10; + } + } + catch(JDatabaseException $e) + { + return $e; + } + + return $results; + } +} \ No newline at end of file diff --git a/administrator/components/com_languages/views/installed/tmpl/default_navigation.php b/administrator/components/com_languages/views/installed/tmpl/default_navigation.php index 2b3da19903e84..14c02cbbed895 100644 --- a/administrator/components/com_languages/views/installed/tmpl/default_navigation.php +++ b/administrator/components/com_languages/views/installed/tmpl/default_navigation.php @@ -21,6 +21,8 @@
  • +
  • +
  • diff --git a/administrator/components/com_languages/views/override/index.html b/administrator/components/com_languages/views/override/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/administrator/components/com_languages/views/override/index.html @@ -0,0 +1 @@ + diff --git a/administrator/components/com_languages/views/override/tmpl/edit.php b/administrator/components/com_languages/views/override/tmpl/edit.php new file mode 100644 index 0000000000000..abae2b43fad1d --- /dev/null +++ b/administrator/components/com_languages/views/override/tmpl/edit.php @@ -0,0 +1,89 @@ + + + +
    +
    +
    + item->key) ? JText::_('COM_LANGUAGES_VIEW_OVERRIDE_EDIT_NEW_OVERRIDE_LEGEND') : JText::_('COM_LANGUAGES_VIEW_OVERRIDE_EDIT_EDIT_OVERRIDE_LEGEND'); ?> +
      + +
    • form->getLabel('key'); ?> + form->getInput('key'); ?> +
      +
      + +
      +
      +
    • + +
    • form->getLabel('override'); ?> + form->getInput('override'); ?>
    • + +
    +
    +
    + +
    +
    + +
      + + +
    • form->getInput('searchstring'); ?> +
    • + +
    +
    + + + + +
    +
    +
    \ No newline at end of file diff --git a/administrator/components/com_languages/views/override/tmpl/index.html b/administrator/components/com_languages/views/override/tmpl/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/administrator/components/com_languages/views/override/tmpl/index.html @@ -0,0 +1 @@ + diff --git a/administrator/components/com_languages/views/override/view.html.php b/administrator/components/com_languages/views/override/view.html.php new file mode 100644 index 0000000000000..cac892686dd75 --- /dev/null +++ b/administrator/components/com_languages/views/override/view.html.php @@ -0,0 +1,96 @@ +addStyleSheet(JURI::root().'media/system/css/overrider.css'); + JHTML::core(); + $doc->addScript(JURI::root().'media/system/js/overrider.js'); + + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->state = $this->get('State'); + + // Check for errors. + if(count($errors = $this->get('Errors'))) { + JError::raiseError(500, implode("\n", $errors)); + return false; + } + + $cached_time = JFactory::getApplication()->getUserState('com_languages.overrides.cachedtime.'.$this->state->get('filter.client').'.'.$this->state->get('filter.language'), 0); + if(time() - $cached_time > 60 * 5) + { + $this->state->set('cache_expired', true); + } + + $this->addToolbar(); + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @since 1.6 + */ + protected function addToolbar() + { + JRequest::setVar('hidemainmenu', true); + + $app = JFactory::getApplication(); + $user = JFactory::getUser(); + $canDo = LanguagesHelper::getActions(); + + $client = $this->state->get('filter.client'); + $language = JLanguage::getInstance($this->state->get('filter.language'))->getName(); + JToolBarHelper::title(JText::sprintf('COM_LANGUAGES_VIEW_OVERRIDE_EDIT_TITLE', JText::_('COM_LANGUAGES_VIEW_OVERRIDE_CLIENT_'.strtoupper($client)), $language), 'langmanager'); + + if ($canDo->get('core.edit')) { + JToolBarHelper::apply('override.apply'); + JToolBarHelper::save('override.save'); + } + + // This component does not support Save as Copy due to uniqueness checks. + // While it can be done, it causes too much confusion if the user does + // not change the Old URL. + + if ($canDo->get('core.edit') && $canDo->get('core.create')) { + JToolBarHelper::save2new('override.save2new'); + } + + if (empty($this->item->key)) { + JToolBarHelper::cancel('override.cancel'); + } else { + JToolBarHelper::cancel('override.cancel', 'JTOOLBAR_CLOSE'); + } + + //JToolBarHelper::help('JHELP_COMPONENTS_OVERRIDER_EDIT'); + } +} diff --git a/administrator/components/com_languages/views/overrides/index.html b/administrator/components/com_languages/views/overrides/index.html new file mode 100644 index 0000000000000..fa6d84e8055f5 --- /dev/null +++ b/administrator/components/com_languages/views/overrides/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/administrator/components/com_languages/views/overrides/tmpl/default.php b/administrator/components/com_languages/views/overrides/tmpl/default.php new file mode 100644 index 0000000000000..1ae6e81d2ab31 --- /dev/null +++ b/administrator/components/com_languages/views/overrides/tmpl/default.php @@ -0,0 +1,88 @@ +escape($this->state->get('list.ordering')); +$listDirn = $this->escape($this->state->get('list.direction')); +$saveOrder = $listOrder == 'a.ordering'; ?> +
    +
    + +
    + + + + + +
    +
    +
    + + + + + + + + + + + + + + + + +authorise('core.edit', 'com_languages'); + $i = 0; + foreach($this->items as $key => $text): ?> + + + + + + + + +
    + + + + + + + +
    + pagination->getListFooter(); ?> +
    + + + + escape($key); ?> + + escape($key); ?> + + + escape($text); ?> + + pagination->getRowOffset($i); ?> +
    +
    + + + + + +
    +
    \ No newline at end of file diff --git a/administrator/components/com_languages/views/overrides/tmpl/index.html b/administrator/components/com_languages/views/overrides/tmpl/index.html new file mode 100644 index 0000000000000..fa6d84e8055f5 --- /dev/null +++ b/administrator/components/com_languages/views/overrides/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/administrator/components/com_languages/views/overrides/view.html.php b/administrator/components/com_languages/views/overrides/view.html.php new file mode 100644 index 0000000000000..2d47058ac48a4 --- /dev/null +++ b/administrator/components/com_languages/views/overrides/view.html.php @@ -0,0 +1,84 @@ +addStyleSheet(JURI::root().'media/system/css/overrider.css'); + //JHTML::core(); + $doc->addScript(JURI::root().'media/system/js/overrider.js'); + + // Get data from the model + $state = $this->get('State'); + $items = $this->get('Overrides'); + $pagination = $this->get('Pagination'); + + $this->assignRef('state', $state); + $this->assignRef('items', $items); + $this->assignRef('pagination', $pagination); + + $this->addToolbar(); + parent::display($tpl); + } + + protected function addToolbar() + { + // Get the results for each action + $canDo = LanguagesHelper::getActions(); + + JToolBarHelper::title(JText::_('COM_LANGUAGES_VIEW_OVERRIDES_TITLE'), 'langmanager'); + + if($canDo->get('core.create')) + { + JToolbarHelper::addNew('override.add'); + } + + if($canDo->get('core.edit') && $this->pagination->total) + { + JToolbarHelper::editList('override.edit'); + } + + if($canDo->get('core.delete') && $this->pagination->total) + { + JToolbarHelper::deleteList('', 'overrides.delete'); + } + + if($canDo->get('core.admin')) + { + JToolBarHelper::preferences('com_languages'); + } + } +} \ No newline at end of file diff --git a/administrator/language/en-GB/en-GB.com_languages.ini b/administrator/language/en-GB/en-GB.com_languages.ini index a387931a378f5..9657a9df0701f 100644 --- a/administrator/language/en-GB/en-GB.com_languages.ini +++ b/administrator/language/en-GB/en-GB.com_languages.ini @@ -14,6 +14,12 @@ COM_LANGUAGES_FIELD_IMAGE_DESC="Prefix of the image file for this language when COM_LANGUAGES_FIELD_IMAGE_LABEL="Image Prefix" COM_LANGUAGES_FIELD_LANG_TAG_DESC="Enter here the language tag – example: en-GB for English (UK). This should be the exact prefix used for the language installed or to be installed." COM_LANGUAGES_FIELD_LANG_TAG_LABEL="Language Tag" +COM_LANGUAGES_OVERRIDE_FIELD_KEY_LABEL="Language Constant" +COM_LANGUAGES_OVERRIDE_FIELD_KEY_DESC="The language constant of the string you want to override. If you don't know the constant please use the search box on the right in order to search for the text to override." +COM_LANGUAGES_OVERRIDE_FIELD_OVERRIDE_LABEL="Text" +COM_LANGUAGES_OVERRIDE_FIELD_OVERRIDE_DESC="Here you can enter the text which you want to be displayed instead of the overridden one." +COM_LANGUAGES_OVERRIDE_FIELD_SEARCHSTRING_LABEL="Search Text" +COM_LANGUAGES_OVERRIDE_FIELD_SEARCHSTRING_DESC="Please enter the text to search for here. It may be in any of the language files." COM_LANGUAGES_FIELD_PUBLISHED_DESC="Whether this content language is published or not. If published, it will display as a choice in the Language Switcher module in frontend." COM_LANGUAGES_FIELD_LANG_CODE_DESC="This Language Code will be appended to the site url. When SEF is enabled, one will get http://mysite.com/en/. If SEF is disabled the suffix &lang=en will be appended at the end of the URL. Note the Language Code must be unique among all the languages." COM_LANGUAGES_FIELD_LANG_CODE_LABEL="URL Language Code" @@ -63,9 +69,26 @@ COM_LANGUAGES_SEARCH_IN_TITLE="Search in title" COM_LANGUAGES_SUBMENU_CONTENT="Content" COM_LANGUAGES_SUBMENU_INSTALLED_ADMINISTRATOR="Installed - Administrator" COM_LANGUAGES_SUBMENU_INSTALLED_SITE="Installed - Site" +COM_LANGUAGES_SUBMENU_OVERRIDES="Overrides" COM_LANGUAGES_VIEW_INSTALLED_TITLE="Language Manager: Installed Languages" COM_LANGUAGES_VIEW_LANGUAGE_EDIT_EDIT_TITLE="Language Manager: Edit Content Language" COM_LANGUAGES_VIEW_LANGUAGE_EDIT_NEW_TITLE="Language Manager: New Content Language" COM_LANGUAGES_VIEW_LANGUAGES_TITLE="Language Manager: Content Languages" +COM_LANGUAGES_VIEW_OVERRIDE_CLIENT_SITE="Site" +COM_LANGUAGES_VIEW_OVERRIDE_CLIENT_ADMINISTRATOR="Administrator" +COM_LANGUAGES_VIEW_OVERRIDE_CONSTANT_SEARCH_BUTTON="Language Constant?" +COM_LANGUAGES_VIEW_OVERRIDE_EDIT_TITLE="Language Manager: %1$s Override for Language '%2$s'" +COM_LANGUAGES_VIEW_OVERRIDE_EDIT_NEW_OVERRIDE_LEGEND="Create a New Override" +COM_LANGUAGES_VIEW_OVERRIDE_EDIT_EDIT_OVERRIDE_LEGEND="Edit this Override" +COM_LANGUAGES_VIEW_OVERRIDE_MORE_RESULTS="More Results" +COM_LANGUAGES_VIEW_OVERRIDE_REFRESHING="Please wait while the cache is recreated." +COM_LANGUAGES_VIEW_OVERRIDE_RESULTS_LEGEND="Search Results" +COM_LANGUAGES_VIEW_OVERRIDE_SAVE_SUCCESS="Language Override was saved successfully." +COM_LANGUAGES_VIEW_OVERRIDE_SEARCH_BUTTON="Search" +COM_LANGUAGES_VIEW_OVERRIDE_SEARCH_LEGEND="Search Text" +COM_LANGUAGES_VIEW_OVERRIDES_FILTER_SEARCH_DESC="Search constant or text." +COM_LANGUAGES_VIEW_OVERRIDES_KEY="Constant" +COM_LANGUAGES_VIEW_OVERRIDES_TEXT="Text" +COM_LANGUAGES_VIEW_OVERRIDES_TITLE="Language Manager: Language Overrides" COM_LANGUAGES_XML_DESCRIPTION="Component for language management" -JLIB_RULES_SETTING_NOTES="1. If you change the setting, it will apply to this component. Note that:
    Inherited means that the permissions from global configuration and parent group will be used.
    Denied means that no matter what the global configuration or parent group settings are, the group being edited cannot take this action on this component.
    Allowed means that the group being edited will be able to take this action for this component (but if this is in conflict with the global configuration or parent group it will have no impact; a conflict will be indicated by Not Allowed (Locked) under Calculated Settings).
    2. If you select a new setting, click Save to refresh the calculated settings." +JLIB_RULES_SETTING_NOTES="1. If you change the setting, it will apply to this component. Note that:
    Inherited means that the permissions from global configuration and parent group will be used.
    Denied means that no matter what the global configuration or parent group settings are, the group being edited cannot take this action on this component.
    Allowed means that the group being edited will be able to take this action for this component (but if this is in conflict with the global configuration or parent group it will have no impact; a conflict will be indicated by Not Allowed (Locked) under Calculated Settings).
    2. If you select a new setting, click Save to refresh the calculated settings." \ No newline at end of file diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql index aee2cbdc01390..e599109e3f994 100644 --- a/installation/sql/mysql/joomla.sql +++ b/installation/sql/mysql/joomla.sql @@ -790,6 +790,21 @@ CREATE TABLE `#__newsfeeds` ( ) DEFAULT CHARSET=utf8; +# ------------------------------------------------------- + +# +# Table structure for table `#__overrider` +# + +CREATE TABLE IF NOT EXISTS `#__overrider` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key', + `constant` varchar(255) NOT NULL, + `string` text NOT NULL, + `file` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) DEFAULT CHARSET=utf8; + + # ------------------------------------------------------- # diff --git a/media/system/css/overrider.css b/media/system/css/overrider.css new file mode 100644 index 0000000000000..ea12496b54ced --- /dev/null +++ b/media/system/css/overrider.css @@ -0,0 +1,80 @@ +/* $HeadURL: https://joomgallery.org/svn/joomgallery/JG-2.0/JG/trunk/media/joomgallery/css/admin.joomgallery.css $*/ +/* $Id: admin.joomgallery.css 3420 2011-10-16 18:13:35Z chraneco $*/ +/****************************************************************************************\ +** JoomGallery 2.0 ** +** By: JoomGallery::ProjectTeam ** +** Copyright (C) 2008 - 2011 JoomGallery::ProjectTeam ** +** Based on: JoomGallery 1.0.0 by JoomGallery::ProjectTeam ** +** Released under GNU GPL Public License ** +** License: http://www.gnu.org/copyleft/gpl.html or have a look ** +** at administrator/components/com_joomgallery/LICENSE.TXT ** +\****************************************************************************************/ + +/** + * Joomgallery Admin CSS styles + **/ +#results-container{padding-bottom:10px;} +.jg_spinner { + background-image:url(../../system/images/modal/spinner.gif); + background-repeat:no-repeat; + background-position:center; +} + +/* ///////////////// */ +.spinner { + position: absolute; + opacity: 0.9; + z-index: 999; + background: #fff; +} + +.spinner-img { + background: url('../images/spinner.gif') no-repeat; + width: 66px; + height: 66px; +} + +.row0{ + background-color:#f7f7f7; +} +.row1{ + background-color:#f0f0f0; + border-top:1px solid #ffffff; +} +.result{ + padding:5px 0px; + border:1px solid #ffffff; +} +.result:hover{ + background-color:#e8f6fe; + cursor:pointer; +} + +.result-key{ + color:#666666; + padding-left:5px; +} + +.result-string{ + padding-left:25px; + margin-top:5px; +} + +#more-results{ + height:16px; + padding:10px 0; +} + +#refresh-status{ + height:16px; +} + +.save-spinner { + background-image:url(../../system/images/modal/spinner.gif); + background-repeat:no-repeat; + background-position:center; + width:16px; + height:16px; + float:right; + margin-right:8px; +} \ No newline at end of file diff --git a/media/system/js/overrider.js b/media/system/js/overrider.js new file mode 100644 index 0000000000000..2935299940098 --- /dev/null +++ b/media/system/js/overrider.js @@ -0,0 +1,225 @@ +// $HeadURL: https://joomgallery.org/svn/joomgallery/JG-2.0/JG/trunk/media/joomgallery/js/admin.js $ +// $Id: admin.js 3383 2011-10-07 20:30:32Z erftralle $ +/****************************************************************************************\ +** JoomGallery 2 ** +** By: JoomGallery::ProjectTeam ** +** Copyright (C) 2008 - 2011 JoomGallery::ProjectTeam ** +** Based on: JoomGallery 1.0.0 by JoomGallery::ProjectTeam ** +** Released under GNU GPL Public License ** +** License: http://www.gnu.org/copyleft/gpl.html or have a look ** +** at administrator/components/com_joomgallery/LICENSE.TXT ** +\****************************************************************************************/ + +/** + * Overwrite function for Joomla.submitbutton. + * Submits the form. + * + * @param string pressbutton The button pressed + * @return void + */ + +Joomla.overrider = { + states : { + refreshing:false, + counter:0 + } +}; + +Joomla.overrider.refreshCache = function() +{ + var req = new Request.JSON({ + method: 'post', + url: 'index.php?option=com_languages&task=strings.refresh&format=json', + onRequest: function() { + this.states.refreshing = true; + document.id('refresh-status').reveal(); + }.bind(this), + onSuccess: function(r) { + if (r.messages) { + Joomla.renderMessages(r.messages); + } + document.id('refresh-status').dissolve(); + this.states.refreshing = false; + }.bind(this), + onFailure: function(xhr) { + var r = JSON.decode(xhr.responseText); + if (r) { + alert(r.message); + } + }.bind(this) + }); + req.post(); +}; + +Joomla.overrider.searchStrings = function(searchstring, more) +{ + if(this.states.refreshing) + { + return; + } + var req = new Request.JSON({ + method: 'post', + url: 'index.php?option=com_languages&task=strings.search&format=json', + onRequest: function() { + if(more) + { + document.id('more-results').addClass('jg_spinner'); + } + else + { + document.id('more-results').set('style', 'display:none;'); + var children = $$('#results-container div'); + children.destroy(); + document.id('results-container').addClass('jg_spinner').reveal(); + } + }.bind(this), + onSuccess: function(r) { + if (r.messages) { + Joomla.renderMessages(r.messages); + } + if(r.data) + { + if(r.data.results) + { + this.insertResults(r.data.results); + } + if(r.data.more) + { + this.states.more = r.data.more; + document.id('more-results').reveal(); + } + else + { + document.id('more-results').set('style', 'display:none;'); + } + } + document.id('results-container').removeClass('jg_spinner'); + document.id('more-results').removeClass('jg_spinner'); + }.bind(this), + onFailure: function(xhr) { + document.id('results-container').removeClass('jg_spinner'); + document.id('more-results').removeClass('jg_spinner'); + var r = JSON.decode(xhr.responseText); + if (r) { + alert(r.message); + } + }.bind(this) + }); + req.post('searchstring=' + searchstring + '&more=' + more); +}; + +Joomla.overrider.insertResults = function(results) +{ + this.states.counter = this.states.counter + 1; + + var results_div = new Element('div', { + id: 'language-results' + this.states.counter, + style: 'display:none;' + }); + Array.each(results, function (item, index) { + var div = new Element('div', { + class: 'result row' + index%2, + onclick: 'Joomla.overrider.selectString(' + this.states.counter + index + ');', + }); + var key = new Element('div', { + id: 'override_key' + this.states.counter + index, + class: 'result-key', + html: item.constant + }); + key.inject(div); + var string = new Element('div', { + id: 'override_string' + this.states.counter + index, + class: 'result-string', + html: item.string + }); + string.inject(div); + div.inject(results_div); + }, this); + results_div.inject(document.id('more-results'), 'before'); + document.id('language-results' + this.states.counter).reveal(); +}; + +Joomla.overrider.selectString = function(id) +{ + document.id('jform_key').value = document.id('override_key' + id).get('html'); + document.id('jform_override').value = document.id('override_string' + id).get('html'); + new Fx.Scroll(window).toTop(); +}; + +Joomla.overrider.edit = function(key) +{ + var newKey = new Element('input', { + type: 'text', + id: 'new-key[' + key + ']', + class: 'inputbox', + style: 'display:none', + size: 80, + value: document.id('key[' + key + ']').get('html') + }); + + var newString = new Element('textarea', { + id: 'new-string[' + key + ']', + class: 'inputbox', + style: 'display:none;width:92%;', + cols: 60, + rows: 5, + value: document.id('string[' + key + ']').get('html') + }); + + newKey.inject('key[' + key + ']', 'after'); + newString.inject('string[' + key + ']', 'after'); + document.id('key[' + key + ']').dissolve(); + document.id('string[' + key + ']').dissolve(); + document.id('new-key[' + key + ']').reveal(); + document.id('new-string[' + key + ']').reveal(); + + var a = new Element('a', { + id: 'save-button[' + key + ']', + class: 'saveorder', + title: 'Save Order', + href: 'javascript:Joomla.overrider.save(\'' + key + '\');' + }); + + a.inject('new-string[' + key + ']', 'before'); +}; + +Joomla.overrider.save = function(key) +{ + document.id('adminForm').task.value = 'override.save'; + + var req = new Request.JSON({ + method: 'post', + url: 'index.php?option=com_languages&format=json', + onRequest: function() { + document.id('save-button[' + key + ']').removeClass('saveorder'); + document.id('save-button[' + key + ']').addClass('save-spinner'); + }.bind(this), + onSuccess: function(r) { + if (r.messages) { + Joomla.renderMessages(r.messages); + } + if(r.success) + { + document.id('key[' + key + ']').set('html', document.id('new-key[' + key + ']').value); + document.id('string[' + key + ']').set('html', document.id('new-string[' + key + ']').value); + document.id('save-button[' + key + ']').nix(true); + document.id('new-key[' + key + ']').nix(true); + document.id('new-string[' + key + ']').nix(true); + document.id('key[' + key + ']').reveal(); + document.id('string[' + key + ']').reveal(); + } + else + { + new Fx.Scroll(window).toTop(); + } + }.bind(this), + onFailure: function(xhr) {alert(xhr); + document.id('save-button[' + key + ']').removeClass('save-spinner'); + var r = JSON.decode(xhr.responseText); + if (r) { + alert(r.message); + } + }.bind(this) + }); + req.post(document.id('adminForm').toQueryString() + '&jform[key]=' + encodeURIComponent(document.id('new-key[' + key + ']').value) + '&jform[override]=' + encodeURIComponent(document.id('new-string[' + key + ']').value) + '&id=' + encodeURIComponent(document.id('key[' + key + ']').get('html'))); +}; \ No newline at end of file From ac704aabe2ad8d04495ca64ea675030ba400fb9e Mon Sep 17 00:00:00 2001 From: Chraneco Date: Tue, 6 Dec 2011 20:45:01 +0100 Subject: [PATCH 02/17] Clean up - Small improvements - Code Style --- .../controllers/override.json.php | 121 ---------- .../com_languages/controllers/override.php | 190 ++++++--------- .../com_languages/controllers/overrides.php | 70 +++--- .../controllers/strings.json.php | 53 +++-- .../com_languages/helpers/helper.php | 129 ---------- .../com_languages/helpers/jsonresponse.php | 66 ++--- .../com_languages/helpers/languages.php | 55 ++++- .../com_languages/models/forms/override.xml | 3 +- .../com_languages/models/override.php | 107 +++++---- .../com_languages/models/overrides.php | 180 +++++++------- .../com_languages/models/strings.php | 84 ++++--- .../views/override/tmpl/edit.php | 13 +- .../views/override/view.html.php | 86 ++++--- .../views/overrides/tmpl/default.php | 15 +- .../views/overrides/view.html.php | 98 +++++--- .../language/en-GB/en-GB.com_languages.ini | 7 +- logs/error.php | 7 + media/overrider/css/index.html | 1 + media/overrider/css/overrider.css | 53 +++++ media/overrider/index.html | 1 + media/overrider/js/index.html | 1 + media/overrider/js/overrider.js | 190 +++++++++++++++ media/system/css/overrider.css | 80 ------- media/system/js/mootools-core-uncompressed.js | 2 +- media/system/js/overrider.js | 225 ------------------ 25 files changed, 837 insertions(+), 1000 deletions(-) delete mode 100644 administrator/components/com_languages/controllers/override.json.php delete mode 100644 administrator/components/com_languages/helpers/helper.php create mode 100644 logs/error.php create mode 100644 media/overrider/css/index.html create mode 100644 media/overrider/css/overrider.css create mode 100644 media/overrider/index.html create mode 100644 media/overrider/js/index.html create mode 100644 media/overrider/js/overrider.js delete mode 100644 media/system/css/overrider.css delete mode 100644 media/system/js/overrider.js diff --git a/administrator/components/com_languages/controllers/override.json.php b/administrator/components/com_languages/controllers/override.json.php deleted file mode 100644 index dd6fdb0818bea..0000000000000 --- a/administrator/components/com_languages/controllers/override.json.php +++ /dev/null @@ -1,121 +0,0 @@ -getModel(); - $data = JRequest::getVar('jform', array(), 'post', 'array'); - $context = "$this->option.edit.$this->context"; - $task = $this->getTask(); - - // Determine the name of the primary key for the data. - if (empty($key)) { - $key = 'id'; - } - - // To avoid data collisions the urlVar may be different from the primary key. - if (empty($urlVar)) { - $urlVar = $key; - } - - $recordId = JRequest::getCmd($urlVar); - - $data[$key] = $recordId; - - $session = JFactory::getSession(); - $registry = $session->get('registry'); - - // Access check. - if (!$this->allowSave($data, $key)) { - echo new JoomJsonResponse(new Exception(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'))); - - return; - } - - // Validate the posted data. - // Sometimes the form needs some posted data, such as for plugins and modules. - $form = $model->getForm($data, false); - - if (!$form) { - echo new JoomJsonResponse(new Exception($model->getError())); - - return; - } - - // Test whether the data is valid. - $validData = $model->validate($form, $data); - - // Check for validation errors. - if ($validData === false) { - // Get the validation messages. - $errors = $model->getErrors(); - - // Push up to three validation messages out to the user. - for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) - { - if (JError::isError($errors[$i])) { - $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); - } - else { - $app->enqueueMessage($errors[$i], 'warning'); - } - } - - echo new JoomJsonResponse(new Exception('Invalid form')); - - return; - } - - // Attempt to save the data. - if (!$model->save($validData)) { - echo new JoomJsonResponse(new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()))); - - return; - } - - $this->setMessage(JText::_('COM_OVERRIDER_SAVE_SUCCESS')); - - echo new JoomJsonResponse(); - - return; - } -} \ No newline at end of file diff --git a/administrator/components/com_languages/controllers/override.php b/administrator/components/com_languages/controllers/override.php index cb35349c97f5b..094e74403c3b4 100644 --- a/administrator/components/com_languages/controllers/override.php +++ b/administrator/components/com_languages/controllers/override.php @@ -1,62 +1,46 @@ getModel(); $cid = JRequest::getVar('cid', array(), 'post', 'array'); $context = "$this->option.edit.$this->context"; - $append = ''; - - // Determine the name of the primary key for the data. - if (empty($key)) { - $key = 'id'; - } - // To avoid data collisions the urlVar may be different from the primary key. - if (empty($urlVar)) { - $urlVar = $key; - } + // Get the constant name + $recordId = (count($cid) ? $cid[0] : JRequest::getCmd('id')); - // Get the previous record id (if any) and the current record id. - $recordId = (count($cid) ? $cid[0] : JRequest::getCmd($urlVar)); - - // Access check. - if (!$this->allowEdit()) { + // Access check + if (!$this->allowEdit()) + { $this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); @@ -64,55 +48,36 @@ public function edit($key = null, $urlVar = null) return false; } - // Check-out succeeded, push the new record id into the session. - //$this->holdEditId($context, $recordId); - $app->setUserState($context.'.data', null); - $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, $urlVar)); + $app->setUserState($context.'.data', null); + $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, 'id')); - return true; + return true; } /** * Method to save a record. * - * @param string $key The name of the primary key of the URL variable. - * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). - * * @return boolean True if successful, false otherwise. * @since 11.1 */ - public function save($key = null, $urlVar = null) + public function save() { - // Check for request forgeries. + // Check for request forgeries JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN')); - // Initialise variables. - $app = JFactory::getApplication(); - $lang = JFactory::getLanguage(); - $model = $this->getModel(); - $data = JRequest::getVar('jform', array(), 'post', 'array'); - $context = "$this->option.edit.$this->context"; - $task = $this->getTask(); - - // Determine the name of the primary key for the data. - if (empty($key)) { - $key = 'id'; - } - - // To avoid data collisions the urlVar may be different from the primary key. - if (empty($urlVar)) { - $urlVar = $key; - } - - $recordId = JRequest::getCmd($urlVar); - - $data[$key] = $recordId; + // Initialize variables + $app = JFactory::getApplication(); + $model = $this->getModel(); + $data = JRequest::getVar('jform', array(), 'post', 'array'); + $context = "$this->option.edit.$this->context"; + $task = $this->getTask(); - $session = JFactory::getSession(); - $registry = $session->get('registry'); + $recordId = JRequest::getCmd('id'); + $data['id'] = $recordId; - // Access check. - if (!$this->allowSave($data, $key)) { + // Access check + if (!$this->allowSave($data, 'id')) + { $this->setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); @@ -120,11 +85,10 @@ public function save($key = null, $urlVar = null) return false; } - // Validate the posted data. - // Sometimes the form needs some posted data, such as for plugins and modules. + // Validate the posted data $form = $model->getForm($data, false); - - if (!$form) { + if (!$form) + { $app->enqueueMessage($model->getError(), 'error'); return false; @@ -137,17 +101,20 @@ public function save($key = null, $urlVar = null) $validData = $model->validate($form, $data); // Check for validation errors. - if ($validData === false) { - // Get the validation messages. + if ($validData === false) + { + // Get the validation messages $errors = $model->getErrors(); // Push up to three validation messages out to the user. for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) { - if (JError::isError($errors[$i])) { + if (JError::isError($errors[$i])) + { $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); } - else { + else + { $app->enqueueMessage($errors[$i], 'warning'); } } @@ -155,84 +122,75 @@ public function save($key = null, $urlVar = null) // Save the data in the session $app->setUserState($context.'.data', $data); - // Redirect back to the edit screen. - $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, $key), false)); + // Redirect back to the edit screen + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, 'id'), false)); return false; } - // Attempt to save the data. - if (!$model->save($validData)) { - // Save the data in the session. + // Attempt to save the data + if (!$model->save($validData)) + { + // Save the data in the session $app->setUserState($context.'.data', $validData); - // Redirect back to the edit screen. + // Redirect back to the edit screen $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); - $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, $key), false)); + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($recordId, 'id'), false)); return false; } - + // Add message of success $this->setMessage(JText::_('COM_LANGUAGES_VIEW_OVERRIDE_SAVE_SUCCESS')); - // Redirect the user and adjust session state based on the chosen task. + // Redirect the user and adjust session state based on the chosen task switch ($task) { case 'apply': - // Set the record data in the session. + // Set the record data in the session $recordId = $model->getState($this->context.'.id'); $app->setUserState($context.'.data', null); - // Redirect back to the edit screen. - $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($validData['key'], $key), false)); + // Redirect back to the edit screen + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend($validData['key'], 'id'), false)); break; case 'save2new': - // Clear the record id and data from the session. + // Clear the record id and data from the session $app->setUserState($context.'.data', null); - // Redirect back to the edit screen. - $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend(null, $key), false)); + // Redirect back to the edit screen + $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$this->getRedirectToItemAppend(null, 'id'), false)); break; default: - // Clear the record id and data from the session. + // Clear the record id and data from the session $app->setUserState($context.'.data', null); - // Redirect to the list screen. + // Redirect to the list screen $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); break; } - // Invoke the postSave method to allow for the child class to access the model. - $this->postSaveHook($model, $validData); - return true; } /** * Method to cancel an edit. * - * @param string $key The name of the primary key of the URL variable. - * - * @return boolean True if access level checks pass, false otherwise. - * @since 11.1 + * @return boolean True + * + * @since 2.5 */ - public function cancel($key = null) + public function cancel() { JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN')); - // Initialise variables. - $app = JFactory::getApplication(); - $context = "$this->option.edit.$this->context"; - - if (empty($key)) { - $key = 'id'; - } - - $recordId = JRequest::getCmd($key); + // Initialize variables + $app = JFactory::getApplication(); + $context = "$this->option.edit.$this->context"; $app->setUserState($context.'.data', null); $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list.$this->getRedirectToListAppend(), false)); diff --git a/administrator/components/com_languages/controllers/overrides.php b/administrator/components/com_languages/controllers/overrides.php index bb4f579fae6b5..7b93120f0f990 100644 --- a/administrator/components/com_languages/controllers/overrides.php +++ b/administrator/components/com_languages/controllers/overrides.php @@ -1,61 +1,69 @@ text_prefix.'_NO_ITEM_SELECTED')); - } else { - // Get the model. - $model = $this->getModel(); + if (!is_array($cid) || count($cid) < 1) + { + $this->setMessage(JText::_($this->text_prefix.'_NO_ITEM_SELECTED'), 'warning'); + } + else + { + // Get the model + $model = $this->getModel('overrides'); - // Remove the items. - if ($model->delete($cid)) { + // Remove the items + if ($model->delete($cid)) + { $this->setMessage(JText::plural($this->text_prefix.'_N_ITEMS_DELETED', count($cid))); - } else { + } + else + { $this->setMessage($model->getError()); } } $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false)); } - - /** - * Proxy for getModel. - * - * @param string $name The name of the model. - * @param string $prefix The prefix for the PHP class name. - * - * @return JModel - * @since 1.6 - */ - public function getModel($name = 'Overrides', $prefix = 'OverriderModel', $config = array('ignore_request' => true)) - { - $model = parent::getModel($name, $prefix, $config); - - return $model; - } } \ No newline at end of file diff --git a/administrator/components/com_languages/controllers/strings.json.php b/administrator/components/com_languages/controllers/strings.json.php index 8943bf3d055a1..a71ce28f57ffb 100644 --- a/administrator/components/com_languages/controllers/strings.json.php +++ b/administrator/components/com_languages/controllers/strings.json.php @@ -1,20 +1,23 @@ getModel()->refresh()); - } - - public function search() - { - echo new JoomJsonResponse($this->getModel()->search()); + echo new JJsonResponse($this->getModel('strings')->refresh()); } - /** - * Proxy for getModel. - * - * @param string $name The name of the model. - * @param string $prefix The prefix for the PHP class name. - * - * @return JModel - * @since 1.6 - */ - public function getModel($name = 'Strings', $prefix = 'LanguagesModel', $config = array('ignore_request' => true)) + /** + * Method for searching language strings + * + * @return array Array of resuls on success, Exception object otherwise + * + * @since 2.5 + */ + public function search() { - $model = parent::getModel($name, $prefix, $config); - - return $model; + echo new JJsonResponse($this->getModel('strings')->search()); } } \ No newline at end of file diff --git a/administrator/components/com_languages/helpers/helper.php b/administrator/components/com_languages/helpers/helper.php deleted file mode 100644 index e03be20b3729a..0000000000000 --- a/administrator/components/com_languages/helpers/helper.php +++ /dev/null @@ -1,129 +0,0 @@ -getUserState('com_overrider.client', 'site'); - - $clients = array( 'site' => JText::_('COM_OVERRIDER_SUBMENU_SITE'), - 'administrator' => JText::_('COM_OVERRIDER_SUBMENU_ADMINISTRATOR') - ); - - foreach($clients as $client => $title) - { - JSubMenuHelper::addEntry( $title, - 'index.php?option=com_overrider&client='.$client, - $client == $current_client - ); - } - } - - /** - * Returns a list of the actions that can be performed - * - * @param string $type The type of the content to check - * @param int $id The ID of the content (category or image) - * @return JObject An object holding the results of the check - * @since 2.0 - */ - public static function getActions() - { - static $cache = null; - - if(!empty($cache)) - { - return $cache; - } - - $user = JFactory::getUser(); - $result = new JObject(); - - $actions = array('core.admin', 'core.manage', 'core.create', 'core.edit', 'core.delete'); - - foreach($actions as $action) - { - $result->set($action, $user->authorise($action, 'com_overrider')); - } - - // Store the result for better performance - $cache = $result; - - return $result; - } - - public function parse($client = 'site', $language = 'en-GB') - { - $filename = constant('JPATH_'.strtoupper($client)).DS.'language'.DS.'overrides'.DS.$language.'.override.ini'; - - return OverriderHelper::parseFile($filename); - } - - public function parseFile($filename) - { - jimport('joomla.filesystem.file'); - - if(!JFile::exists($filename)) - { - return array(); - } - - // Capture hidden PHP errors from the parsing. - $version = phpversion(); - $php_errormsg = null; - $track_errors = ini_get('track_errors'); - ini_set('track_errors', true); - - if($version >= '5.3.1') - { - $contents = file_get_contents($filename); - $contents = str_replace('_QQ_', '"\""', $contents); - $strings = @parse_ini_string($contents); - } - else - { - $strings = @parse_ini_file($filename); - - if($version == '5.3.0' && is_array($strings)) - { - foreach($strings as $key => $string) - { - $strings[$key]=str_replace('_QQ_', '"', $string); - } - } - } - - return $strings; - } - - static function filter($value) - { - return str_replace('"', '"_QQ_"', $value); - } -} \ No newline at end of file diff --git a/administrator/components/com_languages/helpers/jsonresponse.php b/administrator/components/com_languages/helpers/jsonresponse.php index 209233af8c472..aa4ae0ad0e0e3 100644 --- a/administrator/components/com_languages/helpers/jsonresponse.php +++ b/administrator/components/com_languages/helpers/jsonresponse.php @@ -1,30 +1,28 @@ success, * so you can use both flags equivalently. * - * var boolean + * var boolean + * @since 2.5 */ public $error = false; /** * The main response message * - * var boolean + * var string + * @since 2.5 */ public $message = null; /** * Array of messages gathered in the JApplication object * - * var array + * var array + * @since 2.5 */ public $messages = null; /** * The response data * - * var array/object + * var array/object + * @since 2.5 */ public $data = null; /** * Constructor * + * @param array/object $response The Response data + * @param string $message The main response message + * @param boolean $error True, if the success flag shall be set to false, defaults to false + * * @return void - * @since 2.1 + * + * @since 2.5 */ public function __construct($response = null, $message = null, $error = false) { @@ -71,12 +78,12 @@ public function __construct($response = null, $message = null, $error = false) // Get the message queue $messages = JFactory::getApplication()->getMessageQueue(); - // Build the sorted message list - if(is_array($messages) && count($messages)) + // Build the sorted messages list + if (is_array($messages) && count($messages)) { - foreach($messages as $message) + foreach ($messages as $message) { - if(isset($message['type']) && isset($message['message'])) + if (isset($message['type']) && isset($message['message'])) { $lists[$message['type']][] = $message['message']; } @@ -84,13 +91,13 @@ public function __construct($response = null, $message = null, $error = false) } // If messages exist add them to the output - if(isset($lists) && is_array($lists)) + if (isset($lists) && is_array($lists)) { $this->messages = $lists; } // Check if we are dealing with an error - if(JError::isError($response)) + if ($response instanceof Exception) { // Prepare the error response $this->success = false; @@ -110,7 +117,8 @@ public function __construct($response = null, $message = null, $error = false) * Magic toString method for sending the response in JSON format * * @return string The response in JSON format - * @since 2.1 + * + * @since 2.5 */ public function __toString() { diff --git a/administrator/components/com_languages/helpers/languages.php b/administrator/components/com_languages/helpers/languages.php index aaa28d5b82f6e..bc83f063efe8f 100644 --- a/administrator/components/com_languages/helpers/languages.php +++ b/administrator/components/com_languages/helpers/languages.php @@ -68,34 +68,53 @@ public static function getActions() return $result; } + /** + * Method for parsing ini files + * + * @param string $filename Path and name of the ini file to parse + * + * @return array Array of strings found in the file, the array indices will be the keys. On failure an empty array will be returned + * + * @since 2.5 + */ public function parseFile($filename) { jimport('joomla.filesystem.file'); - if(!JFile::exists($filename)) + if (!JFile::exists($filename)) { return array(); } - // Capture hidden PHP errors from the parsing. + // Capture hidden PHP errors from the parsing $version = phpversion(); $php_errormsg = null; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); - if($version >= '5.3.1') + if ($version >= '5.3.1') { $contents = file_get_contents($filename); $contents = str_replace('_QQ_', '"\""', $contents); $strings = @parse_ini_string($contents); + + if ($strings === false) + { + return array(); + } } else { $strings = @parse_ini_file($filename); - if($version == '5.3.0' && is_array($strings)) + if ($strings === false) + { + return array(); + } + + if ($version == '5.3.0' && is_array($strings)) { - foreach($strings as $key => $string) + foreach ($strings as $key => $string) { $strings[$key]=str_replace('_QQ_', '"', $string); } @@ -105,17 +124,37 @@ public function parseFile($filename) return $strings; } - static function filterKey($value) + /** + * Filter method for language keys. + * This method will be called by JForm while filtering the form data. + * + * @param string $value The language key to filter + * + * @return string The filtered language key + * + * @since 2.5 + */ + public static function filterKey($value) { $filter = JFilterInput::getInstance(null, null, 1, 1); return strtoupper($filter->clean($value, 'cmd')); } - static function filterText($value) + /** + * Filter method for language strings. + * This method will be called by JForm while filtering the form data. + * + * @param string $value The language string to filter + * + * @return string The filtered language string + * + * @since 2.5 + */ + public static function filterText($value) { $filter = JFilterInput::getInstance(null, null, 1, 1); return str_replace('"', '"_QQ_"', $filter->clean($value)); } -} +} \ No newline at end of file diff --git a/administrator/components/com_languages/models/forms/override.xml b/administrator/components/com_languages/models/forms/override.xml index 66fe451cda692..8448dce7d11ad 100644 --- a/administrator/components/com_languages/models/forms/override.xml +++ b/administrator/components/com_languages/models/forms/override.xml @@ -1,4 +1,5 @@ +
    + size="50" /> loadForm('com_languages.override', 'override', array('control' => 'jform', 'load_data' => $loadData)); if (empty($form)) { return false; @@ -46,15 +45,17 @@ public function getForm($data = array(), $loadData = true) /** * Method to get the data that should be injected in the form. * - * @return mixed The data for the form. - * @since 1.6 + * @return mixed The data for the form + * + * @since 2.5 */ protected function loadFormData() { // Check the session for previously entered form data. $data = JFactory::getApplication()->getUserState('com_languages.edit.override.data', array()); - if (empty($data)) { + if (empty($data)) + { $data = $this->getItem(); } @@ -64,10 +65,11 @@ protected function loadFormData() /** * Method to get a single record. * - * @param integer $pk The id of the primary key. + * @param string $pk The key name. * - * @return mixed Object on success, false on failure. - * @since 11.1 + * @return mixed Object on success, false otherwise. + * + * @since 2.5 */ public function getItem($pk = null) { @@ -78,12 +80,12 @@ public function getItem($pk = null) $strings = LanguagesHelper::parseFile($filename); $result = new stdClass(); - $result->key = ''; + $result->key = ''; $result->override = ''; - if(isset($strings[$pk])) + if (isset($strings[$pk])) { - $result->key = $pk; - $result->override = $strings[$pk]; + $result->key = $pk; + $result->override = $strings[$pk]; } return $result; @@ -92,43 +94,51 @@ public function getItem($pk = null) /** * Method to save the form data. * - * @param array $data The form data. + * @param array $data The form data. * - * @return boolean True on success, False on error. - * @since 11.1 + * @return boolean True on success, false otherwise. + * + * @since 2.5 */ public function save($data) { $app = JFactory::getApplication(); require_once JPATH_COMPONENT.'/helpers/languages.php'; - $client = $app->getUserState('com_languages.overrides.filter.client', 0) ? 'administrator' : 'site'; + $client = $app->getUserState('com_languages.overrides.filter.client', 0) ? 'administrator' : 'site'; $language = $app->getUserState('com_languages.overrides.filter.language', 'en-GB'); + // Parse the override.ini file in oder to get the keys and strings $filename = constant('JPATH_'.strtoupper($client)).DS.'language'.DS.'overrides'.DS.$language.'.override.ini'; - $strings = LanguagesHelper::parseFile($filename); + $strings = LanguagesHelper::parseFile($filename); - if(isset($strings[$data['id']])) + if (isset($strings[$data['id']])) { - if($data['key'] == $data['id']) + // If an existent string was edited check whether + // the name of the constant is still the same + if ($data['key'] == $data['id']) { + // If yes, simply override it $strings[$data['key']] = $data['override']; } else { + // If no, delete the old string and prepend the new one unset($strings[$data['id']]); $strings = array($data['key'] => $data['override']) + $strings; } } else { + // If it is a new override simply prepend it $strings = array($data['key'] => $data['override']) + $strings; } + // Write override.ini file with the strings $registry = new JRegistry(); $registry->loadObject($strings); - if(!JFile::write($filename, $registry->toString('INI'))) + if (!JFile::write($filename, $registry->toString('INI'))) { return false; } @@ -136,12 +146,15 @@ public function save($data) return true; } - /** - * Stock method to auto-populate the model state. - * - * @return void - * @since 11.1 - */ + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @return void + * + * @since 2.5 + */ protected function populateState() { $app = JFactory::getApplication(); @@ -151,9 +164,5 @@ protected function populateState() $language = $app->getUserStateFromRequest('com_languages.overrides.filter.language', 'filter_language', 'en-GB', 'cmd'); $this->setState('filter.language', $language); - - // Load the parameters. - $value = JComponentHelper::getParams($this->option); - $this->setState('params', $value); } } \ No newline at end of file diff --git a/administrator/components/com_languages/models/overrides.php b/administrator/components/com_languages/models/overrides.php index 98efb94a6b413..8eb9e3fc79c44 100644 --- a/administrator/components/com_languages/models/overrides.php +++ b/administrator/components/com_languages/models/overrides.php @@ -1,25 +1,23 @@ getStoreId(); - // Try to load the data from internal storage. - if(!empty($this->cache[$store])) + // Try to load the data from internal storage + if (!empty($this->cache[$store])) { return $this->cache[$store]; } + // Parse the override.ini file in oder to get the keys and strings $filename = constant('JPATH_'.strtoupper($this->getState('filter.client'))).DS.'language'.DS.'overrides'.DS.$this->getState('filter.language').'.override.ini'; $strings = LanguagesHelper::parseFile($filename); - if(!$all && $this->getTotal() > $this->getState('list.limit')) + // Consider the odering + if ($this->getState('list.ordering') == 'text') + { + if (strtoupper($this->getState('list.direction')) == 'DESC') + { + arsort($strings); + } + else + { + asort($strings); + } + } + else + { + if (strtoupper($this->getState('list.direction')) == 'DESC') + { + krsort($strings); + } + else + { + ksort($strings); + } + } + + // Consider the pagination + if (!$all && $this->getTotal() > $this->getState('list.limit')) { $strings = array_slice($strings, $this->getStart(), $this->getState('list.limit'), true); } - // Add the items to the internal cache. + // Add the items to the internal cache $this->cache[$store] = $strings; return $this->cache[$store]; } /** - * Method to get the pagination object for the list. - * This method uses 'getTotel', 'getStart' and the current - * list limit of this view. + * Method to get the total number of overrides * - * @return object A pagination object - * @since 2.0 - */ - /*function getPagination() - { - jimport('joomla.html.pagination'); - return new JPagination($this->getTotal(), $this->getStart(), $this->getState('list.limit')); - }*/ - - /** - * Method to get the total number of images - * - * @access public * @return int The total number of images * @since 1.5.5 */ - function getTotal() + public function getTotal() { - // Get a storage key. + // Get a storage key $store = $this->getStoreId('getTotal'); - // Try to load the data from internal storage. - if(!empty($this->cache[$store])) + // Try to load the data from internal storage + if (!empty($this->cache[$store])) { return $this->cache[$store]; } - // Add the total to the internal cache. + // Add the total to the internal cache $this->cache[$store] = count($this->getOverrides(true)); return $this->cache[$store]; } - /** - * Method to get the starting number of items for the data set. - * - * @return int The starting number of items available in the data set. - * @since 2.0 - */ - /*public function getStart() - { - $start = $this->getState('list.start'); - $limit = $this->getState('list.limit'); - $total = $this->getTotal(); - if($start > $total - $limit) - { - $start = max(0, (int)(ceil($total / $limit) - 1) * $limit); - } - - return $start; - }*/ - /** * Method to auto-populate the model state. * @@ -133,63 +127,79 @@ function getTotal() * * @param string An optional ordering field. * @param string An optional direction (asc|desc). + * * @return void - * @since 2.0 + * + * @since 2.5 */ protected function populateState($ordering = null, $direction = null) { - $client = $this->getUserStateFromRequest('com_languages.overrides.filter.client', 'filter_client', 0, 'int') ? 'administrator' : 'site'; - $this->setState('filter.client', $client); + $client = $this->getUserStateFromRequest('com_languages.overrides.filter.client', 'filter_client', 0, 'int'); + $this->setState('filter.client', $client ? 'administrator' : 'site'); $language = $this->getUserStateFromRequest('com_languages.overrides.filter.language', 'filter_language', 'en-GB', 'cmd'); $this->setState('filter.language', $language); - // List state information. + // Add filters to the session because they won't be stored there + // by 'getUserStateFromRequest' if they aren't in the current request + $app = JFactory::getApplication(); + $app->setUserState('com_languages.overrides.filter.client', $client); + $app->setUserState('com_languages.overrides.filter.language', $language); + + // List state information parent::populateState('key', 'asc'); } /** - * Method to delete one or more images + * Method to delete one or more overrides * - * @access public - * @return int Number of successfully deleted images, boolean false if an error occured - * @since 1.5.5 + * @param array Array of keys to delete + * + * @return int Number of successfully deleted overrides, boolean false if an error occured + * + * @since 2.5 */ - function delete($cids) + public function delete($cids) { - if(!JFactory::getUser()->authorise('core.delete', 'com_languages')) + // Check permissions first + if (!JFactory::getUser()->authorise('core.delete', 'com_languages')) { - $this->setError(JText::_('COM_OVERRIDES_ERROR_DELETE_NOT_PERMITTED')); + $this->setError(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED')); return false; } - $app = JFactory::getApplication(); - jimport('joomla.filesystem.file'); + require_once JPATH_COMPONENT.'/helpers/languages.php'; $app = JFactory::getApplication(); + // Parse the override.ini file in oder to get the keys and strings $filename = constant('JPATH_'.strtoupper($this->getState('filter.client'))).DS.'language'.DS.'overrides'.DS.$this->getState('filter.language').'.override.ini'; $strings = LanguagesHelper::parseFile($filename); - foreach($cids as $key) + // Unset strings that shall be deleted + foreach ($cids as $key) { - if(isset($strings[$key])) + if (isset($strings[$key])) { unset($strings[$key]); } } + // Write override.ini file with the left strings $registry = new JRegistry(); $registry->loadObject($strings); - $filename = constant('JPATH_'.strtoupper($app->getUserState('com_overrider.filter.client'))).DS.'language'.DS.'overrides'.DS.$app->getUserState('com_overrider.filter.language').'.override.ini'; + $filename = constant('JPATH_'.strtoupper($this->getState('filter.client'))).DS.'language'.DS.'overrides'.DS.$this->getState('filter.language').'.override.ini'; - JFile::write($filename, $registry->toString('INI')); + if (!JFile::write($filename, $registry->toString('INI'))) + { + return false; + } $this->cleanCache(); - return count($cid); + return count($cids); } } \ No newline at end of file diff --git a/administrator/components/com_languages/models/strings.php b/administrator/components/com_languages/models/strings.php index d0e1802855c54..969198ccdaf0d 100644 --- a/administrator/components/com_languages/models/strings.php +++ b/administrator/components/com_languages/models/strings.php @@ -1,28 +1,33 @@ setUserState('com_languages.overrides.cachedtime', null); + // Empty the database cache first try { - $this->_db->setQuery('TRUNCATE TABLE #__overrider'); + $this->_db->setQuery('TRUNCATE TABLE '.$this->_db->qn('#__overrider')); $this->_db->query(); } catch(JDatabaseException $e) @@ -41,43 +47,53 @@ public function refresh() return $e; } + // Create the insert query $query = $this->_db->getQuery(true) - ->insert('#__overrider') - ->columns('constant, string, file'); + ->insert($this->_db->qn('#__overrider')) + ->columns('constant, string, file'); - $client = $app->getUserState('com_languages.overrides.filter.client', 'site') ? 'administrator' : 'site'; + // Initialize some variables + $client = $app->getUserState('com_languages.overrides.filter.client', 'site') ? 'administrator' : 'site'; $language = $app->getUserState('com_languages.overrides.filter.language', 'en-GB'); + $base = constant('JPATH_'.strtoupper($client)).DS; $path = $base.'language'.DS.$language; $files = array(); + + // Parse common language directory if(JFolder::exists($path)) { $files = JFolder::files($path, $language.'.*ini$', false, true); } + // Parse language directories of components $path = $base.'components'; $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + // Parse language directories of modules $path = $base.'modules'; $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + // Parse language directories of templates $path = $base.'templates'; $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); + // Parse language directories of plugins $path = JPATH_ROOT.DS.'plugins'; $files = array_merge($files, JFolder::files($path, $language.'.*ini$', 3, true)); - foreach($files as $file) + // Parse all found ini files and add the strings to the database cache + foreach ($files as $file) { $strings = LanguagesHelper::parseFile($file); - if($strings && count($strings)) + if ($strings && count($strings)) { $query->clear('values'); - foreach($strings as $key => $string) + foreach ($strings as $key => $string) { - $query->values($this->_db->quote($key).','.$this->_db->quote($string).','.$this->_db->quote($file)); + $query->values($this->_db->q($key).','.$this->_db->q($string).','.$this->_db->q($file)); } try @@ -92,11 +108,19 @@ public function refresh() } } + // Update the cached time $app->setUserState('com_languages.overrides.cachedtime.'.$client.'.'.$language, time()); return true; } + /** + * Method for searching language strings + * + * @return array Array of resuls on success, Exception object otherwise + * + * @since 2.5 + */ public function search() { $results = array(); @@ -105,20 +129,26 @@ public function search() try { + $searchstring = $this->_db->q('%'.JRequest::getString('searchstring').'%'); + + // Create the search query $query = $this->_db->getQuery(true) ->select('constant, string, file') - ->from('#__overrider') - ->where('string LIKE '.$this->_db->quote('%'.JRequest::getString('searchstring').'%')); + ->from($this->_db->qn('#__overrider')) + ->where('constant LIKE '.$searchstring.' OR string LIKE '.$searchstring.' OR file LIKE '.$searchstring); + // Consider the limitstart according to the 'more' parameter and load the results $this->_db->setQuery($query, $limitstart, 10); $results['results'] = $this->_db->loadObjectList(); + // Check whether there are more results than already loaded $query->clear('select') ->select('COUNT(id)'); $this->_db->setQuery($query); - if($this->_db->loadResult() > $limitstart + 10) + if ($this->_db->loadResult() > $limitstart + 10) { + // If this is set a 'More Results' link will be displayed in the view $results['more'] = $limitstart + 10; } } diff --git a/administrator/components/com_languages/views/override/tmpl/edit.php b/administrator/components/com_languages/views/override/tmpl/edit.php index abae2b43fad1d..fa808d2a58738 100644 --- a/administrator/components/com_languages/views/override/tmpl/edit.php +++ b/administrator/components/com_languages/views/override/tmpl/edit.php @@ -1,16 +1,15 @@
      -
    • form->getInput('searchstring'); ?>
    -