diff --git a/administrator/components/com_admin/script.php b/administrator/components/com_admin/script.php index 67b97a8825308..3282cb3626a18 100644 --- a/administrator/components/com_admin/script.php +++ b/administrator/components/com_admin/script.php @@ -285,6 +285,7 @@ protected function updateManifestCaches() array('component', 'com_postinstall', '', 1), array('component', 'com_joomlaupdate', '', 1), array('component', 'com_fields', '', 1), + array('component', 'com_associations', '', 1), // Libraries array('library', 'phputf8', '', 0), @@ -1822,6 +1823,7 @@ public function updateAssets() 'com_ajax', 'com_postinstall', 'com_fields', + 'com_associations', ); foreach ($newComponents as $component) diff --git a/administrator/components/com_admin/sql/updates/mysql/3.7.0-2017-01-15.sql b/administrator/components/com_admin/sql/updates/mysql/3.7.0-2017-01-15.sql new file mode 100644 index 0000000000000..5b309f020fa4a --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/3.7.0-2017-01-15.sql @@ -0,0 +1,2 @@ +INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES +(34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/3.7.0-2017-01-15.sql b/administrator/components/com_admin/sql/updates/postgresql/3.7.0-2017-01-15.sql new file mode 100644 index 0000000000000..f244b43bedf4e --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/3.7.0-2017-01-15.sql @@ -0,0 +1,2 @@ +INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES +(34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0); diff --git a/administrator/components/com_associations/access.xml b/administrator/components/com_associations/access.xml new file mode 100644 index 0000000000000..e6fd1ec5258d2 --- /dev/null +++ b/administrator/components/com_associations/access.xml @@ -0,0 +1,8 @@ + + +
+ + + +
+
diff --git a/administrator/components/com_associations/associations.php b/administrator/components/com_associations/associations.php new file mode 100644 index 0000000000000..fdc4e88837ede --- /dev/null +++ b/administrator/components/com_associations/associations.php @@ -0,0 +1,41 @@ +authorise('core.manage', 'com_associations')) +{ + throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403); +} + +JLoader::register('AssociationsHelper', __DIR__ . '/helpers/associations.php'); + +// Check if user has permission to access the component item type. +$itemtype = JFactory::getApplication()->input->get('itemtype', '', 'string'); + +if ($itemtype !== '') +{ + list($extensionName, $typeName) = explode('.', $itemtype); + + if (!AssociationsHelper::hasSupport($extensionName)) + { + throw new Exception(JText::sprintf('COM_ASSOCIATIONS_COMPONENT_NOT_SUPPORTED', JText::_($extensionName)), 404); + } + + if (!JFactory::getUser()->authorise('core.manage', $extensionName)) + { + throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403); + } +} + +$controller = JControllerLegacy::getInstance('Associations'); +$controller->execute(JFactory::getApplication()->input->get('task')); +$controller->redirect(); diff --git a/administrator/components/com_associations/associations.xml b/administrator/components/com_associations/associations.xml new file mode 100644 index 0000000000000..2e058c522c09b --- /dev/null +++ b/administrator/components/com_associations/associations.xml @@ -0,0 +1,30 @@ + + + com_associations + Joomla! Project + Januar 2017 + (C) 2005 - 2016 Open Source Matters. All rights reserved. + GNU General Public License version 2 or later; see LICENSE.txt + admin@joomla.org + www.joomla.org + __DEPLOY_VERSION__ + COM_ASSOCIATIONS_XML_DESCRIPTION + + COM_ASSOCIATIONS + + access.xml + config.xml + associations.php + controller.php + controllers + helpers + layouts + models + views + + + language/en-GB.com_associations.ini + language/en-GB.com_associations.sys.ini + + + diff --git a/administrator/components/com_associations/config.xml b/administrator/components/com_associations/config.xml new file mode 100644 index 0000000000000..1074b48ec73fb --- /dev/null +++ b/administrator/components/com_associations/config.xml @@ -0,0 +1,17 @@ + + +
+ +
+
diff --git a/administrator/components/com_associations/controller.php b/administrator/components/com_associations/controller.php new file mode 100644 index 0000000000000..da3f9ed60e9fe --- /dev/null +++ b/administrator/components/com_associations/controller.php @@ -0,0 +1,27 @@ +input->get('itemtype')); + + $id = $this->input->get('id', 0); + + // Check if reference item can be edited. + if (!AssociationsHelper::allowEdit($extensionName, $typeName, $id)) + { + JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 'error'); + $this->setRedirect(JRoute::_('index.php?option=com_associations&view=associations', false)); + + return false; + } + + return parent::display(); + } + + /** + * Method for canceling the edit action + * + * @param string $key The name of the primary key of the URL variable. + * + * @return void. + * + * @since __DEPLOY_VERSION__ + */ + public function cancel($key = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + list($extensionName, $typeName) = explode('.', $this->input->get('itemtype')); + + // Only check in, if component item type allows to check out. + if (AssociationsHelper::typeSupportsCheckout($extensionName, $typeName)) + { + $ids = array(); + $targetId = $this->input->get('target-id', '', 'string'); + + if ($targetId !== '') + { + $ids = array_unique(explode(',', $targetId)); + } + + $ids[] = $this->input->get('id', 0); + + foreach ($ids as $key => $id) + { + AssociationsHelper::getItem($extensionName, $typeName, $id)->checkin(); + } + } + + $this->setRedirect(JRoute::_('index.php?option=com_associations&view=associations', false)); + } +} diff --git a/administrator/components/com_associations/controllers/associations.php b/administrator/components/com_associations/controllers/associations.php new file mode 100644 index 0000000000000..71ff7ef84bf00 --- /dev/null +++ b/administrator/components/com_associations/controllers/associations.php @@ -0,0 +1,71 @@ + true)) + { + return parent::getModel($name, $prefix, $config); + } + + /** + * Method to purge the associations table. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function purge() + { + $this->getModel('associations')->purge(); + $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); + } + + /** + * Method to delete the orphans from the associations table. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function clean() + { + $this->getModel('associations')->clean(); + $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); + } +} diff --git a/administrator/components/com_associations/helpers/associations.php b/administrator/components/com_associations/helpers/associations.php new file mode 100644 index 0000000000000..9e0252667f1a5 --- /dev/null +++ b/administrator/components/com_associations/helpers/associations.php @@ -0,0 +1,528 @@ +getAssociationList($typeName, $itemId); + + } + + /** + * Get the the instance of the extension helper class + * + * @param string $extensionName The extension name with com_ + * + * @return HelperClass|null + * + * @since __DEPLOY_VERSION__ + */ + public static function getExtensionHelper($extensionName) + { + if (!self::hasSupport($extensionName)) + { + return null; + } + + $support = self::$extensionsSupport[$extensionName]; + + return $support->get('helper'); + } + + /** + * Get item information + * + * @param string $extensionName The extension name with com_ + * @param string $typeName The item type + * @param int $itemId The id of item for which we need the associated items + * + * @return JTable|null + * + * @since __DEPLOY_VERSION__ + */ + public static function getItem($extensionName, $typeName, $itemId) + { + if (!self::hasSupport($extensionName)) + { + return array(); + } + + // Get the extension specific helper method + $helper = self::getExtensionHelper($extensionName); + + return $helper->getItem($typeName, $itemId); + } + + /** + * Check if extension supports associations + * + * @param string $extensionName The extension name with com_ + * + * @return bool + * + * @since __DEPLOY_VERSION__ + */ + public static function hasSupport($extensionName) + { + if (is_null(self::$extensionsSupport)) + { + self::getSupportedExtensions(); + } + + return in_array($extensionName, self::$supportedExtensionsList); + } + + /** + * Get the extension specific helper class name + * + * @param string $extensionName The extension name with com_ + * + * @return bool + * + * @since __DEPLOY_VERSION__ + */ + private static function getExtensionHelperClassName($extensionName) + { + $realName = self::getExtensionRealName($extensionName); + + return ucfirst($realName) . 'AssociationsHelper'; + } + + /** + * Get the real extension name. This means without com_ + * + * @param string $extensionName The extension name with com_ + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + private static function getExtensionRealName($extensionName) + { + return strpos($extensionName, 'com_') === false ? $extensionName : substr($extensionName, 4); + } + + /** + * Get the associated language edit links Html. + * + * @param string $extensionName Extension Name + * @param string $typeName ItemType + * @param integer $itemId Item id. + * @param string $itemLanguage Item language code. + * @param boolean $addLink True for adding edit links. False for just text. + * @param boolean $allLanguages True for showing all content languages. False only languages with associations. + * + * @return string The language HTML + * + * @since __DEPLOY_VERSION__ + */ + public static function getAssociationHtmlList($extensionName, $typeName, $itemId, $itemLanguage, $addLink = true, $allLanguages = true) + { + // Get the associations list for this item. + $items = self::getAssociationList($extensionName, $typeName, $itemId); + + $titleFieldName = self::getTypeFieldName($extensionName, $typeName, 'title'); + + // Get all content languages. + $languages = self::getContentLanguages(); + + $canEditReference = self::allowEdit($extensionName, $typeName, $itemId); + $canCreate = self::allowAdd($extensionName, $typeName); + + // Create associated items list. + foreach ($languages as $langCode => $language) + { + // Don't do for the reference language. + if ($langCode == $itemLanguage) + { + continue; + } + + // Don't show languages without associations, if we don't want to show them. + if (!$allLanguages && !isset($items[$langCode])) + { + continue; + } + + // Get html parameters. + if (isset($items[$langCode])) + { + $title = '

' . $items[$langCode][$titleFieldName]; + $additional = ''; + + if (isset($items[$langCode]['category_title'])) + { + $additional = '
' . JText::_('JCATEGORY') . ': ' . $items[$langCode]['category_title']; + } + elseif (isset($items[$langCode]['menu_title'])) + { + $additional = '
' . JText::_('COM_ASSOCIATIONS_HEADING_MENUTYPE') . ': ' . $items[$langCode]['menu_title']; + } + + $additional .= $addLink ? '

' . JText::_('COM_ASSOCIATIONS_EDIT_ASSOCIATION') : ''; + $labelClass = 'label'; + $target = $langCode . ':' . $items[$langCode]['id'] . ':edit'; + $allow = $canEditReference && self::allowEdit($extensionName, $typeName, $items[$langCode]['id']); + } + else + { + $items[$langCode] = array(); + + $title = '

' . JText::_('COM_ASSOCIATIONS_NO_ASSOCIATION'); + $additional = $addLink ? '

