/libraries/fof/table/relations.php
PHP | 942 lines | 508 code | 131 blank | 303 comment | 69 complexity | 9df39f8c2734059138c8fa8761c20577 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
- <?php
- /**
- * @package FrameworkOnFramework
- * @subpackage table
- * @copyright Copyright (C) 2010 - 2014 Akeeba Ltd. All rights reserved.
- * @license GNU General Public License version 2 or later; see LICENSE.txt
- */
- // Protect from unauthorized access
- defined('FOF_INCLUDED') or die;
- class FOFTableRelations
- {
- /**
- * Holds all known relation definitions
- *
- * @var array
- */
- private $relations = array(
- 'child' => array(),
- 'parent' => array(),
- 'children' => array(),
- 'multiple' => array(),
- );
- /**
- * Holds the default relations' keys
- *
- * @var array
- */
- private $defaultRelation = array(
- 'child' => null,
- 'parent' => null,
- 'children' => null,
- 'multiple' => null,
- );
- /**
- * The table these relations are attached to
- *
- * @var FOFTable
- */
- private $table = null;
- /**
- * The name of the component used by our attached table
- *
- * @var string
- */
- private $componentName = 'joomla';
- /**
- * The type (table name without prefix and component name) of our attached table
- *
- * @var string
- */
- private $tableType = '';
- /**
- * Create a relations object based on the provided FOFTable instance
- *
- * @param FOFTable $table The table instance used to initialise the relations
- */
- public function __construct(FOFTable $table)
- {
- // Store the table
- $this->table = $table;
- // Get the table's type from its name
- $tableName = $table->getTableName();
- $tableName = str_replace('#__', '', $tableName);
- $type = explode("_", $tableName);
- if (count($type) == 1)
- {
- $this->tableType = array_pop($type);
- }
- else
- {
- $this->componentName = array_shift($type);
- $this->tableType = array_pop($type);
- }
- $this->tableType = FOFInflector::singularize($this->tableType);
- $tableKey = $table->getKeyName();
- unset($type);
- // Scan all table keys and look for foo_bar_id fields. These fields are used to populate parent relations.
- foreach ($table->getKnownFields() as $field)
- {
- // Skip the table key name
- if ($field == $tableKey)
- {
- continue;
- }
- if (substr($field, -3) != '_id')
- {
- continue;
- }
- $parts = explode('_', $field);
- // If the component type of the field is not set assume 'joomla'
- if (count($parts) == 2)
- {
- array_unshift($parts, 'joomla');
- }
- // Sanity check
- if (count($parts) != 3)
- {
- continue;
- }
- // Make sure we skip any references back to ourselves (should be redundant, due to key field check above)
- if ($parts[1] == $this->tableType)
- {
- continue;
- }
- // Default item name: the name of the table, singular
- $itemName = FOFInflector::singularize($parts[1]);
- // Prefix the item name with the component name if we refer to a different component
- if ($parts[0] != $this->componentName)
- {
- $itemName = $parts[0] . '_' . $itemName;
- }
- // Figure out the table class
- $tableClass = ucfirst($parts[0]) . 'Table' . ucfirst($parts[1]);
- $default = empty($this->relations['parent']);
- $this->addParentRelation($itemName, $tableClass, $field, $field, $default);
- }
- // Get the relations from the configuration provider
- $key = $table->getConfigProviderKey() . '.relations';
- $configRelations = $table->getConfigProvider()->get($key, array());
- if (!empty($configRelations))
- {
- foreach ($configRelations as $relation)
- {
- if (empty($relation['type']))
- {
- continue;
- }
- if (isset($relation['pivotTable']))
- {
- $this->addMultipleRelation($relation['itemName'], $relation['tableClass'],
- $relation['localKey'], $relation['ourPivotKey'], $relation['theirPivotKey'],
- $relation['remoteKey'], $relation['pivotTable'], $relation['default']);
- }
- else
- {
- $method = 'add' . ucfirst($relation['type']). 'Relation';
- if (!method_exists($this, $method))
- {
- continue;
- }
- $this->$method($relation['itemName'], $relation['tableClass'],
- $relation['localKey'], $relation['remoteKey'], $relation['default']);
- }
- }
- }
- }
- /**
- * Add a 1:1 forward (child) relation. This adds relations for the getChild() method.
- *
- * In other words: does a table HAVE ONE child
- *
- * Parent and child relations works the same way. We have them separated as it makes more sense for us humans to
- * read code like $item->getParent() and $item->getChild() than $item->getRelatedObject('someRandomKeyName')
- *
- * @param string $itemName is how it will be known locally to the getRelatedItem method (singular)
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: our primary key
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param boolean $default add as the default child relation?
- *
- * @return void
- */
- public function addChildRelation($itemName, $tableClass = null, $localKey = null, $remoteKey = null, $default = true)
- {
- $itemName = $this->normaliseItemName($itemName, false);
- if (empty($localKey))
- {
- $localKey = $this->table->getKeyName();
- }
- $this->addBespokeSimpleRelation('child', $itemName, $tableClass, $localKey, $remoteKey, $default);
- }
- /**
- * Defining an inverse 1:1 (parent) relation. You must specify at least the $tableClass or the $localKey.
- * This adds relations for the getParent() method.
- *
- * In other words: does a table BELONG TO ONE parent
- *
- * Parent and child relations works the same way. We have them separated as it makes more sense for us humans to
- * read code like $item->getParent() and $item->getChild() than $item->getRelatedObject('someRandomKeyName')
- *
- * @param string $itemName is how it will be known locally to the getRelatedItem method (singular)
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: componentname_itemname_id
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param boolean $default Is this the default parent relationship?
- *
- * @return void
- */
- public function addParentRelation($itemName, $tableClass = null, $localKey = null, $remoteKey = null, $default = true)
- {
- $itemName = $this->normaliseItemName($itemName, false);
- $this->addBespokeSimpleRelation('parent', $itemName, $tableClass, $localKey, $remoteKey, $default);
- }
- /**
- * Defining a forward 1:∞ (children) relation. This adds relations to the getChildren() method.
- *
- * In other words: does a table HAVE MANY children?
- *
- * The children relation works very much the same as the parent and child relation. The difference is that the
- * parent and child relations return a single table object, whereas the children relation returns an iterator to
- * many objects.
- *
- * @param string $itemName is how it will be known locally to the getRelatedItems method (plural)
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: our primary key
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param boolean $default is this the default children relationship?
- *
- * @return void
- */
- public function addChildrenRelation($itemName, $tableClass = null, $localKey = null, $remoteKey = null, $default = true)
- {
- $itemName = $this->normaliseItemName($itemName, true);
- if (empty($localKey))
- {
- $localKey = $this->table->getKeyName();
- }
- $this->addBespokeSimpleRelation('children', $itemName, $tableClass, $localKey, $remoteKey, $default);
- }
- /**
- * Defining a ∞:∞ (multiple) relation. This adds relations to the getMultiple() method.
- *
- * In other words: is a table RELATED TO MANY other records?
- *
- * @param string $itemName is how it will be known locally to the getRelatedItems method (plural)
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: our primary key field name
- * @param string $ourPivotKey is the column containing our side of the FK relation in the pivot table, default: $localKey
- * @param string $theirPivotKey is the column containing the other table's side of the FK relation in the pivot table, default $remoteKey
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param string $glueTable is the name of the glue (pivot) table, default: #__componentname_thisclassname_itemname with plural items (e.g. #__foobar_users_roles)
- * @param boolean $default is this the default multiple relation?
- */
- public function addMultipleRelation($itemName, $tableClass = null, $localKey = null, $ourPivotKey = null, $theirPivotKey = null, $remoteKey = null, $glueTable = null, $default = true)
- {
- $itemName = $this->normaliseItemName($itemName, true);
- if (empty($localKey))
- {
- $localKey = $this->table->getKeyName();
- }
- $this->addBespokePivotRelation('multiple', $itemName, $tableClass, $localKey, $remoteKey, $ourPivotKey, $theirPivotKey, $glueTable, $default);
- }
- /**
- * Removes a previously defined relation by name. You can optionally specify the relation type.
- *
- * @param string $itemName The name of the relation to remove
- * @param string $type [optional] The relation type (child, parent, children, ...)
- *
- * @return void
- */
- public function removeRelation($itemName, $type = null)
- {
- $types = array_keys($this->relations);
- if (in_array($type, $types))
- {
- $types = array($type);
- }
- foreach ($types as $type)
- {
- foreach ($this->relations[$type] as $relations)
- {
- if (array_key_exists($itemName, $relations))
- {
- unset ($this->relations[$type][$itemName]);
- return;
- }
- }
- }
- }
- /**
- * Removes all existing relations
- *
- * @param string $type The type or relations to remove, omit to remove all relation types
- *
- * @return void
- */
- public function clearRelations($type = null)
- {
- $types = array_keys($this->relations);
- if (in_array($type, $types))
- {
- $types = array($type);
- }
- foreach ($types as $type)
- {
- $this->relations[$type] = array();
- }
- }
- /**
- * Does the named relation exist? You can optionally specify the type.
- *
- * @param string $itemName The name of the relation to check
- * @param string $type [optional] The relation type (child, parent, children, ...)
- *
- * @return boolean
- */
- public function hasRelation($itemName, $type = null)
- {
- $types = array_keys($this->relations);
- if (in_array($type, $types))
- {
- $types = array($type);
- }
- foreach ($types as $type)
- {
- foreach ($this->relations[$type] as $relations)
- {
- if (array_key_exists($itemName, $relations))
- {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * Get the definition of a relation
- *
- * @param string $itemName The name of the relation to check
- * @param string $type [optional] The relation type (child, parent, children, ...)
- *
- * @return array
- *
- * @throws RuntimeException When the relation is not found
- */
- public function getRelation($itemName, $type)
- {
- $types = array_keys($this->relations);
- if (in_array($type, $types))
- {
- $types = array($type);
- }
- foreach ($types as $type)
- {
- foreach ($this->relations[$type] as $relations)
- {
- if (array_key_exists($itemName, $relations))
- {
- $temp = $relations[$itemName];
- $temp['type'] = $type;
- return $temp;
- }
- }
- }
- throw new RuntimeException("Relation $itemName not found in table {$this->tableType}", 500);
- }
- /**
- * Gets the item referenced by a named relation. You can optionally specify the type. Only single item relation
- * types will be searched.
- *
- * @param string $itemName The name of the relation to use
- * @param string $type [optional] The relation type (child, parent)
- *
- * @return FOFTable
- *
- * @throws RuntimeException If the named relation doesn't exist or isn't supposed to return single items
- */
- public function getRelatedItem($itemName, $type = null)
- {
- if (empty($type))
- {
- $relation = $this->getRelation($itemName, $type);
- $type = $relation['type'];
- }
- switch ($type)
- {
- case 'parent':
- return $this->getParent($itemName);
- break;
- case 'child':
- return $this->getChild($itemName);
- break;
- default:
- throw new RuntimeException("Invalid relation type $type for returning a single related item", 500);
- break;
- }
- }
- /**
- * Gets the iterator for the items referenced by a named relation. You can optionally specify the type. Only
- * multiple item relation types will be searched.
- *
- * @param string $itemName The name of the relation to use
- * @param string $type [optional] The relation type (children, multiple)
- *
- * @return FOFDatabaseIterator
- *
- * @throws RuntimeException If the named relation doesn't exist or isn't supposed to return single items
- */
- public function getRelatedItems($itemName, $type = null)
- {
- if (empty($type))
- {
- $relation = $this->getRelation($itemName, $type);
- $type = $relation['type'];
- }
- switch ($type)
- {
- case 'children':
- return $this->getChildren($itemName);
- break;
- case 'multiple':
- return $this->getMultiple($itemName);
- break;
- case 'siblings':
- return $this->getSiblings($itemName);
- break;
- default:
- throw new RuntimeException("Invalid relation type $type for returning a collection of related items", 500);
- break;
- }
- }
- /**
- * Gets a parent item
- *
- * @param string $itemName [optional] The name of the relation to use, skip to use the default parent relation
- *
- * @return FOFTable
- *
- * @throws RuntimeException When the relation is not found
- */
- public function getParent($itemName = null)
- {
- if (empty($itemName))
- {
- $itemName = $this->defaultRelation['parent'];
- }
- if (empty($itemName))
- {
- throw new RuntimeException(sprintf('Default parent relation for %s not found', $this->table->getTableName()), 500);
- }
- if (!isset($this->relations['parent'][$itemName]))
- {
- throw new RuntimeException(sprintf('Parent relation %s for %s not found', $itemName, $this->table->getTableName()), 500);
- }
- return $this->getTableFromRelation($this->relations['parent'][$itemName]);
- }
- /**
- * Gets a child item
- *
- * @param string $itemName [optional] The name of the relation to use, skip to use the default child relation
- *
- * @return FOFTable
- *
- * @throws RuntimeException When the relation is not found
- */
- public function getChild($itemName = null)
- {
- if (empty($itemName))
- {
- $itemName = $this->defaultRelation['child'];
- }
- if (empty($itemName))
- {
- throw new RuntimeException(sprintf('Default child relation for %s not found', $this->table->getTableName()), 500);
- }
- if (!isset($this->relations['child'][$itemName]))
- {
- throw new RuntimeException(sprintf('Child relation %s for %s not found', $itemName, $this->table->getTableName()), 500);
- }
- return $this->getTableFromRelation($this->relations['child'][$itemName]);
- }
- /**
- * Gets an iterator for the children items
- *
- * @param string $itemName [optional] The name of the relation to use, skip to use the default children relation
- *
- * @return FOFDatabaseIterator
- *
- * @throws RuntimeException When the relation is not found
- */
- public function getChildren($itemName = null)
- {
- if (empty($itemName))
- {
- $itemName = $this->defaultRelation['children'];
- }
- if (empty($itemName))
- {
- throw new RuntimeException(sprintf('Default children relation for %s not found', $this->table->getTableName()), 500);
- }
- if (!isset($this->relations['children'][$itemName]))
- {
- throw new RuntimeException(sprintf('Children relation %s for %s not found', $itemName, $this->table->getTableName()), 500);
- }
- return $this->getIteratorFromRelation($this->relations['children'][$itemName]);
- }
- /**
- * Gets an iterator for the sibling items. This relation is inferred from the parent relation. It returns all
- * elements on the same table which have the same parent.
- *
- * @param string $itemName [optional] The name of the relation to use, skip to use the default children relation
- *
- * @return FOFDatabaseIterator
- *
- * @throws RuntimeException When the relation is not found
- */
- public function getSiblings($itemName = null)
- {
- if (empty($itemName))
- {
- $itemName = $this->defaultRelation['parent'];
- }
- if (empty($itemName))
- {
- throw new RuntimeException(sprintf('Default siblings relation for %s not found', $this->table->getTableName()), 500);
- }
- if (!isset($this->relations['parent'][$itemName]))
- {
- throw new RuntimeException(sprintf('Sibling relation %s for %s not found', $itemName, $this->table->getTableName()), 500);
- }
- // Get my table class
- $tableName = $this->table->getTableName();
- $tableName = str_replace('#__', '', $tableName);
- $tableNameParts = explode('_', $tableName, 2);
- $tableClass = ucfirst($tableNameParts[0]) . 'Table' . ucfirst(FOFInflector::singularize($tableNameParts[1]));
- $parentRelation = $this->relations['parent'][$itemName];
- $relation = array(
- 'tableClass' => $tableClass,
- 'localKey' => $parentRelation['localKey'],
- 'remoteKey' => $parentRelation['localKey'],
- );
- return $this->getIteratorFromRelation($relation);
- }
- /**
- * Gets an iterator for the multiple items
- *
- * @param string $itemName [optional] The name of the relation to use, skip to use the default multiple relation
- *
- * @return FOFDatabaseIterator
- *
- * @throws RuntimeException When the relation is not found
- */
- public function getMultiple($itemName = null)
- {
- if (empty($itemName))
- {
- $itemName = $this->defaultRelation['multiple'];
- }
- if (empty($itemName))
- {
- throw new RuntimeException(sprintf('Default multiple relation for %s not found', $this->table->getTableName()), 500);
- }
- if (!isset($this->relations['multiple'][$itemName]))
- {
- throw new RuntimeException(sprintf('Multiple relation %s for %s not found', $itemName, $this->table->getTableName()), 500);
- }
- return $this->getIteratorFromRelation($this->relations['multiple'][$itemName]);
- }
- /**
- * Returns a FOFTable object based on a given relation
- *
- * @param array $relation Relation definition
- *
- * @return FOFTable
- *
- * @throws RuntimeException
- */
- private function getTableFromRelation($relation)
- {
- // Get a table object from the table class name
- $tableClass = $relation['tableClass'];
- $tableClassParts = FOFInflector::explode($tableClass);
- $table = FOFTable::getInstance($tableClassParts[2], ucfirst($tableClassParts[0]) . ucfirst($tableClassParts[1]));
- // Get the table name
- $tableName = $table->getTableName();
- // Get the remote and local key names
- $remoteKey = $relation['remoteKey'];
- $localKey = $relation['localKey'];
- // Get the local key's value
- $value = $this->table->$localKey;
- // This is required to prevent one relation from killing the db cursor used in a different relation...
- $oldDb = $this->table->getDbo();
- $oldDb->disconnect(); // YES, WE DO NEED TO DISCONNECT BEFORE WE CLONE THE DB OBJECT. ARGH!
- $db = clone $oldDb;
- $query = $db->getQuery(true)
- ->select('*')
- ->from($db->qn($tableName))
- ->where($db->qn($remoteKey) . ' = ' . $db->q($value));
- $db->setQuery($query, 0, 1);
- $data = $db->loadObject();
- if (!is_object($data))
- {
- throw new RuntimeException(sprintf('Cannot load item from relation against table %s column %s', $tableName, $remoteKey), 500);
- }
- $table->bind($data);
- return $table;
- }
- /**
- * Returns a FOFDatabaseIterator based on a given relation
- *
- * @param array $relation Relation definition
- *
- * @return FOFDatabaseIterator
- *
- * @throws RuntimeException
- */
- private function getIteratorFromRelation($relation)
- {
- // Get a table object from the table class name
- $tableClass = $relation['tableClass'];
- $tableClassParts = FOFInflector::explode($tableClass);
- $table = FOFTable::getInstance($tableClassParts[2], ucfirst($tableClassParts[0]) . ucfirst($tableClassParts[1]));
- // Get the table name
- $tableName = $table->getTableName();
- // Get the remote and local key names
- $remoteKey = $relation['remoteKey'];
- $localKey = $relation['localKey'];
- // Get the local key's value
- $value = $this->table->$localKey;
- // This is required to prevent one relation from killing the db cursor used in a different relation...
- $oldDb = $this->table->getDbo();
- $oldDb->disconnect(); // YES, WE DO NEED TO DISCONNECT BEFORE WE CLONE THE DB OBJECT. ARGH!
- $db = clone $oldDb;
- // Begin the query
- $query = $db->getQuery(true)
- ->select('*')
- ->from($db->qn($tableName));
- // Do we have a pivot table?
- $hasPivot = array_key_exists('pivotTable', $relation);
- // If we don't have pivot it's a straightforward query
- if (!$hasPivot)
- {
- $query
- ->where($db->qn($remoteKey) . ' = ' . $db->q($value));
- }
- // If we have a pivot table we have to do a subquery
- else
- {
- $subQuery = $db->getQuery(true)
- ->select($db->qn($relation['theirPivotKey']))
- ->from($db->qn($relation['pivotTable']))
- ->where($db->qn($relation['ourPivotKey']) . ' = ' . $db->q($value));
- $query->where($db->qn($remoteKey) . ' IN (' . $subQuery . ')');
- }
- $db->setQuery($query);
- $cursor = $db->execute();
- $iterator = FOFDatabaseIterator::getIterator($db->name, $cursor, null, $tableClass);
- return $iterator;
- }
- /**
- * Add any bespoke relation which doesn't involve a pivot table.
- *
- * @param string $relationType The type of the relationship (parent, child, children)
- * @param string $itemName is how it will be known locally to the getRelatedItems method
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: componentname_itemname_id
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param boolean $default is this the default children relationship?
- *
- * @return void
- */
- private function addBespokeSimpleRelation($relationType, $itemName, $tableClass, $localKey, $remoteKey, $default)
- {
- $ourPivotKey = null;
- $theirPivotKey = null;
- $pivotTable = null;
- $this->normaliseParameters(false, $itemName, $tableClass, $localKey, $remoteKey, $ourPivotKey, $theirPivotKey, $pivotTable);
- $this->relations[$relationType][$itemName] = array(
- 'tableClass' => $tableClass,
- 'localKey' => $localKey,
- 'remoteKey' => $remoteKey,
- );
- if ($default)
- {
- $this->defaultRelation[$relationType] = $itemName;
- }
- }
- /**
- * Add any bespoke relation which involves a pivot table.
- *
- * @param string $relationType The type of the relationship (multiple)
- * @param string $itemName is how it will be known locally to the getRelatedItems method
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: componentname_itemname_id
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param string $ourPivotKey is the column containing our side of the FK relation in the pivot table, default: $localKey
- * @param string $theirPivotKey is the column containing the other table's side of the FK relation in the pivot table, default $remoteKey
- * @param string $pivotTable is the name of the glue (pivot) table, default: #__componentname_thisclassname_itemname with plural items (e.g. #__foobar_users_roles)
- * @param boolean $default is this the default children relationship?
- *
- * @return void
- */
- private function addBespokePivotRelation($relationType, $itemName, $tableClass, $localKey, $remoteKey, $ourPivotKey, $theirPivotKey, $pivotTable, $default)
- {
- $this->normaliseParameters(true, $itemName, $tableClass, $localKey, $remoteKey, $ourPivotKey, $theirPivotKey, $pivotTable);
- $this->relations[$relationType][$itemName] = array(
- 'tableClass' => $tableClass,
- 'localKey' => $localKey,
- 'remoteKey' => $remoteKey,
- 'ourPivotKey' => $ourPivotKey,
- 'theirPivotKey' => $theirPivotKey,
- 'pivotTable' => $pivotTable,
- );
- if ($default)
- {
- $this->defaultRelation[$relationType] = $itemName;
- }
- }
- /**
- * Normalise the parameters of a relation, guessing missing values
- *
- * @param boolean $pivot Is this a many to many relation involving a pivot table?
- * @param string $itemName is how it will be known locally to the getRelatedItems method (plural)
- * @param string $tableClass if skipped it is defined automatically as ComponentnameTableItemname
- * @param string $localKey is the column containing our side of the FK relation, default: componentname_itemname_id
- * @param string $remoteKey is the remote table's FK column, default: componentname_itemname_id
- * @param string $ourPivotKey is the column containing our side of the FK relation in the pivot table, default: $localKey
- * @param string $theirPivotKey is the column containing the other table's side of the FK relation in the pivot table, default $remoteKey
- * @param string $pivotTable is the name of the glue (pivot) table, default: #__componentname_thisclassname_itemname with plural items (e.g. #__foobar_users_roles)
- *
- * @return void
- */
- private function normaliseParameters($pivot = false, &$itemName, &$tableClass, &$localKey, &$remoteKey, &$ourPivotKey, &$theirPivotKey, &$pivotTable)
- {
- // Get a default table class if none is provided
- if (empty($tableClass))
- {
- $tableClassParts = explode('_', $itemName, 3);
- if (count($tableClassParts) == 1)
- {
- array_unshift($tableClassParts, $this->componentName);
- }
- if ($tableClassParts[0] == 'joomla')
- {
- $tableClassParts[0] = 'J';
- }
- $tableClass = ucfirst($tableClassParts[0]) . 'Table' . ucfirst(FOFInflector::singularize($tableClassParts[1]));
- }
- // Make sure we have both a local and remote key
- if (empty($localKey) && empty($remoteKey))
- {
- $tableClassParts = FOFInflector::explode($tableClass);
- $localKey = $tableClassParts[0] . '_' . $tableClassParts[2] . '_id';
- $remoteKey = $localKey;
- }
- elseif (empty($localKey) && !empty($remoteKey))
- {
- $localKey = $remoteKey;
- }
- elseif (!empty($localKey) && empty($remoteKey))
- {
- $remoteKey = $localKey;
- }
- // If we don't have a pivot table nullify the relevant variables and return
- if (!$pivot)
- {
- $ourPivotKey = null;
- $theirPivotKey = null;
- $pivotTable = null;
- return;
- }
- if (empty($ourPivotKey))
- {
- $ourPivotKey = $localKey;
- }
- if (empty($theirPivotKey))
- {
- $theirPivotKey = $remoteKey;
- }
- if (empty($pivotTable))
- {
- $pivotTable = '#__' . strtolower($this->componentName) . '_' .
- strtolower(FOFInflector::pluralize($this->tableType)) . '_';
- $itemNameParts = explode('_', $itemName);
- $lastPart = array_pop($itemNameParts);
- $pivotTable .= strtolower($lastPart);
- }
- }
- /**
- * Normalises the format of a relation name
- *
- * @param string $itemName The raw relation name
- * @param boolean $pluralise Should I pluralise the name? If not, I will singularise it
- *
- * @return string The normalised relation key name
- */
- private function normaliseItemName($itemName, $pluralise = false)
- {
- // Explode the item name
- $itemNameParts = explode('_', $itemName);
- // If we have multiple parts the first part is considered to be the component name
- if (count($itemNameParts) > 1)
- {
- $prefix = array_shift($itemNameParts);
- }
- else
- {
- $prefix = null;
- }
- // If we still have multiple parts we need to pluralise/singularise the last part and join everything in
- // CamelCase format
- if (count($itemNameParts) > 1)
- {
- $name = array_pop($itemNameParts);
- $name = $pluralise ? FOFInflector::pluralize($name) : FOFInflector::singularize($name);
- $itemNameParts[] = $name;
- $itemName = FOFInflector::implode($itemNameParts);
- }
- // Otherwise we singularise/pluralise the remaining part
- else
- {
- $name = array_pop($itemNameParts);
- $itemName = $pluralise ? FOFInflector::pluralize($name) : FOFInflector::singularize($name);
- }
- if (!empty($prefix))
- {
- $itemName = $prefix . '_' . $itemName;
- }
- return $itemName;
- }
- }