' . JText::_('COM_ASSOCIATIONS_ADD_NEW_ASSOCIATION') : ''; + $labelClass = 'label label-warning'; + $target = $langCode . ':0:add'; + $allow = $canCreate; + } + + // Generate item Html. + $options = array( + 'option' => 'com_associations', + 'view' => 'association', + 'layout' => 'edit', + 'itemtype' => $extensionName . '.' . $typeName, + 'task' => 'association.edit', + 'id' => $itemId, + 'target' => $target, + ); + + $url = JRoute::_('index.php?' . http_build_query($options)); + $text = strtoupper($language->sef); + $langImage = JHtml::_('image', 'mod_languages/' . $language->image . '.gif', $language->title, array('title' => $language->title), true); + $tooltip = implode(' ', array($langImage, $language->title, $title, $additional)); + + $items[$langCode]['link'] = JHtml::_('tooltip', $tooltip, null, null, $text, $allow && $addLink ? $url : '', null, 'hasTooltip ' . $labelClass); + } + + return JLayoutHelper::render('joomla.content.associations', $items); + } + + /** + * Get all extensions with associations support. + * + * @return array The extensions. + * + * @since __DEPLOY_VERSION__ + */ + public static function getSupportedExtensions() + { + if (!is_null(self::$extensionsSupport)) + { + return self::$extensionsSupport; + } + + self::$extensionsSupport = array(); + + $extensions = self::getEnabledExtensions(); + + foreach ($extensions as $extension) + { + $support = self::getSupportedExtension($extension->element); + + if ($support->get('associationssupport') === true) + { + self::$supportedExtensionsList[] = $extension->element; + } + + self::$extensionsSupport[$extension->element] = $support; + } + + return self::$extensionsSupport; + } + + /** + * Get item context based on the item key. + * + * @param string $extensionName The extension identifier. + * + * @return Joomla\Registry\Registry The item properties. + * + * @since __DEPLOY_VERSION__ + */ + public static function getSupportedExtension($extensionName) + { + $result = new Registry; + + $result->def('component', $extensionName); + $result->def('associationssupport', false); + $result->def('helper', null); + + // Check if associations helper exists + if (!file_exists(JPATH_ADMINISTRATOR . '/components/' . $extensionName . '/helpers/associations.php')) + { + return $result; + } + + require_once JPATH_ADMINISTRATOR . '/components/' . $extensionName . '/helpers/associations.php'; + + $componentAssociationsHelperClassName = self::getExtensionHelperClassName($extensionName); + + if (!class_exists($componentAssociationsHelperClassName, false)) + { + return $result; + } + + // Create an instance of the helper class + $helper = new $componentAssociationsHelperClassName; + $result->set('helper', $helper); + + if ($helper->hasAssociationsSupport() === false) + { + return $result; + } + + $result->set('associationssupport', true); + + // Get the translated titles. + $languagePath = JPATH_ADMINISTRATOR . '/components/' . $extensionName; + $lang = JFactory::getLanguage(); + + $lang->load($extensionName . '.sys', JPATH_ADMINISTRATOR); + $lang->load($extensionName . '.sys', $languagePath); + $lang->load($extensionName, JPATH_ADMINISTRATOR); + $lang->load($extensionName, $languagePath); + + $result->def('title', JText::_(strtoupper($extensionName))); + + // Get the supported types + $types = $helper->getItemTypes(); + $rTypes = array(); + + foreach ($types as $typeName) + { + $details = $helper->getType($typeName); + $context = 'component'; + $title = $helper->getTypeTitle($typeName); + $languageKey = $typeName; + + if ($typeName === 'category') + { + $languageKey = strtoupper($extensionName) . '_CATEGORIES'; + $context = 'category'; + } + + if ($lang->hasKey(strtoupper($extensionName . '_' . $title . 'S'))) + { + $languageKey = strtoupper($extensionName . '_' . $title . 'S'); + } + + $title = $lang->hasKey($languageKey) ? JText::_($languageKey) : JText::_('COM_ASSOCIATIONS_ITEMS'); + + $rType = new Registry; + + $rType->def('name', $typeName); + $rType->def('details', $details); + $rType->def('title', $title); + $rType->def('context', $context); + + $rTypes[$typeName] = $rType; + } + + $result->def('types', $rTypes); + + return $result; + } + + /** + * Get all installed and enabled extensions + * + * @return mixed + * + * @since __DEPLOY_VERSION__ + */ + private static function getEnabledExtensions() + { + $db = JFactory::getDbo(); + + $query = $db->getQuery(true) + ->select('*') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('type') . ' = ' . $db->quote('component')) + ->where($db->quoteName('enabled') . ' = 1'); + + $db->setQuery($query); + + return $db->loadObjectList(); + } + + /** + * Get all the content languages. + * + * @return array Array of objects all content languages by language code. + * + * @since __DEPLOY_VERSION__ + */ + public static function getContentLanguages() + { + $db = JFactory::getDbo(); + + // Get all content languages. + $query = $db->getQuery(true) + ->select($db->quoteName(array('sef', 'lang_code', 'image', 'title', 'published'))) + ->from($db->quoteName('#__languages')) + ->order($db->quoteName('ordering') . ' ASC'); + + $db->setQuery($query); + + return $db->loadObjectList('lang_code'); + } + + /** + * Get the associated items for an item + * + * @param string $extensionName The extension name with com_ + * @param string $typeName The item type + * @param int $itemId The id of item for which we need the associated items + * + * @return bool + * + * @since __DEPLOY_VERSION__ + */ + public static function allowEdit($extensionName, $typeName, $itemId) + { + if (!self::hasSupport($extensionName)) + { + return false; + } + + // Get the extension specific helper method + $helper= self::getExtensionHelper($extensionName); + + if (method_exists($helper, 'allowEdit')) + { + return $helper->allowEdit($typeName, $itemId); + } + + return JFactory::getUser()->authorise('core.edit', $extensionName); + } + + /** + * Check if user is allowed to create items. + * + * @param string $extensionName The extension name with com_ + * @param string $typeName The item type + * + * @return boolean True on allowed. + * + * @since __DEPLOY_VERSION__ + */ + public static function allowAdd($extensionName, $typeName) + { + if (!self::hasSupport($extensionName)) + { + return false; + } + + // Get the extension specific helper method + $helper= self::getExtensionHelper($extensionName); + + if (method_exists($helper, 'allowAdd')) + { + return $helper->allowAdd($typeName); + } + + return JFactory::getUser()->authorise('core.create', $extensionName); + } + + /** + * Check if the type supports checkout + * + * @param string $extensionName The extension name with com_ + * @param string $typeName The item type + * + * @return boolean True on allowed. + * + * @since __DEPLOY_VERSION__ + */ + public static function typeSupportsCheckout($extensionName, $typeName) + { + if (!self::hasSupport($extensionName)) + { + return false; + } + + // Get the extension specific helper method + $helper = self::getExtensionHelper($extensionName); + + $support = $helper->getTypeSupport($typeName); + + return !empty($support['checkout']); + } + + /** + * Get a table field name for a type + * + * @param string $extensionName The extension name with com_ + * @param string $typeName The item type + * @param string $fieldName The item type + * + * @return boolean True on allowed. + * + * @since __DEPLOY_VERSION__ + */ + public static function getTypeFieldName($extensionName, $typeName, $fieldName) + { + if (!self::hasSupport($extensionName)) + { + return false; + } + + // Get the extension specific helper method + $helper = self::getExtensionHelper($extensionName); + + return $helper->getTypeFieldName($typeName, $fieldName); + } +} diff --git a/administrator/components/com_associations/layouts/joomla/searchtools/default/bar.php b/administrator/components/com_associations/layouts/joomla/searchtools/default/bar.php new file mode 100644 index 0000000000000..2c2bf13c8adb5 --- /dev/null +++ b/administrator/components/com_associations/layouts/joomla/searchtools/default/bar.php @@ -0,0 +1,32 @@ + + + + + input->get('forcedItemType', '', 'string') == '') : ?> + filterForm->getField('itemtype'); ?> +
+ input; ?> +
+ + input->get('forcedLanguage', '', 'cmd') == '') : ?> + filterForm->getField('language'); ?> +
+ input; ?> +
+ + + + 'none')); ?> diff --git a/administrator/components/com_associations/models/association.php b/administrator/components/com_associations/models/association.php new file mode 100644 index 0000000000000..d90a792501c85 --- /dev/null +++ b/administrator/components/com_associations/models/association.php @@ -0,0 +1,36 @@ +loadForm('com_associations.association', 'association', array('control' => 'jform', 'load_data' => $loadData)); + + return !empty($form) ? $form : false; + } +} diff --git a/administrator/components/com_associations/models/associations.php b/administrator/components/com_associations/models/associations.php new file mode 100644 index 0000000000000..0c3b1d8f12c01 --- /dev/null +++ b/administrator/components/com_associations/models/associations.php @@ -0,0 +1,529 @@ +input->get('forcedLanguage', '', 'cmd'); + $forcedItemType = $app->input->get('forcedItemType', '', 'string'); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Adjust the context to support forced languages. + if ($forcedLanguage) + { + $this->context .= '.' . $forcedLanguage; + } + + // Adjust the context to support forced component item types. + if ($forcedItemType) + { + $this->context .= '.' . $forcedItemType; + } + + $this->setState('itemtype', $this->getUserStateFromRequest($this->context . '.itemtype', 'itemtype', '', 'string')); + $this->setState('language', $this->getUserStateFromRequest($this->context . '.language', 'language', '', 'string')); + + $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); + $this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd')); + $this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'cmd')); + $this->setState('filter.menutype', $this->getUserStateFromRequest($this->context . '.filter.menutype', 'filter_menutype', '', 'string')); + $this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'string')); + $this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd')); + + // List state information. + parent::populateState($ordering, $direction); + + // Force a language. + if (!empty($forcedLanguage)) + { + $this->setState('language', $forcedLanguage); + } + + // Force a component item type. + if (!empty($forcedItemType)) + { + $this->setState('itemtype', $forcedItemType); + } + } + + /** + * Method to get a store id based on model configuration state. + * + * This is necessary because the model is used by the component and + * different modules that might need different sets of data or different + * ordering requirements. + * + * @param string $id A prefix for the store id. + * + * @return string A store id. + * + * @since __DEPLOY_VERSION__ + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('itemtype'); + $id .= ':' . $this->getState('language'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.state'); + $id .= ':' . $this->getState('filter.category_id'); + $id .= ':' . $this->getState('filter.menutype'); + $id .= ':' . $this->getState('filter.access'); + $id .= ':' . $this->getState('filter.level'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to load the list data. + * + * @return JDatabaseQuery|bool + * + * @since __DEPLOY_VERSION__ + */ + protected function getListQuery() + { + $type = null; + + list($extensionName, $typeName) = explode('.', $this->state->get('itemtype')); + + $extension = AssociationsHelper::getSupportedExtension($extensionName); + $types = $extension->get('types'); + + if (array_key_exists($typeName, $types)) + { + $type = $types[$typeName]; + } + + if (is_null($type)) + { + return false; + } + + // Create a new query object. + $user = JFactory::getUser(); + $db = $this->getDbo(); + $query = $db->getQuery(true); + + $details = $type->get('details'); + + if (!array_key_exists('support', $details)) + { + return false; + } + + $support = $details['support']; + + if (!array_key_exists('fields', $details)) + { + return false; + } + + $fields = $details['fields']; + + // Main query. + $query->select($db->qn($fields['id'], 'id')) + ->select($db->qn($fields['title'], 'title')) + ->select($db->qn($fields['alias'], 'alias')); + + if (!array_key_exists('tables', $details)) + { + return false; + } + + $tables = $details['tables']; + + foreach ($tables as $key => $table) + { + $query->from($db->qn($table, $key)); + } + + if (!array_key_exists('joins', $details)) + { + return false; + } + + $joins = $details['joins']; + + foreach ($joins as $join) + { + $query->join($join['type'], $db->qn($join['condition'])); + } + + // Join over the language. + $query->select($db->qn($fields['language'], 'language')) + ->select($db->qn('l.title', 'language_title')) + ->select($db->qn('l.image', 'language_image')) + ->join('LEFT', $db->qn('#__languages', 'l') . ' ON ' . $db->qn('l.lang_code') . ' = ' . $db->qn($fields['language'])); + + // Join over the associations. + $query->select('COUNT(' . $db->qn('asso2.id') . ') > 1 AS ' . $db->qn('association')) + ->join( + 'LEFT', + $db->qn('#__associations', 'asso') . ' ON ' . $db->qn('asso.id') . ' = ' . $db->qn($fields['id']) + . ' AND ' . $db->qn('asso.context') . ' = ' . $db->quote($extensionName . '.' . 'item') + ) + ->join('LEFT', $db->qn('#__associations', 'asso2') . ' ON ' . $db->qn('asso2.key') . ' = ' . $db->qn('asso.key')); + + // Prepare the group by clause. + $groupby = array( + $fields['id'], + $fields['title'], + $fields['language'], + 'l.title', + 'l.image', + ); + + // Select author for ACL checks. + if (!empty($fields['created_user_id'])) + { + $query->select($db->qn($fields['created_user_id'], 'created_user_id')); + } + + // Select checked out data for check in checkins. + if (!empty($fields['checked_out']) && !empty($fields['checked_out_time'])) + { + $query->select($db->qn($fields['checked_out'], 'checked_out')) + ->select($db->qn($fields['checked_out_time'], 'checked_out_time')); + + // Join over the users. + $query->select($db->qn('u.name', 'editor')) + ->join('LEFT', $db->qn('#__users', 'u') . ' ON ' . $db->qn('u.id') . ' = ' . $db->qn($fields['checked_out'])); + + $groupby[] = 'u.name'; + } + + // If component item type supports ordering, select the ordering also. + if (!empty($fields['ordering'])) + { + $query->select($db->qn($fields['ordering'], 'ordering')); + } + + // If component item type supports state, select the item state also. + if (!empty($fields['state'])) + { + $query->select($db->qn($fields['state'], 'state')); + } + + // If component item type supports level, select the level also. + if (!empty($fields['level'])) + { + $query->select($db->qn($fields['level'], 'level')); + } + + // If component item type supports categories, select the category also. + if (!empty($fields['catid'])) + { + $query->select($db->qn($fields['catid'], 'catid')); + + // Join over the categories. + $query->select($db->qn('c.title', 'category_title')) + ->join('LEFT', $db->qn('#__categories', 'c') . ' ON ' . $db->qn('c.id') . ' = ' . $db->qn($fields['catid'])); + + $groupby[] = 'c.title'; + } + + // If component item type supports menu type, select the menu type also. + if (!empty($fields['menutype'])) + { + $query->select($db->qn($fields['menutype'], 'menutype')); + + // Join over the menu types. + $query->select($db->qn('mt.title', 'menutype_title')) + ->select($db->qn('mt.id', 'menutypeid')) + ->join('LEFT', $db->qn('#__menu_types', 'mt') . ' ON ' . $db->qn('mt.menutype') . ' = ' . $db->qn($fields['menutype'])); + + $groupby[] = 'mt.title'; + $groupby[] = 'mt.id'; + } + + // If component item type supports access level, select the access level also. + if (array_key_exists('acl', $support) && $support['acl'] == true && !empty($fields['access'])) + { + $query->select($db->qn($fields['access'], 'access')); + + // Join over the access levels. + $query->select($db->qn('ag.title', 'access_level')) + ->join('LEFT', $db->qn('#__viewlevels', 'ag') . ' ON ' . $db->qn('ag.id') . ' = ' . $db->qn($fields['access'])); + + $groupby[] = 'ag.title'; + + // Implement View Level Access. + if (!$user->authorise('core.admin', $extensionName)) + { + $query->where($fields['access'] . ' IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')'); + } + } + + // If component item type is menus we need to remove the root item and the administrator menu. + if ($extensionName === 'com_menus') + { + $query->where($db->qn($fields['id']) . ' > 1') + ->where($db->qn('a.client_id') . ' = 0'); + } + + // If component item type is category we need to remove all other component categories. + if ($typeName === 'category') + { + $query->where($db->qn('a.extension') . ' = ' . $db->quote($extensionName)); + } + + // Filter on the language. + if ($language = $this->getState('language')) + { + $query->where($db->qn($fields['language']) . ' = ' . $db->quote($language)); + } + + // Filter by item state. + $state = $this->getState('filter.state'); + + if (is_numeric($state)) + { + $query->where($db->qn($fields['state']) . ' = ' . (int) $state); + } + elseif ($state === '') + { + $query->where($db->qn($fields['state']) . ' IN (0, 1)'); + } + + // Filter on the category. + $baselevel = 1; + + if ($categoryId = $this->getState('filter.category_id')) + { + $categoryTable = JTable::getInstance('Category', 'JTable'); + $categoryTable->load($categoryId); + $baselevel = (int) $categoryTable->level; + + $query->where($db->qn('c.lft') . ' >= ' . (int) $categoryTable->lft) + ->where($db->qn('c.rgt') . ' <= ' . (int) $categoryTable->rgt); + } + + // Filter on the level. + if ($level = $this->getState('filter.level')) + { + $tableAlias = in_array($extensionName, array('com_menus', 'com_categories')) ? 'a' : 'c'; + $query->where($db->qn($tableAlias . '.level') . ' <= ' . ((int) $level + (int) $baselevel - 1)); + } + + // Filter by menu type. + if ($menutype = $this->getState('filter.menutype')) + { + $query->where($fields['menutype'] . ' = ' . $db->quote($menutype)); + } + + // Filter by access level. + if ($access = $this->getState('filter.access')) + { + $query->where($fields['access'] . ' = ' . (int) $access); + } + + // Filter by search in name. + if ($search = $this->getState('filter.search')) + { + if (stripos($search, 'id:') === 0) + { + $query->where($db->qn($fields['id']) . ' = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); + $query->where('(' . $db->qn($fields['title']) . ' LIKE ' . $search + . ' OR ' . $db->qn($fields['alias']) . ' LIKE ' . $search . ')'); + } + } + + // Add the group by clause + $query->group($db->qn($groupby)); + + // Add the list ordering clause. + $query->order($db->escape($this->getState('list.ordering') . ' ' . $this->getState('list.direction'))); + + return $query; + } + + /** + * Delete associations from #__associations table. + * + * @param string $context The associations context. Empty for all. + * @param string $key The associations key. Empty for all. + * + * @return boolean True on success. + * + * @since __DEPLOY_VERSION__ + */ + public function purge($context = '', $key = '') + { + $app = JFactory::getApplication(); + $db = $this->getDbo(); + $query = $db->getQuery(true)->delete($db->qn('#__associations')); + + // Filter by associations context. + if ($context) + { + $query->where($db->qn('context') . ' = ' . $db->quote($context)); + } + + // Filter by key. + if ($key) + { + $query->where($db->qn('key') . ' = ' . $db->quote($key)); + } + + $db->setQuery($query); + + try + { + $db->execute(); + } + catch (JDatabaseExceptionExecuting $e) + { + $app->enqueueMessage(JText::_('COM_ASSOCIATIONS_PURGE_FAILED'), 'error'); + + return false; + } + + $app->enqueueMessage( + JText::_((int) $db->getAffectedRows() > 0 ? 'COM_ASSOCIATIONS_PURGE_SUCCESS' : 'COM_ASSOCIATIONS_PURGE_NONE'), + 'message' + ); + + return true; + } + + /** + * Delete orphans from the #__associations table. + * + * @param string $context The associations context. Empty for all. + * @param string $key The associations key. Empty for all. + * + * @return boolean True on success + * + * @since __DEPLOY_VERSION__ + */ + public function clean($context = '', $key = '') + { + $app = JFactory::getApplication(); + $db = $this->getDbo(); + $query = $db->getQuery(true) + ->select($db->qn('key') . ', COUNT(*)') + ->from($db->qn('#__associations')) + ->group($db->qn('key')) + ->having('COUNT(*) = 1'); + + // Filter by associations context. + if ($context) + { + $query->where($db->qn('context') . ' = ' . $db->quote($context)); + } + + // Filter by key. + if ($key) + { + $query->where($db->qn('key') . ' = ' . $db->quote($key)); + } + + $db->setQuery($query); + + $assocKeys = $db->loadObjectList(); + + $count = 0; + + // We have orphans. Let's delete them. + foreach ($assocKeys as $value) + { + $query->clear() + ->delete($db->qn('#__associations')) + ->where($db->qn('key') . ' = ' . $db->quote($value->key)); + + $db->setQuery($query); + + try + { + $db->execute(); + } + catch (JDatabaseExceptionExecuting $e) + { + $app->enqueueMessage(JText::_('COM_ASSOCIATIONS_DELETE_ORPHANS_FAILED'), 'error'); + + return false; + } + + $count += (int) $db->getAffectedRows(); + } + + $app->enqueueMessage( + JText::_($count > 0 ? 'COM_ASSOCIATIONS_DELETE_ORPHANS_SUCCESS' : 'COM_ASSOCIATIONS_DELETE_ORPHANS_NONE'), + 'message' + ); + + return true; + } +} diff --git a/administrator/components/com_associations/models/fields/itemlanguage.php b/administrator/components/com_associations/models/fields/itemlanguage.php new file mode 100644 index 0000000000000..d1b5e21996879 --- /dev/null +++ b/administrator/components/com_associations/models/fields/itemlanguage.php @@ -0,0 +1,115 @@ +input; + + list($extensionName, $typeName) = explode('.', $input->get('itemtype')); + + $extension = AssociationsHelper::getSupportedExtension($extensionName); + $types = $extension->get('types'); + + if (array_key_exists($typeName, $types)) + { + $type = $types[$typeName]; + } + + $details = $type->get('details'); + + if (array_key_exists('fields', $details)) + { + $fields = $details['fields']; + } + + $languageField = substr($fields['language'], 2); + $referenceId = $input->get('id', 0, 'int'); + $reference = ArrayHelper::fromObject(AssociationsHelper::getItem($extensionName, $typeName, $referenceId)); + $referenceLang = $reference[$languageField]; + + // Get item associations given ID and item type + $associations = AssociationsHelper::getAssociationList($extensionName, $typeName, $referenceId); + + // Check if user can create items in this component item type. + $canCreate = AssociationsHelper::allowAdd($extensionName, $typeName); + + // Gets existing languages. + $existingLanguages = AssociationsHelper::getContentLanguages(); + + $options = array(); + + // Each option has the format "|", example: "en-GB|1" + foreach ($existingLanguages as $langCode => $language) + { + // If language code is equal to reference language we don't need it. + if ($language->lang_code == $referenceLang) + { + continue; + } + + $options[$langCode] = new stdClass; + $options[$langCode]->text = $language->title; + + // If association exists in this language. + if (isset($associations[$language->lang_code])) + { + $itemId = (int) $associations[$language->lang_code]['id']; + $options[$langCode]->value = $language->lang_code . ':' . $itemId . ':edit'; + + // Check if user does have permission to edit the associated item. + $canEdit = AssociationsHelper::allowEdit($extensionName, $typeName, $itemId); + + // ToDo: Do an additional check to check if user can edit a checked out item (if component item type supports it). + $canCheckout = true; + + // Disable language if user is not allowed to edit the item associated to it. + $options[$langCode]->disable = !($canEdit && $canCheckout); + } + else + { + // New item, id = 0 and disabled if user is not allowed to create new items. + $options[$langCode]->value = $language->lang_code . ':0:add'; + + // Disable language if user is not allowed to create items. + $options[$langCode]->disable = !$canCreate; + } + } + + return array_merge(parent::getOptions(), $options); + } +} diff --git a/administrator/components/com_associations/models/fields/itemtype.php b/administrator/components/com_associations/models/fields/itemtype.php new file mode 100644 index 0000000000000..d077f711d7530 --- /dev/null +++ b/administrator/components/com_associations/models/fields/itemtype.php @@ -0,0 +1,62 @@ +get('associationssupport') === true) + { + foreach ($extension->get('types') as $type) + { + $context = $extension->get('component') . '.' . $type->get('name'); + $options[$extension->get('title')][] = JHtml::_('select.option', $context, $type->get('title')); + } + } + } + + // Sort by alpha order. + ksort($options, SORT_NATURAL); + + // Add options to parent array. + return array_merge(parent::getGroups(), $options); + } +} diff --git a/administrator/components/com_associations/models/fields/modalassociation.php b/administrator/components/com_associations/models/fields/modalassociation.php new file mode 100644 index 0000000000000..ee3f593095c9b --- /dev/null +++ b/administrator/components/com_associations/models/fields/modalassociation.php @@ -0,0 +1,105 @@ +value > 0 ? (int) $this->value : ''; + + // Build the script. + $script = array(); + + // Select button script + $script[] = 'function jSelectAssociation_' . $this->id . '(id) {'; + $script[] = ' target = document.getElementById("target-association");'; + $script[] = ' document.getElementById("target-association").src = target.getAttribute("data-editurl") + ' + . '"&task=" + target.getAttribute("data-item") + ".edit" + "&id=" + id'; + $script[] = ' jQuery("#associationSelect' . $this->id . 'Modal").modal("hide");'; + $script[] = '}'; + + // Add the script to the document head. + JFactory::getDocument()->addScriptDeclaration(implode("\n", $script)); + + // Setup variables for display. + $html = array(); + + $linkAssociations = 'index.php?option=com_associations&view=associations&layout=modal&tmpl=component' + . '&forcedItemType=' . JFactory::getApplication()->input->get('itemtype', '', 'string') . '&function=jSelectAssociation_' . $this->id; + + $linkAssociations .= "&forcedLanguage=' + document.getElementById('target-association').getAttribute('data-language') + '"; + + $urlSelect = $linkAssociations . '&' . JSession::getFormToken() . '=1'; + + // Select custom association button + $html[] = '' + . '' + . '' + . ''; + + // Clear association button + $html[] = '' + . '' . JText::_('JCLEAR') + . ''; + + $html[] = ''; + + // Select custom association modal + $html[] = JHtml::_( + 'bootstrap.renderModal', + 'associationSelect' . $this->id . 'Modal', + array( + 'title' => JText::_('COM_ASSOCIATIONS_SELECT_TARGET'), + 'backdrop' => 'static', + 'url' => $urlSelect, + 'height' => '400px', + 'width' => '800px', + 'bodyHeight' => '70', + 'modalWidth' => '80', + 'footer' => '', + ) + ); + + return implode("\n", $html); + } +} diff --git a/administrator/components/com_associations/models/forms/association.xml b/administrator/components/com_associations/models/forms/association.xml new file mode 100644 index 0000000000000..89add5542b210 --- /dev/null +++ b/administrator/components/com_associations/models/forms/association.xml @@ -0,0 +1,21 @@ + +
+
+ + + + + +
+ + + +
diff --git a/administrator/components/com_associations/models/forms/filter_associations.xml b/administrator/components/com_associations/models/forms/filter_associations.xml new file mode 100644 index 0000000000000..fb2199975e28a --- /dev/null +++ b/administrator/components/com_associations/models/forms/filter_associations.xml @@ -0,0 +1,116 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/administrator/components/com_associations/views/association/tmpl/edit.php b/administrator/components/com_associations/views/association/tmpl/edit.php new file mode 100644 index 0000000000000..49bee064e18f3 --- /dev/null +++ b/administrator/components/com_associations/views/association/tmpl/edit.php @@ -0,0 +1,70 @@ + $this->app->input->get('layout', '', 'string'), + 'itemtype' => $this->itemtype, + 'id' => $this->referenceId, + ); +?> + + +
+
+
+
+

+ +
+
+
+
+
+

+ form->getInput('modalassociation'); ?> + form->getInput('itemlanguage'); ?> +
+ +
+
+ +
+ + + + +
diff --git a/administrator/components/com_associations/views/association/view.html.php b/administrator/components/com_associations/views/association/view.html.php new file mode 100644 index 0000000000000..033dbeacda809 --- /dev/null +++ b/administrator/components/com_associations/views/association/view.html.php @@ -0,0 +1,197 @@ +get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + + return false; + } + + $this->app = JFactory::getApplication(); + $this->form = $this->get('Form'); + $input = $this->app->input; + + $this->referenceId = $input->get('id', 0, 'int'); + + list($extensionName, $typeName) = explode('.', $input->get('itemtype')); + + $this->extensionName = $extensionName; + $this->typeName = $typeName; + $this->itemtype = $extensionName . '.' . $typeName; + + $languageField = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'language'); + $referenceId = $input->get('id', 0, 'int'); + $reference = ArrayHelper::fromObject(AssociationsHelper::getItem($extensionName, $typeName, $referenceId)); + + $this->referenceLanguage = $reference[$languageField]; + + $options = array( + 'option' => $typeName === 'category' ? 'com_categories' : $extensionName, + 'view' => $typeName, + 'extension' => $extensionName, + 'tmpl' => 'component', + ); + + // Reference and target edit links. + $this->editUri = 'index.php?' . http_build_query($options); + + // Get target language. + $this->targetId = '0'; + $this->targetLanguage = ''; + $this->defaultTargetSrc = ''; + $this->targetAction = ''; + + if ($target = $input->get('target', '', 'string')) + { + $matches = preg_split("#[\:]+#", $target); + $this->targetAction = $matches[2]; + $this->targetId = $matches[1]; + $this->targetLanguage = $matches[0]; + $task = $typeName . '.' . $this->targetAction; + $this->defaultTargetSrc = JRoute::_($this->editUri . '&task= ' . $task . ' &id=' . (int) $this->targetId); + $this->form->setValue('itemlanguage', '', $this->targetLanguage . ':' . $this->targetId . ':' . $this->targetAction); + } + + /* + * @todo Review later + */ + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + } + else + { + // In article associations modal we need to remove language filter if forcing a language. + // We also need to change the category filter to show show categories with All or the forced language. + if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD')) + { + // If the language is forced we can't allow to select the language, so transform the language selector filter into an hidden field. + $languageXml = new SimpleXMLElement(''); + $this->filterForm->setField($languageXml, 'filter', true); + + // Also, unset the active language filter so the search tools is not open by default with this filter. + unset($this->activeFilters['language']); + + // One last changes needed is to change the category filter to just show categories with All language or with the forced language. + $this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter'); + } + } + + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function addToolbar() + { + // Hide main menu. + JFactory::getApplication()->input->set('hidemainmenu', 1); + + $helper = AssociationsHelper::getExtensionHelper($this->extensionName); + $title = $helper->getTypeTitle($this->typeName); + + $languageKey = strtoupper($this->extensionName . '_' . $title . 'S'); + + if ($this->typeName === 'category') + { + $languageKey = strtoupper($this->extensionName) . '_CATEGORIES'; + } + + JToolbarHelper::title(JText::sprintf('COM_ASSOCIATIONS_TITLE_EDIT', JText::_($this->extensionName), JText::_($languageKey)), 'contract'); + + $bar = JToolbar::getInstance('toolbar'); + + $bar->appendButton( + 'Custom', '', 'reference' + ); + + $bar->appendButton( + 'Custom', '', 'target' + ); + + JToolBarHelper::custom('copy', 'copy.png', '', 'COM_ASSOCIATIONS_COPY_REFERENCE', false); + + JToolbarHelper::cancel('association.cancel', 'JTOOLBAR_CLOSE'); + JToolbarHelper::help('JGLOBAL_HELP'); + + JHtmlSidebar::setAction('index.php?option=com_associations'); + } +} diff --git a/administrator/components/com_associations/views/associations/tmpl/default.php b/administrator/components/com_associations/views/associations/tmpl/default.php new file mode 100644 index 0000000000000..1690367692d49 --- /dev/null +++ b/administrator/components/com_associations/views/associations/tmpl/default.php @@ -0,0 +1,171 @@ +escape($this->state->get('list.ordering')); +$listDirn = $this->escape($this->state->get('list.direction')); +$canManageCheckin = JFactory::getUser()->authorise('core.manage', 'com_checkin'); +$colSpan = 5; + +$iconStates = array( + -2 => 'icon-trash', + 0 => 'icon-unpublish', + 1 => 'icon-publish', + 2 => 'icon-archive', +); + +JText::script('COM_ASSOCIATIONS_PURGE_CONFIRM_PROMPT'); + +JFactory::getDocument()->addScriptDeclaration(' + Joomla.submitbutton = function(pressbutton) + { + if (pressbutton == "associations.purge") + { + if (confirm(Joomla.JText._("COM_ASSOCIATIONS_PURGE_CONFIRM_PROMPT"))) + { + Joomla.submitform(pressbutton); + } + else + { + return false; + } + } + else + { + Joomla.submitform(pressbutton); + } + }; +'); +?> +
+sidebar)) : ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); ?> + items)) : ?> +
+ +
+ + + + + typeSupports['state'])) : ?> + + + + + + typeFields['menutype'])) : ?> + + + typeFields['access'])) : ?> + + + + + + + + + + + + items as $i => $item) : + $canCheckin = true; + $canEdit = AssociationsHelper::allowEdit($this->extensionName, $this->typeName, $item->id); + $canCheckin = $canManageCheckin || AssociationsHelper::typeSupportsCheckout($this->extensionName, $this->typeName); + ?> + + typeSupports['state'])) : ?> + + + + + + typeFields['menutype'])) : ?> + + + typeFields['access'])) : ?> + + + + + + +
+ + + + + + + + + + + + + +
+ pagination->getListFooter(); ?> +
+ + + level)) : ?> + $item->level)); ?> + + checked_out) && $item->checked_out) : ?> + editor, $item->checked_out_time, 'associations.', $canCheckin); ?> + + + + escape($item->title); ?> + + escape($item->title); ?> + + typeFields['alias'])) : ?> + + escape($item->alias)); ?> + + + typeFields['catid'])) : ?> +
+ escape($item->category_title); ?> +
+ +
+ language_title ? JHtml::_('image', 'mod_languages/' . $item->language_image . '.gif', $item->language_title, array('title' => $item->language_title), true) . ' ' . $this->escape($item->language_title) : JText::_('JUNDEFINED'); ?> + + extensionName, $this->typeName, (int) $item->id, $item->language); ?> + + escape($item->menutype_title); ?> + + escape($item->access_level); ?> + + id; ?> +
+ + + +
+ diff --git a/administrator/components/com_associations/views/associations/tmpl/modal.php b/administrator/components/com_associations/views/associations/tmpl/modal.php new file mode 100644 index 0000000000000..d97db3616e8d2 --- /dev/null +++ b/administrator/components/com_associations/views/associations/tmpl/modal.php @@ -0,0 +1,161 @@ +isClient('site')) +{ + JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN')); +} + +JHtml::_('jquery.framework'); +JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom')); +JHtml::_('behavior.multiselect'); +JHtml::_('formbehavior.chosen', 'select'); + +$function = $app->input->getCmd('function', 'jSelectAssociation'); +$listOrder = $this->escape($this->state->get('list.ordering')); +$listDirn = $this->escape($this->state->get('list.direction')); +$colSpan = 4; +$iconStates = array( + -2 => 'icon-trash', + 0 => 'icon-unpublish', + 1 => 'icon-publish', + 2 => 'icon-archive', +); + +$app->getDocument()->addScriptDeclaration( + "jQuery(document).ready(function($) { + // Run function on parent window. + $('.select-link').on('click', function() { + if (self != top) + { + window.parent." . $function . "(this.getAttribute('data-id')); + } + }); + });" +); +?> +
+ +sidebar)) : ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); ?> + items)) : ?> +
+ +
+ + + + + typeSupports['state'])) : ?> + + + + + + typeFields['menutype'])) : ?> + + + typeSupports['acl'])) : ?> + + + + + + + + + + + + items as $i => $item) : + ?> + + typeSupports['state'])) : ?> + + + + + + typeFields['menutype'])) : ?> + + + typeSupports['acl'])) : ?> + + + + + + +
+ + + + + + + + + + + + + +
+ pagination->getListFooter(); ?> +
+ + + level)) : ?> + $item->level)); ?> + + escape($item->title); ?> + typeFields['alias'])) : ?> + + escape($item->alias)); ?> + + + typeFields['catid'])) : ?> +
+ escape($item->category_title); ?> +
+ +
+ language_title ? JHtml::_('image', 'mod_languages/' . $item->language_image . '.gif', $item->language_title, array('title' => $item->language_title), true) . ' ' . $this->escape($item->language_title) : JText::_('JUNDEFINED'); ?> + + association) : ?> + extensionName, $this->typeName, (int) $item->id, $item->language, false); ?> + + + escape($item->menutype_title); ?> + + escape($item->access_level); ?> + + id; ?> +
+ + + + + + + +
+ diff --git a/administrator/components/com_associations/views/associations/view.html.php b/administrator/components/com_associations/views/associations/view.html.php new file mode 100644 index 0000000000000..08c81633701a9 --- /dev/null +++ b/administrator/components/com_associations/views/associations/view.html.php @@ -0,0 +1,232 @@ +state = $this->get('State'); + $this->filterForm = $this->get('FilterForm'); + $this->activeFilters = $this->get('ActiveFilters'); + + if (!JLanguageAssociations::isEnabled()) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_ASSOCIATIONS_ERROR_NO_ASSOC'), 'warning'); + } + elseif ($this->state->get('itemtype') == '' || $this->state->get('language') == '') + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_ASSOCIATIONS_NOTICE_NO_SELECTORS'), 'notice'); + } + else + { + $type = null; + + list($extensionName, $typeName) = explode('.', $this->state->get('itemtype')); + + $extension = AssociationsHelper::getSupportedExtension($extensionName); + + $types = $extension->get('types'); + + if (array_key_exists($typeName, $types)) + { + $type = $types[$typeName]; + } + + $this->itemType = $type; + + if (is_null($type)) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_ASSOCIATIONS_ERROR_NO_TYPE'), 'warning'); + } + else + { + $this->extensionName = $extensionName; + $this->typeName = $typeName; + $this->typeSupports = array(); + $this->typeFields = array(); + + $details = $type->get('details'); + + if (array_key_exists('support', $details)) + { + $support = $details['support']; + $this->typeSupports = $support; + } + + if (array_key_exists('fields', $details)) + { + $fields = $details['fields']; + $this->typeFields = $fields; + } + + // Dynamic filter form. + // This selectors doesn't have to activate the filter bar. + unset($this->activeFilters['itemtype']); + unset($this->activeFilters['language']); + + // Remove filters options depending on selected type. + if (empty($support['state'])) + { + unset($this->activeFilters['state']); + $this->filterForm->removeField('state', 'filter'); + } + if ($type !== 'category') + { + unset($this->activeFilters['category_id']); + $this->filterForm->removeField('category_id', 'filter'); + } + if ($extensionName !== 'com_menus') + { + unset($this->activeFilters['menutype']); + $this->filterForm->removeField('menutype', 'filter'); + } + if (!in_array($extensionName, array('com_categories', 'com_menus'))) + { + unset($this->activeFilters['level']); + $this->filterForm->removeField('level', 'filter'); + } + if (empty($support['acl'])) + { + unset($this->activeFilters['access']); + $this->filterForm->removeField('access', 'filter'); + } + + // Add extension attribute to category filter. + if (empty($support['catid'])) + { + $this->filterForm->setFieldAttribute('category_id', 'extension', $extensionName, 'filter'); + } + + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + + $linkParameters = array( + 'layout' => 'edit', + 'itemtype' => $extensionName . '.' . $typeName, + 'task' => 'association.edit', + ); + + $this->editUri = 'index.php?option=com_associations&view=association&' . http_build_query($linkParameters); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + $this->addToolbar(); + + // Will add sidebar if needed $this->sidebar = JHtmlSidebar::render(); + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function addToolbar() + { + $user = JFactory::getUser(); + + if (isset($this->typeName) && isset($this->extensionName)) + { + $helper = AssociationsHelper::getExtensionHelper($this->extensionName); + $title = $helper->getTypeTitle($this->typeName); + + $languageKey = strtoupper($this->extensionName . '_' . $title . 'S'); + + if ($this->typeName === 'category') + { + $languageKey = strtoupper($this->extensionName) . '_CATEGORIES'; + } + + JToolbarHelper::title( + JText::sprintf( + 'COM_ASSOCIATIONS_TITLE_LIST', JText::_($this->extensionName), JText::_($languageKey) + ), 'contract' + ); + } + else + { + JToolbarHelper::title(JText::_('COM_ASSOCIATIONS_TITLE_LIST_SELECT'), 'contract'); + } + + if ($user->authorise('core.admin', 'com_associations') || $user->authorise('core.options', 'com_associations')) + { + if (!isset($this->typeName)) + { + JToolbarHelper::custom('associations.purge', 'purge', 'purge', 'COM_ASSOCIATIONS_PURGE', false, false); + JToolbarHelper::custom('associations.clean', 'refresh', 'refresh', 'COM_ASSOCIATIONS_DELETE_ORPHANS', false, false); + } + JToolbarHelper::preferences('com_associations'); + } + + /* + * @todo Help page + */ + JToolbarHelper::help('JGLOBAL_HELP'); + } +} diff --git a/administrator/components/com_contact/helpers/associations.php b/administrator/components/com_contact/helpers/associations.php new file mode 100644 index 0000000000000..ec28ad98ca6d4 --- /dev/null +++ b/administrator/components/com_contact/helpers/associations.php @@ -0,0 +1,191 @@ +getType($typeName); + + $context = $this->extension . '.item'; + $catidField = 'catid'; + + if ($typeName === 'category') + { + $context = 'com_categories.item'; + $catidField = ''; + } + + // Get the associations. + $associations = JLanguageAssociations::getAssociations( + $this->extension, + $type['tables']['a'], + $context, + $id, + 'id', + 'alias', + $catidField + ); + + return $associations; + } + + /** + * Get item information + * + * @param string $typeName The item type + * @param int $id The id of item for which we need the associated items + * + * @return JTable|null + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($typeName, $id) + { + if (empty($id)) + { + return null; + } + + $table = null; + + switch ($typeName) + { + case 'contact': + $table = JTable::getInstance('Contact', 'ContactTable'); + break; + + case 'category': + $table = JTable::getInstance('Category'); + break; + } + + if (empty($table)) + { + return null; + } + + $table->load($id); + + return $table; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * + * @return array Array of item types + * + * @since __DEPLOY_VERSION__ + */ + public function getType($typeName = '') + { + $fields = $this->getFieldsTemplate(); + $tables = array(); + $joins = array(); + $support = $this->getSupportTemplate(); + $title = ''; + + if (in_array($typeName, $this->itemTypes)) + { + switch ($typeName) + { + case 'contact': + $fields['title'] = 'a.name'; + $fields['state'] = 'a.published'; + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__contact_details' + ); + + $title = 'contact'; + break; + + case 'category': + $fields['created_user_id'] = 'a.created_user_id'; + $fields['ordering'] = 'a.lft'; + $fields['level'] = 'a.level'; + $fields['catid'] = ''; + $fields['state'] = 'a.published'; + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__categories' + ); + + $title = 'category'; + break; + } + } + + return array( + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title + ); + } +} diff --git a/administrator/components/com_content/helpers/associations.php b/administrator/components/com_content/helpers/associations.php new file mode 100644 index 0000000000000..0d7c66f02074a --- /dev/null +++ b/administrator/components/com_content/helpers/associations.php @@ -0,0 +1,189 @@ +getType($typeName); + + $context = $this->extension . '.item'; + $catidField = 'catid'; + + if ($typeName === 'category') + { + $context = 'com_categories.item'; + $catidField = ''; + } + + // Get the associations. + $associations = JLanguageAssociations::getAssociations( + $this->extension, + $type['tables']['a'], + $context, + $id, + 'id', + 'alias', + $catidField + ); + + return $associations; + } + + /** + * Get item information + * + * @param string $typeName The item type + * @param int $id The id of item for which we need the associated items + * + * @return JTable|null + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($typeName, $id) + { + if (empty($id)) + { + return null; + } + + $table = null; + + switch ($typeName) + { + case 'article': + $table = JTable::getInstance('Content'); + break; + + case 'category': + $table = JTable::getInstance('Category'); + break; + } + + if (is_null($table)) + { + return null; + } + + $table->load($id); + + return $table; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * + * @return array Array of item types + * + * @since __DEPLOY_VERSION__ + */ + public function getType($typeName = '') + { + $fields = $this->getFieldsTemplate(); + $tables = array(); + $joins = array(); + $support = $this->getSupportTemplate(); + $title = ''; + + if (in_array($typeName, $this->itemTypes)) + { + + switch ($typeName) + { + case 'article': + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__content' + ); + + $title = 'article'; + break; + + case 'category': + $fields['created_user_id'] = 'a.created_user_id'; + $fields['ordering'] = 'a.lft'; + $fields['level'] = 'a.level'; + $fields['catid'] = ''; + $fields['state'] = 'a.published'; + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__categories' + ); + + $title = 'category'; + break; + } + } + + return array( + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title + ); + } +} diff --git a/administrator/components/com_menus/helpers/associations.php b/administrator/components/com_menus/helpers/associations.php new file mode 100644 index 0000000000000..c1244016713a2 --- /dev/null +++ b/administrator/components/com_menus/helpers/associations.php @@ -0,0 +1,166 @@ +getType($typeName); + + $context = $this->extension . '.item'; + + // Get the associations. + $associations = JLanguageAssociations::getAssociations( + $this->extension, + $type['tables']['a'], + $context, + $id, + 'id', + 'alias', + '' + ); + + return $associations; + } + + /** + * Get item information + * + * @param string $typeName The item type + * @param int $id The id of item for which we need the associated items + * + * @return JTable|null + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($typeName, $id) + { + if (empty($id)) + { + return null; + } + + $table = null; + + switch ($typeName) + { + case 'item': + $table = JTable::getInstance('menu'); + break; + } + + if (is_null($table)) + { + return null; + } + + $table->load($id); + + return $table; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * + * @return array Array of item types + * + * @since __DEPLOY_VERSION__ + */ + public function getType($typeName = '') + { + $fields = $this->getFieldsTemplate(); + $tables = array(); + $joins = array(); + $support = $this->getSupportTemplate(); + $title = ''; + + if (in_array($typeName, $this->itemTypes)) + { + + switch ($typeName) + { + case 'item': + $fields['ordering'] = 'a.lft'; + $fields['level'] = 'a.level'; + $fields['catid'] = ''; + $fields['state'] = 'a.published'; + $fields['created_user_id'] = ''; + $fields['menutype'] = 'a.menutype'; + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__menu' + ); + + $title = 'menu'; + break; + } + } + + return array( + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title + ); + } +} diff --git a/administrator/components/com_newsfeeds/helpers/associations.php b/administrator/components/com_newsfeeds/helpers/associations.php new file mode 100644 index 0000000000000..76d7a7740ffee --- /dev/null +++ b/administrator/components/com_newsfeeds/helpers/associations.php @@ -0,0 +1,192 @@ +getType($typeName); + + $context = $this->extension . '.item'; + $catidField = 'catid'; + + if ($typeName === 'category') + { + $context = 'com_categories.item'; + $catidField = ''; + } + + // Get the associations. + $associations = JLanguageAssociations::getAssociations( + $this->extension, + $type['tables']['a'], + $context, + $id, + 'id', + 'alias', + $catidField + ); + + return $associations; + } + + /** + * Get item information + * + * @param string $typeName The item type + * @param int $id The id of item for which we need the associated items + * + * @return JTable|null + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($typeName, $id) + { + if (empty($id)) + { + return null; + } + + $table = null; + + switch ($typeName) + { + case 'contact': + $table = JTable::getInstance('Newsfeed', 'NewsfeedsTable'); + break; + + case 'category': + $table = JTable::getInstance('Category'); + break; + } + + if (empty($table)) + { + return null; + } + + $table->load($id); + + return $table; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * + * @return array Array of item types + * + * @since __DEPLOY_VERSION__ + */ + public function getType($typeName = '') + { + $fields = $this->getFieldsTemplate(); + $tables = array(); + $joins = array(); + $support = $this->getSupportTemplate(); + $title = ''; + + if (in_array($typeName, $this->itemTypes)) + { + + switch ($typeName) + { + case 'newsfeed': + $fields['title'] = 'a.name'; + $fields['state'] = 'a.published'; + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__newsfeeds' + ); + $title = 'newsfeed'; + break; + + case 'category': + $fields['created_user_id'] = 'a.created_user_id'; + $fields['ordering'] = 'a.lft'; + $fields['level'] = 'a.level'; + $fields['catid'] = ''; + $fields['state'] = 'a.published'; + + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + + $tables = array( + 'a' => '#__categories' + ); + + $title = 'category'; + break; + } + } + + return array( + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title + ); + } +} diff --git a/administrator/language/en-GB/en-GB.com_associations.ini b/administrator/language/en-GB/en-GB.com_associations.ini new file mode 100644 index 0000000000000..56fa4ff02c1c8 --- /dev/null +++ b/administrator/language/en-GB/en-GB.com_associations.ini @@ -0,0 +1,50 @@ +; Joomla! Project +; Copyright (C) 2005 - 2016 Open Source Matters. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 + +COM_ASSOCIATIONS="Multilingual Associations" +COM_ASSOCIATIONS_ADD_NEW_ASSOCIATION="Add new association" +COM_ASSOCIATIONS_ASSOCIATED_ITEM="Target" +COM_ASSOCIATIONS_CHANGE_TARGET="Change Target" +COM_ASSOCIATIONS_COMPONENT_NOT_SUPPORTED="The extension %s does not support multilingual associations." +COM_ASSOCIATIONS_COMPONENT_SELECTOR_DESC="Select a component from this list" +COM_ASSOCIATIONS_COMPONENT_SELECTOR_LABEL="Select component" +COM_ASSOCIATIONS_CONFIGURATION="Multilingual Associations: Options" +COM_ASSOCIATIONS_COPY_REFERENCE="Copy Reference to Target" +COM_ASSOCIATIONS_DELETE_ORPHANS="Delete Orphans" +COM_ASSOCIATIONS_DELETE_ORPHANS_FAILED="Failed to delete orphans." +COM_ASSOCIATIONS_DELETE_ORPHANS_NONE="There were no orphans to delete." +COM_ASSOCIATIONS_DELETE_ORPHANS_SUCCESS="All orphans have been deleted." +COM_ASSOCIATIONS_EDIT_ASSOCIATION="Edit association" +COM_ASSOCIATIONS_EDIT_HIDE_REFERENCE="Hide Reference" +COM_ASSOCIATIONS_EDIT_SHOW_REFERENCE="Show Reference" +COM_ASSOCIATIONS_ERROR_NO_ASSOC="The Multilingual Associations component can't be used if the site is not set as multilingual and/or Items Associations is not enabled in the Language Filter plugin." +COM_ASSOCIATIONS_FILTER_MENUTYPE_DESC="Select a Menu" +COM_ASSOCIATIONS_FILTER_MENUTYPE_LABEL="Menu" +COM_ASSOCIATIONS_FILTER_SEARCH_DESC="Search an item by its title" +COM_ASSOCIATIONS_FILTER_SEARCH_LABEL="Search item" +COM_ASSOCIATIONS_FILTER_SELECT_ITEM_TYPE="- Select Item Type -" +COM_ASSOCIATIONS_HEADING_ASSOCIATION="Associations" +COM_ASSOCIATIONS_HEADING_MENUTYPE="Menu" +COM_ASSOCIATIONS_HEADING_MENUTYPE_ASC="Menu ascending" +COM_ASSOCIATIONS_HEADING_MENUTYPE_DESC="Menu descending" +COM_ASSOCIATIONS_ITEMS="Items" +COM_ASSOCIATIONS_NO_ASSOCIATION="There is no association for this language" +COM_ASSOCIATIONS_NOTICE_NO_SELECTORS="Please select an Item Type and a reference language to view the associations." +COM_ASSOCIATIONS_PURGE="Delete All Associations" +COM_ASSOCIATIONS_PURGE_CONFIRM_PROMPT="Are you sure you want to delete all associations? Confirming will permanently delete them!" +COM_ASSOCIATIONS_PURGE_FAILED="Failed to delete all associations." +COM_ASSOCIATIONS_PURGE_NONE="There were no associations to delete." +COM_ASSOCIATIONS_PURGE_SUCCESS="All associations have been deleted." +COM_ASSOCIATIONS_REFERENCE_ITEM="Reference" +COM_ASSOCIATIONS_SAVE_REFERENCE="Save Reference" +COM_ASSOCIATIONS_SAVE_TARGET="Save Target" +COM_ASSOCIATIONS_SELECT_MENU="- Select Menu -" +COM_ASSOCIATIONS_SELECT_TARGET="Select Target" +COM_ASSOCIATIONS_SELECT_TARGET_LANGUAGE="- Select Target Language -" +COM_ASSOCIATIONS_TITLE="Associations" +COM_ASSOCIATIONS_TITLE_EDIT="Multilingual Associations: Edit Associations (%1s > %2s)" +COM_ASSOCIATIONS_TITLE_LIST="Multilingual Associations (%1s > %2s)" +COM_ASSOCIATIONS_TITLE_LIST_SELECT="Multilingual Associations: Select Item Type and Language" +COM_ASSOCIATIONS_XML_DESCRIPTION="Improved multilingual content management component" diff --git a/administrator/language/en-GB/en-GB.com_associations.sys.ini b/administrator/language/en-GB/en-GB.com_associations.sys.ini new file mode 100644 index 0000000000000..e9846cdcd5aa3 --- /dev/null +++ b/administrator/language/en-GB/en-GB.com_associations.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; Copyright (C) 2005 - 2016 Open Source Matters. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 + +COM_ASSOCIATIONS="Multilingual Associations" +COM_ASSOCIATIONS_XML_DESCRIPTION="Improved multilingual content management component" \ No newline at end of file diff --git a/administrator/language/en-GB/en-GB.com_contact.ini b/administrator/language/en-GB/en-GB.com_contact.ini index 2f3ae894d5809..e04687039a12d 100644 --- a/administrator/language/en-GB/en-GB.com_contact.ini +++ b/administrator/language/en-GB/en-GB.com_contact.ini @@ -20,6 +20,7 @@ COM_CONTACT_CONTACT_DETAILS="Details" COM_CONTACT_CONTACT_DISPLAY_DETAILS="Display options for the individual contact page." COM_CONTACT_CONTACT_SETTINGS_LABEL="Contact Options" COM_CONTACT_CONTACT_VIEW_DEFAULT_DESC="This links to the contact information for one contact." +COM_CONTACT_CONTACTS="Contact" COM_CONTACT_DETAILS="Contact Information" COM_CONTACT_EDIT_CONTACT="Edit Contact" COM_CONTACT_EDIT_DETAILS="Edit contact information displayed on an individual page." diff --git a/administrator/language/en-GB/en-GB.com_menus.ini b/administrator/language/en-GB/en-GB.com_menus.ini index 7cd31f5436127..b52590b2b69f4 100644 --- a/administrator/language/en-GB/en-GB.com_menus.ini +++ b/administrator/language/en-GB/en-GB.com_menus.ini @@ -138,6 +138,7 @@ COM_MENUS_ITEMS_SET_HOME_0="No menu item set to home." COM_MENUS_ITEMS_SET_HOME_1="1 menu item successfully set to home." COM_MENUS_ITEMS_SET_HOME_MORE="%d menu items successfully set to home." COM_MENUS_ITEMS_UNSET_HOME="1 menu item successfully unset to home." +COM_MENUS_LABEL_HIDDEN="Hidden" COM_MENUS_LAYOUT_FEATURED_OPTIONS="Layout" COM_MENUS_LAYOUT_MENUTYPE_OPTIONS_LABEL="Menu Type" COM_MENUS_LINKTYPE_OPTIONS_LABEL="Link Type" @@ -152,14 +153,13 @@ COM_MENUS_MENU_MENUTYPE_LABEL="Menu Type" COM_MENUS_MENU_SAVE_SUCCESS="Menu successfully saved" COM_MENUS_MENU_SEARCH_FILTER="Search in Title or Menu type" COM_MENUS_MENU_SPRINTF="Menu: %s" +COM_MENUS_MENUS="Menu items" COM_MENUS_MENU_TYPE_PROTECTED_MENU_LABEL="Menu (Protected)" COM_MENUS_MENU_TYPE_PROTECTED_MAIN_LABEL="Main (Protected)" COM_MENUS_TYPE_SYSTEM="System Links" COM_MENUS_MENU_TITLE_DESC="The title of the menu to display in the Administrator Menubar and lists." COM_MENUS_MENUS_FILTER_SEARCH_DESC="Search in title and menu type." COM_MENUS_MENUS_FILTER_SEARCH_LABEL="Search Menus" -COM_MENUS_PAGE_OPTIONS_LABEL="Page Display" -COM_MENUS_LABEL_HIDDEN="Hidden" ; in the following string ; %1$s is for module title, %2$s is for access-title, %3$s is for position COM_MENUS_MODULE_ACCESS_POSITION="%1$s (%2$s in %3$s)" @@ -184,6 +184,7 @@ COM_MENUS_NEW_MENUITEM="New Menu Item" COM_MENUS_NO_ITEM_SELECTED="No menu items selected." COM_MENUS_NO_MENUS_SELECTED="No menu selected." COM_MENUS_OPTION_SELECT_LEVEL="- Select Max Levels -" +COM_MENUS_PAGE_OPTIONS_LABEL="Page Display" COM_MENUS_REQUEST_FIELDSET_LABEL="Required Settings" COM_MENUS_SAVE_SUCCESS="Menu item successfully saved." COM_MENUS_SELECT_A_MENUITEM="Select a Menu Item" @@ -206,6 +207,7 @@ COM_MENUS_TYPE_HEADING="Menu Heading" COM_MENUS_TYPE_HEADING_DESC="A heading for use within menus, useful when separating menus with a separator." COM_MENUS_TYPE_SEPARATOR="Text Separator" COM_MENUS_TYPE_SEPARATOR_DESC="A text separator." +COM_MENUS_TYPE_SYSTEM="System Links" COM_MENUS_TYPE_UNEXISTING="Component '%s' does not exist." COM_MENUS_TYPE_UNKNOWN="Unknown" COM_MENUS_VIEW_EDIT_ITEM_TITLE="Menus: Edit Item" diff --git a/administrator/language/en-GB/en-GB.com_newsfeeds.ini b/administrator/language/en-GB/en-GB.com_newsfeeds.ini index a5e2375495baa..aaabd65bd8bdb 100644 --- a/administrator/language/en-GB/en-GB.com_newsfeeds.ini +++ b/administrator/language/en-GB/en-GB.com_newsfeeds.ini @@ -115,6 +115,7 @@ COM_NEWSFEEDS_N_ITEMS_TRASHED_1="News feed successfully trashed." COM_NEWSFEEDS_N_ITEMS_UNPUBLISHED="%d news feeds successfully unpublished." COM_NEWSFEEDS_N_ITEMS_UNPUBLISHED_1="News feed successfully unpublished." COM_NEWSFEEDS_NEW_NEWSFEED="New News Feed" +COM_NEWSFEEDS_NEWSFEEDS="Newsfeeds" COM_NEWSFEEDS_NO_ITEM_SELECTED="No news feeds selected." COM_NEWSFEEDS_NONE="None" COM_NEWSFEEDS_NUM_ARTICLES_HEADING="# Articles" diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql index 773c6d9a38f5d..7474bca850e9b 100644 --- a/installation/sql/mysql/joomla.sql +++ b/installation/sql/mysql/joomla.sql @@ -516,6 +516,7 @@ INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `elem (31, 0, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (32, 0, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (33, 0, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), +(34, 0, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (102, 0, 'phputf8', 'library', 'phputf8', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (103, 0, 'Joomla! Platform', 'library', 'joomla', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (104, 0, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), @@ -1383,7 +1384,7 @@ CREATE TABLE IF NOT EXISTS `#__menu` ( -- INSERT INTO `#__menu` (`id`, `menutype`, `title`, `alias`, `note`, `path`, `link`, `type`, `published`, `parent_id`, `level`, `component_id`, `checked_out`, `checked_out_time`, `browserNav`, `access`, `img`, `template_style_id`, `params`, `lft`, `rgt`, `home`, `language`, `client_id`) VALUES -(1, '', 'Menu_Item_Root', 'root', '', '', '', '', 1, 0, 0, 0, 0, '0000-00-00 00:00:00', 0, 0, '', 0, '', 0, 43, 0, '*', 0), +(1, '', 'Menu_Item_Root', 'root', '', '', '', '', 1, 0, 0, 0, 0, '0000-00-00 00:00:00', 0, 0, '', 0, '', 0, 45, 0, '*', 0), (2, 'menu', 'com_banners', 'Banners', '', 'Banners', 'index.php?option=com_banners', 'component', 1, 1, 1, 4, 0, '0000-00-00 00:00:00', 0, 0, 'class:banners', 0, '', 1, 10, 0, '*', 1), (3, 'menu', 'com_banners', 'Banners', '', 'Banners/Banners', 'index.php?option=com_banners', 'component', 1, 2, 2, 4, 0, '0000-00-00 00:00:00', 0, 0, 'class:banners', 0, '', 2, 3, 0, '*', 1), (4, 'menu', 'com_banners_categories', 'Categories', '', 'Banners/Categories', 'index.php?option=com_categories&extension=com_banners', 'component', 1, 2, 2, 6, 0, '0000-00-00 00:00:00', 0, 0, 'class:banners-cat', 0, '', 4, 5, 0, '*', 1), @@ -1403,7 +1404,8 @@ INSERT INTO `#__menu` (`id`, `menutype`, `title`, `alias`, `note`, `path`, `link (19, 'menu', 'com_joomlaupdate', 'Joomla! Update', '', 'Joomla! Update', 'index.php?option=com_joomlaupdate', 'component', 1, 1, 1, 28, 0, '0000-00-00 00:00:00', 0, 0, 'class:joomlaupdate', 0, '', 35, 36, 0, '*', 1), (20, 'main', 'com_tags', 'Tags', '', 'Tags', 'index.php?option=com_tags', 'component', 1, 1, 1, 29, 0, '0000-00-00 00:00:00', 0, 1, 'class:tags', 0, '', 37, 38, 0, '', 1), (21, 'main', 'com_postinstall', 'Post-installation messages', '', 'Post-installation messages', 'index.php?option=com_postinstall', 'component', 1, 1, 1, 32, 0, '0000-00-00 00:00:00', 0, 1, 'class:postinstall', 0, '', 39, 40, 0, '*', 1), -(101, 'mainmenu', 'Home', 'home', '', 'home', 'index.php?option=com_content&view=featured', 'component', 1, 1, 1, 22, 0, '0000-00-00 00:00:00', 0, 1, '', 0, '{"featured_categories":[""],"layout_type":"blog","num_leading_articles":"1","num_intro_articles":"3","num_columns":"3","num_links":"0","multi_column_order":"1","orderby_pri":"","orderby_sec":"front","order_date":"","show_pagination":"2","show_pagination_results":"1","show_title":"","link_titles":"","show_intro":"","info_block_position":"","show_category":"","link_category":"","show_parent_category":"","link_parent_category":"","show_author":"","link_author":"","show_create_date":"","show_modify_date":"","show_publish_date":"","show_item_navigation":"","show_vote":"","show_readmore":"","show_readmore_title":"","show_icons":"","show_print_icon":"","show_email_icon":"","show_hits":"","show_noauth":"","show_feed_link":"1","feed_summary":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":1,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}', 41, 42, 1, '*', 0); +(22, 'main', 'com_associations', 'Multilingual Associations', '', 'Multilingual Associations', 'index.php?option=com_associations', 'component', 1, 1, 1, 34, 0, '0000-00-00 00:00:00', 0, 0, 'class:associations', 0, '', 41, 42, 0, '*', 1), +(101, 'mainmenu', 'Home', 'home', '', 'home', 'index.php?option=com_content&view=featured', 'component', 1, 1, 1, 22, 0, '0000-00-00 00:00:00', 0, 1, '', 0, '{"featured_categories":[""],"layout_type":"blog","num_leading_articles":"1","num_intro_articles":"3","num_columns":"3","num_links":"0","multi_column_order":"1","orderby_pri":"","orderby_sec":"front","order_date":"","show_pagination":"2","show_pagination_results":"1","show_title":"","link_titles":"","show_intro":"","info_block_position":"","show_category":"","link_category":"","show_parent_category":"","link_parent_category":"","show_author":"","link_author":"","show_create_date":"","show_modify_date":"","show_publish_date":"","show_item_navigation":"","show_vote":"","show_readmore":"","show_readmore_title":"","show_icons":"","show_print_icon":"","show_email_icon":"","show_hits":"","show_noauth":"","show_feed_link":"1","feed_summary":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":1,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}', 43, 44, 1, '*', 0); -- -------------------------------------------------------- diff --git a/installation/sql/postgresql/joomla.sql b/installation/sql/postgresql/joomla.sql index a1cdd5518ddaa..6fa0d30984a1b 100644 --- a/installation/sql/postgresql/joomla.sql +++ b/installation/sql/postgresql/joomla.sql @@ -504,7 +504,8 @@ INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder" (30, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), (31, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), (32, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), -(33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0); +(33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), +(34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0); -- Libraries INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES @@ -1348,7 +1349,8 @@ INSERT INTO "#__menu" ("id", "menutype", "title", "alias", "note", "path", "link (19, 'menu', 'com_joomlaupdate', 'Joomla! Update', '', 'Joomla! Update', 'index.php?option=com_joomlaupdate', 'component', 1, 1, 1, 28, 0, '1970-01-01 00:00:00', 0, 0, 'class:joomlaupdate', 0, '', 35, 36, 0, '*', 1), (20, 'main', 'com_tags', 'Tags', '', 'Tags', 'index.php?option=com_tags', 'component', 1, 1, 1, 29, 0, '1970-01-01 00:00:00', 0, 1, 'class:tags', 0, '', 37, 38, 0, '', 1), (21, 'main', 'com_postinstall', 'Post-installation messages', '', 'Post-installation messages', 'index.php?option=com_postinstall', 'component', 1, 1, 1, 32, 0, '1970-01-01 00:00:00', 0, 1, 'class:postinstall', 0, '', 39, 40, 0, '*', 1), -(101, 'mainmenu', 'Home', 'home', '', 'home', 'index.php?option=com_content&view=featured', 'component', 1, 1, 1, 22, 0, '1970-01-01 00:00:00', 0, 1, '', 0, '{"featured_categories":[""],"layout_type":"blog","num_leading_articles":"1","num_intro_articles":"3","num_columns":"3","num_links":"0","multi_column_order":"1","orderby_pri":"","orderby_sec":"front","order_date":"","show_pagination":"2","show_pagination_results":"1","show_title":"","link_titles":"","show_intro":"","info_block_position":"","show_category":"","link_category":"","show_parent_category":"","link_parent_category":"","show_author":"","link_author":"","show_create_date":"","show_modify_date":"","show_publish_date":"","show_item_navigation":"","show_vote":"","show_readmore":"","show_readmore_title":"","show_icons":"","show_print_icon":"","show_email_icon":"","show_hits":"","show_noauth":"","show_feed_link":"1","feed_summary":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":1,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}', 41, 42, 1, '*', 0); +(22, 'main', 'com_associations', 'Multilingual Associations', '', 'Multilingual Associations', 'index.php?option=com_associations', 'component', 1, 1, 1, 34, 0, '1970-01-01 00:00:00', 0, 0, 'class:associations', 0, '', 41, 42, 0, '*', 1), +(101, 'mainmenu', 'Home', 'home', '', 'home', 'index.php?option=com_content&view=featured', 'component', 1, 1, 1, 22, 0, '1970-01-01 00:00:00', 0, 1, '', 0, '{"featured_categories":[""],"layout_type":"blog","num_leading_articles":"1","num_intro_articles":"3","num_columns":"3","num_links":"0","multi_column_order":"1","orderby_pri":"","orderby_sec":"front","order_date":"","show_pagination":"2","show_pagination_results":"1","show_title":"","link_titles":"","show_intro":"","info_block_position":"","show_category":"","link_category":"","show_parent_category":"","link_parent_category":"","show_author":"","link_author":"","show_create_date":"","show_modify_date":"","show_publish_date":"","show_item_navigation":"","show_vote":"","show_readmore":"","show_readmore_title":"","show_icons":"","show_print_icon":"","show_email_icon":"","show_hits":"","show_noauth":"","show_feed_link":"1","feed_summary":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":1,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}', 43, 44, 1, '*', 0); SELECT setval('#__menu_id_seq', 102, false); diff --git a/installation/sql/sqlazure/joomla.sql b/installation/sql/sqlazure/joomla.sql index ac38e0d4b8012..3d49f956a30ba 100644 --- a/installation/sql/sqlazure/joomla.sql +++ b/installation/sql/sqlazure/joomla.sql @@ -805,7 +805,9 @@ SELECT 31, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, '', '', '', '', UNION ALL SELECT 32, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0 UNION ALL -SELECT 33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0; +SELECT 33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0 +UNION ALL +SELECT 34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0; -- Libraries INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state]) @@ -2264,7 +2266,7 @@ CREATE NONCLUSTERED INDEX [idx_img] ON [#__menu] SET IDENTITY_INSERT [#__menu] ON; INSERT INTO [#__menu] ([id], [menutype], [title], [alias], [note], [path], [link], [type], [published], [parent_id], [level], [component_id], [checked_out], [checked_out_time], [browserNav], [access], [img], [template_style_id], [params], [lft], [rgt], [home], [language], [client_id]) -SELECT 1, '', 'Menu_Item_Root', 'root', '', '', '', '', 1, 0, 0, 0, 0, '1900-01-01 00:00:00', 0, 0, '', 0, '', 0, 43, 0, '*', 0 +SELECT 1, '', 'Menu_Item_Root', 'root', '', '', '', '', 1, 0, 0, 0, 0, '1900-01-01 00:00:00', 0, 0, '', 0, '', 0, 45, 0, '*', 0 UNION ALL SELECT 2, 'menu', 'com_banners', 'Banners', '', 'Banners', 'index.php?option=com_banners', 'component', 1, 1, 1, 4, 0, '1900-01-01 00:00:00', 0, 0, 'class:banners', 0, '', 1, 10, 0, '*', 1 UNION ALL @@ -2304,7 +2306,9 @@ SELECT 20, 'menu', 'com_tags', 'Tags', '', 'Tags', 'index.php?option=com_tags', UNION ALL SELECT 21, 'menu', 'com_postinstall', 'Post-installation messages', '', 'Post-installation messages', 'index.php?option=com_postinstall', 'component', 1, 1, 1, 32, 0, '1900-01-01 00:00:00', 0, 1, 'class:postinstall', 0, '', 39, 40, 0, '*', 1 UNION ALL -SELECT 101, 'mainmenu', 'Home', 'home', '', 'home', 'index.php?option=com_content&view=featured', 'component', 1, 1, 1, 22, 0, '1900-01-01 00:00:00', 0, 1, '', 0, '{"featured_categories":[""],"layout_type":"blog","num_leading_articles":"1","num_intro_articles":"3","num_columns":"3","num_links":"0","multi_column_order":"1","orderby_pri":"","orderby_sec":"front","order_date":"","show_pagination":"2","show_pagination_results":"1","show_title":"","link_titles":"","show_intro":"","info_block_position":"","show_category":"","link_category":"","show_parent_category":"","link_parent_category":"","show_author":"","link_author":"","show_create_date":"","show_modify_date":"","show_publish_date":"","show_item_navigation":"","show_vote":"","show_readmore":"","show_readmore_title":"","show_icons":"","show_print_icon":"","show_email_icon":"","show_hits":"","show_noauth":"","show_feed_link":"1","feed_summary":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":1,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}', 41, 42, 1, '*', 0; +SELECT 22, 'menu', 'com_associations', 'Multilingual Associations', '', 'Multilingual Associations', 'index.php?option=com_associations', 'component', 1, 1, 1, 34, 0, '1900-01-01 00:00:00', 0, 0, 'class:associations', 0, '', 41, 42, 0, '*', 1 +UNION ALL +SELECT 101, 'mainmenu', 'Home', 'home', '', 'home', 'index.php?option=com_content&view=featured', 'component', 1, 1, 1, 22, 0, '1900-01-01 00:00:00', 0, 1, '', 0, '{"featured_categories":[""],"layout_type":"blog","num_leading_articles":"1","num_intro_articles":"3","num_columns":"3","num_links":"0","multi_column_order":"1","orderby_pri":"","orderby_sec":"front","order_date":"","show_pagination":"2","show_pagination_results":"1","show_title":"","link_titles":"","show_intro":"","info_block_position":"","show_category":"","link_category":"","show_parent_category":"","link_parent_category":"","show_author":"","link_author":"","show_create_date":"","show_modify_date":"","show_publish_date":"","show_item_navigation":"","show_vote":"","show_readmore":"","show_readmore_title":"","show_icons":"","show_print_icon":"","show_email_icon":"","show_hits":"","show_noauth":"","show_feed_link":"1","feed_summary":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":1,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}', 43, 44, 1, '*', 0; SET IDENTITY_INSERT [#__menu] OFF; diff --git a/layouts/joomla/content/associations.php b/layouts/joomla/content/associations.php index cb3766483544b..87c9556337e2e 100644 --- a/layouts/joomla/content/associations.php +++ b/layouts/joomla/content/associations.php @@ -15,7 +15,7 @@
    $item) : ?>
  • - link; ?> + link; ?>
diff --git a/libraries/joomla/association/extension/helper.php b/libraries/joomla/association/extension/helper.php new file mode 100644 index 0000000000000..67e55435721f4 --- /dev/null +++ b/libraries/joomla/association/extension/helper.php @@ -0,0 +1,292 @@ +associationsSupport; + } + + /** + * Get the item types + * + * @return array Array of item types + * + * @since __DEPLOY_VERSION__ + */ + public function getItemTypes() + { + return $this->itemTypes; + } + + /** + * Get the associated items for an item + * + * @param string $typeName The item type + * @param int $itemId The id of item for which we need the associated items + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public function getAssociationList($typeName, $itemId) + { + $items = array(); + + $associations = $this->getAssociations($typeName, $itemId); + + foreach ($associations as $key => $association) + { + $items[$key] = ArrayHelper::fromObject($this->getItem($typeName, (int) $association->id), false); + } + + return $items; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * + * @return array Array of item types + * + * @since __DEPLOY_VERSION__ + */ + public function getType($typeName = '') + { + $fields = $this->getFieldsTemplate(); + $tables = array(); + $joins = array(); + $support = $this->getSupportTemplate(); + $title = ''; + + return array( + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title + ); + } + + /** + * Get information about the fields the type provides + * + * @param string $typeName The item type + * + * @return array Array of support information + * + * @since __DEPLOY_VERSION__ + */ + public function getTypeFields($typeName) + { + return $this->getTypeInformation($typeName, 'fields'); + } + + /** + * Get information about the fields the type provides + * + * @param string $typeName The item type + * + * @return array Array of support information + * + * @since __DEPLOY_VERSION__ + */ + public function getTypeSupport($typeName) + { + return $this->getTypeInformation($typeName, 'support'); + } + + /** + * Get information about the tables the type use + * + * @param string $typeName The item type + * + * @return array Array of support information + * + * @since __DEPLOY_VERSION__ + */ + public function getTypeTables($typeName) + { + return $this->getTypeInformation($typeName, 'tables'); + } + + /** + * Get information about the table joins for the type + * + * @param string $typeName The item type + * + * @return array Array of support information + * + * @since __DEPLOY_VERSION__ + */ + public function getTypeJoins($typeName) + { + return $this->getTypeInformation($typeName, 'joins'); + } + + /** + * Get the type title + * + * @param string $typeName The item type + * + * @return array Array of support information + * + * @since __DEPLOY_VERSION__ + */ + public function getTypeTitle($typeName) + { + $type = $this->getType($typeName); + + if (!array_key_exists('title', $type)) + { + return ''; + } + + return $type['title']; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * @param string $part part of the information + * + * @return array Array of support information + * + * @since __DEPLOY_VERSION__ + */ + private function getTypeInformation($typeName, $part = 'support') + { + $type = $this->getType($typeName); + + if (!array_key_exists($part, $type)) + { + return array(); + } + + return $type[$part]; + } + + /** + * Get a table field name for a type + * + * @param string $typeName The item type + * @param string $fieldName The item type + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + public function getTypeFieldName($typeName, $fieldName) + { + $fields = $this->getTypeFields($typeName); + + if (!array_key_exists($fieldName, $fields)) + { + return ''; + } + + $tmp = $fields[$fieldName]; + $pos = strpos($tmp, '.'); + + if ($pos === false) + { + return $tmp; + } + + return substr($tmp, $pos + 1); + } + + /** + * Get default values for support array + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + protected function getSupportTemplate() + { + return array( + 'state' => false, + 'acl' => false, + 'checkout' => false + ); + } + + /** + * Get default values for fields array + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + protected function getFieldsTemplate() + { + return array( + 'id' => 'a.id', + 'title' => 'a.title', + 'alias' => 'a.alias', + 'ordering' => 'a.ordering', + 'menutype' => '', + 'level' => '', + 'catid' => 'a.catid', + 'language' => 'a.language', + 'access' => 'a.access', + 'state' => 'a.state', + 'created_user_id' => 'a.created_by', + 'checked_out' => 'a.checked_out', + 'checked_out_time' => 'a.checked_out_time' + ); + } +} diff --git a/libraries/joomla/association/extension/interface.php b/libraries/joomla/association/extension/interface.php new file mode 100644 index 0000000000000..692dd80bca6f7 --- /dev/null +++ b/libraries/joomla/association/extension/interface.php @@ -0,0 +1,27 @@ +' + title + ''); + $(reference).contents().find('#jform_associations_' + languageCode).val(targetLoadedId).change().chosen(); + } + + // Update the target item associations tab. + var reference = document.getElementById('reference-association'); + var referenceId = reference.getAttribute('data-id'); + var languageCode = reference.getAttribute('data-language').replace(/-/, '_'); + var title = $(reference).contents().find('#jform_title').val(); + var target = $(this).contents(); + + // - For modal association selectors. + target.find('#jform_associations_' + languageCode + '_id').val(referenceId); + target.find('#jform_associations_' + languageCode + '_name').val(title); + + // - For chosen association selectors (menus). + target.find('#jform_associations_' + languageCode + '_chzn').remove(); + var chznField = target.find('#jform_associations_' + languageCode); + chznField.append(''); + chznField.val(referenceId).change().chosen(); + + var parse, langAssociation; + + $('#jform_itemlanguage option').each(function() + { + parse = $(this).val().split(':'); + + if (typeof parse[1] !== 'undefined' && parse[1] !== '0') + { + // - For modal association selectors. + langAssociation = parse[0].replace(/-/,'_'); + target.find('#jform_associations_' + langAssociation + '_id').val(parse[1]); + + // - For chosen association selectors (menus). + target.find('#jform_associations_' + langAssociation + '_chzn').remove(); + chznField = target.find('#jform_associations_' + langAssociation); + chznField.append(''); + chznField.val(parse[1]).change().chosen(); + } + }); + + // Iframe load finished, hide Joomla loading layer. + Joomla.loadingLayer('hide'); + } + }); +}); diff --git a/media/com_associations/js/sidebyside.js b/media/com_associations/js/sidebyside.js new file mode 100644 index 0000000000000..89e3c7484dcfc --- /dev/null +++ b/media/com_associations/js/sidebyside.js @@ -0,0 +1 @@ +jQuery(document).ready(function(a){a("#toolbar-target").hide(),a("#toolbar-copy").hide(),Joomla.submitbutton=function(b){if("association.cancel"==b)Joomla.submitform(b);else if("copy"==b)window.frames["reference-association"].Joomla.submitbutton(document.getElementById("adminForm").getAttribute("data-associatedview")+".save2copy");else if("undo-association"==b){var c=document.getElementById("reference-association"),d=document.getElementById("target-association"),f=(c.getAttribute("data-id"),c.getAttribute("data-language").replace(/-/,"_")),h=(d.getAttribute("data-id"),d.getAttribute("data-language").replace(/-/,"_"));c=a(c).contents(),d=a(d).contents(),c.find("#jform_associations_"+h+"_id").val(""),c.find("#jform_associations_"+h+"_name").val(""),c.find("#jform_associations_"+h+"_chzn").remove(),c.find("#jform_associations_"+h).val("").change().chosen();var i="";a("#jform_itemlanguage option").each(function(){i=a(this).val().split("|")[0],"undefined"!=typeof i&&(i=i.replace(/-/,"_"),d.find("#jform_associations_"+i+"_id").val(""),d.find("#jform_associations_"+i+"_chzn").remove(),d.find("#jform_associations_"+i).val("").change().chosen())}),d.find("#jform_associations_"+f+"_id").val(""),d.find("#jform_associations_"+f+"_name").val(""),d.find("#jform_associations_"+f+"_chzn").remove(),d.find("#jform_associations_"+f).val("").change().chosen();var j=a("#jform_itemlanguage").val(),k=h.replace(/_/,"-");a('#jform_itemlanguage option[value="'+j+'"]').val(k+":0:add"),a("#jform_itemlanguage").val("").change(),a("#jform_itemlanguage").trigger("liszt:updated"),Joomla.submitbutton("reference")}else a("#"+b+"-association").contents().find("#jform_language").attr("disabled",!1),window.frames[b+"-association"].Joomla.submitbutton(document.getElementById("adminForm").getAttribute("data-associatedview")+".apply");return!1},Joomla.loadingLayer("load"),a("body").on("click","#toogle-left-panel",function(){var b=this.getAttribute("data-hide-reference"),c=this.getAttribute("data-show-reference");a(this).text()===b?a(this).text(c):a(this).text(b),a("#left-panel").toggle(),a("#right-panel").toggleClass("full-width")}),a("body").on("change","#jform_itemlanguage",function(){var b=document.getElementById("target-association"),c=a(this).val();""!=c&&"undefined"!=typeof c?(b.setAttribute("data-action",c.split(":")[2]),b.setAttribute("data-id",c.split(":")[1]),b.setAttribute("data-language",c.split(":")[0]),Joomla.loadingLayer("show"),b.src=b.getAttribute("data-editurl")+"&task="+b.getAttribute("data-item")+"."+b.getAttribute("data-action")+"&id="+b.getAttribute("data-id")):(a("#toolbar-target").hide(),a("#toolbar-copy").hide(),a("#select-change").addClass("hidden"),a("#remove-assoc").addClass("hidden"),b.setAttribute("data-action",""),b.setAttribute("data-id","0"),b.setAttribute("data-language",""),b.src="")}),a("#reference-association").on("load",function(){if(a(this).contents().find("#jform_id").val()!==this.getAttribute("data-id")){var b=document.getElementById("target-association");b.src=b.getAttribute("data-editurl")+"&task="+b.getAttribute("data-item")+".edit&id="+a(this).contents().find("#jform_id").val(),this.src=this.getAttribute("data-editurl")+"&task="+this.getAttribute("data-item")+".edit&id="+this.getAttribute("data-id")}var c=a(this).contents();c.find("#jform_language_chzn").remove(),c.find("#jform_language").attr("disabled",!0).chosen(),c.find("#associations").find(".btn").remove();var d="";a("#jform_itemlanguage option").each(function(){d=a(this).val().split(":"),"undefined"!=typeof d[0]&&(langAssociation=d[0].replace(/-/,"_"),""==c.find("#jform_associations_"+langAssociation+"_id").val()&&c.find("#jform_associations_"+langAssociation+"_name").val(document.getElementById("reference-association").getAttribute("data-no-assoc")))}),Joomla.loadingLayer("hide")}),a("#target-association").on("load",function(){if(""!=this.getAttribute("src")){a("#toolbar-target").show(),a("#toolbar-copy").show(),a("#select-change").removeClass("hidden");var b=this.getAttribute("data-language"),c=this.getAttribute("data-id"),d=a(this).contents().find("#jform_id").val()||"0";if(a(this).contents().find('a[href="#associations"]').parent().hide(),a(this).contents().find("#associations").hasClass("active")&&(a(this).contents().find('a[href="#associations"]').parent().removeClass("active"),a(this).contents().find("#associations").removeClass("active"),a(this).contents().find(".nav-tabs").find("li").first().addClass("active"),a(this).contents().find(".tab-content").find(".tab-pane").first().addClass("active")),a(this).contents().find("#jform_language_chzn").remove(),a(this).contents().find("#jform_language").val(b).change().attr("disabled",!0).chosen(),"0"==d)document.getElementById("select-change-text").innerHTML=document.getElementById("select-change").getAttribute("data-select");else{document.getElementById("select-change-text").innerHTML=document.getElementById("select-change").getAttribute("data-change"),a("#remove-assoc").removeClass("hidden");var e=document.getElementById("target-id").value,f=""==e?d:e+","+d;document.getElementById("target-id").value=f,d!=c&&(a('#jform_itemlanguage option[value^="'+b+":"+c+':add"]').val(b+":"+d+":edit"),this.setAttribute("data-id",d),this.setAttribute("data-action","edit"));var g=document.getElementById("reference-association"),h=b.replace(/-/,"_"),i=a(this).contents().find("#jform_title").val();a(g).contents().find("#jform_associations_"+h+"_id").val(d),a(g).contents().find("#jform_associations_"+h+"_name").val(i),a(g).contents().find("#jform_associations_"+h+"_chzn").remove(),a(g).contents().find("#jform_associations_"+h).append('"),a(g).contents().find("#jform_associations_"+h).val(d).change().chosen()}var g=document.getElementById("reference-association"),j=g.getAttribute("data-id"),h=g.getAttribute("data-language").replace(/-/,"_"),i=a(g).contents().find("#jform_title").val(),k=a(this).contents();k.find("#jform_associations_"+h+"_id").val(j),k.find("#jform_associations_"+h+"_name").val(i),k.find("#jform_associations_"+h+"_chzn").remove();var l=k.find("#jform_associations_"+h);l.append('"),l.val(j).change().chosen();var m,n;a("#jform_itemlanguage option").each(function(){m=a(this).val().split(":"),"undefined"!=typeof m[1]&&"0"!==m[1]&&(n=m[0].replace(/-/,"_"),k.find("#jform_associations_"+n+"_id").val(m[1]),k.find("#jform_associations_"+n+"_chzn").remove(),l=k.find("#jform_associations_"+n),l.append(''),l.val(m[1]).change().chosen())}),Joomla.loadingLayer("hide")}})}); \ No newline at end of file