function doActivityOnProcessFindList() { $mapper =& Piece_ORM::getMapper('Entry'); if (Piece_ORM_Error::hasErrors('exception')) { return; } $this->_entries = $mapper->findAll(); return 'DisplayListFromProcessFindList'; }
function doActivityOnProcessCreateNew() { $mapper =& Piece_ORM::getMapper('Entry'); if (Piece_ORM_Error::hasErrors('exception')) { return; } $mapper->insert($this->_entry); return 'DisplayNewFinishFromProcessCreateNew'; }
/** * Normalizes "through" definition. * * @throws PIECE_ORM_ERROR_INVALID_CONFIGURATION */ function _normalizeThrough() { if (!array_key_exists('through', $this->_relationship)) { $this->_relationship['through'] = array(); } if (!array_key_exists('table', $this->_relationship['through'])) { $throughTableName1 = $this->_metadata->getTableName(true) . "_{$this->_relationship['table']}"; $throughTableName2 = "{$this->_relationship['table']}_" . $this->_metadata->getTableName(true); foreach (array($throughTableName1, $throughTableName2) as $throughTableName) { Piece_ORM_Error::disableCallback(); $throughMetadata =& Piece_ORM_Metadata_Factory::factory($throughTableName); Piece_ORM_Error::enableCallback(); if (Piece_ORM_Error::hasErrors()) { $error = Piece_ORM_Error::pop(); if ($error['code'] != PIECE_ORM_ERROR_NOT_FOUND) { Piece_ORM_Error::push($error['code'], $error['message'], 'exception', array(), $error); return; } continue; } $this->_relationship['through']['table'] = $throughTableName; break; } if (!$throughMetadata) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "One of [ {$throughTableName1} ] or [ {$throughTableName2} ] must exists in the database, if the element [ table ] in the element [ through ] omit."); return; } } $throughMetadata =& Piece_ORM_Metadata_Factory::factory($this->_relationship['through']['table']); if (Piece_ORM_Error::hasErrors()) { return; } if (!array_key_exists('column', $this->_relationship['through'])) { if ($primaryKey = $this->_metadata->getPrimaryKey()) { $this->_relationship['through']['column'] = $this->_metadata->getTableName(true) . "_{$primaryKey}"; } else { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'A single primary key field is required, if the element [ column ] in the element [ through ] omit.'); return; } } if (!$throughMetadata->hasField($this->_relationship['through']['column'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "The field [ {$this->_relationship['through']['column']} ] not found in the table [ " . $throughMetadata->getTableName(true) . ' ].'); return; } if (!array_key_exists('referencedColumn', $this->_relationship['through'])) { if ($primaryKey = $this->_metadata->getPrimaryKey()) { $this->_relationship['through']['referencedColumn'] = $primaryKey; } else { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'A single primary key field is required, if the element [ referencedColumn ] in the element [ through ] omit.'); return; } } if (!$this->_metadata->hasField($this->_relationship['through']['referencedColumn'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "The field [ {$this->_relationship['through']['referencedColumn']} ] not found in the table [ " . $this->_metadata->getTableName(true) . ' ].'); return; } if (!array_key_exists('inverseColumn', $this->_relationship['through'])) { if ($primaryKey = $this->_relationshipMetadata->getPrimaryKey()) { $this->_relationship['through']['inverseColumn'] = $this->_relationshipMetadata->getTableName(true) . "_{$primaryKey}"; } else { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'A single primary key field is required, if the element [ column ] in the element [ through ] omit.'); return; } } if (!$throughMetadata->hasField($this->_relationship['through']['inverseColumn'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "The field [ {$this->_relationship['through']['inverseColumn']} ] not found in the table [ " . $throughMetadata->getTableName(true) . ' ].'); return; } }
/** * Loads a mapper class based on the given information. * * @param string $mapperID * @param string $mapperName * @throws PIECE_ORM_ERROR_INVALID_OPERATION * @throws PIECE_ORM_ERROR_NOT_FOUND * @throws PIECE_ORM_ERROR_NOT_READABLE */ function _load($mapperID, $mapperName) { if (Piece_ORM_Mapper_Factory::_loaded($mapperID)) { return; } if (is_null($GLOBALS['PIECE_ORM_Mapper_ConfigDirectory'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_OPERATION, 'The configuration directory must be specified.'); return; } if (!file_exists($GLOBALS['PIECE_ORM_Mapper_ConfigDirectory'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, "The configuration directory [ {$GLOBALS['PIECE_ORM_Mapper_ConfigDirectory']} ] not found."); return; } if (is_null($GLOBALS['PIECE_ORM_Mapper_CacheDirectory'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_OPERATION, 'The cache directory must be specified.'); return; } if (!file_exists($GLOBALS['PIECE_ORM_Mapper_CacheDirectory'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, "The cache directory [ {$GLOBALS['PIECE_ORM_Mapper_CacheDirectory']} ] not found."); return; } if (!is_readable($GLOBALS['PIECE_ORM_Mapper_CacheDirectory']) || !is_writable($GLOBALS['PIECE_ORM_Mapper_CacheDirectory'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_READABLE, "The cache directory [ {$GLOBALS['PIECE_ORM_Mapper_CacheDirectory']} ] is not readable or writable."); return; } $configFile = "{$GLOBALS['PIECE_ORM_Mapper_ConfigDirectory']}/{$mapperName}.yaml"; if (!file_exists($configFile)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, "The configuration file [ {$configFile} ] not found."); return; } if (!is_readable($configFile)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_READABLE, "The configuration file [ {$configFile} ] is not readable."); return; } $mapperSource = Piece_ORM_Mapper_Factory::_getMapperSource($mapperID, $mapperName, $configFile); if (Piece_ORM_Error::hasErrors()) { return; } eval($mapperSource); if (!Piece_ORM_Mapper_Factory::_loaded($mapperID)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, "The mapper [ {$mapperName} ] not found."); } }
/** * Adds a findOneXXX method and its query to the mapper source. * * @param string $methodName * @param string $query * @param string $orderBy * @throws PIECE_ORM_ERROR_INVALID_CONFIGURATION */ function _addFindOne($methodName, $query, $orderBy) { if (!$query) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'The element [ query ] or its value is required to generate a findOne method declaration.'); return; } $propertyName = strtolower($methodName); $this->_propertyDefinitions['query'][$propertyName] = $this->_generateQueryPropertyDeclaration($propertyName, $query); $this->_propertyDefinitions['orderBy'][$propertyName] = $this->_generateOrderByPropertyDeclaration($propertyName, $orderBy); $this->_methodDefinitions[strtolower($methodName)] = "\n function {$methodName}(\$criteria = null)\n {\n return \$this->_findOne('{$methodName}', \$criteria);\n }"; }
/** * Removes associated objects from a table. * * @param array $relationship */ function delete($relationship) { if (!array_key_exists($relationship['mappedAs'], $this->_subject)) { return; } if (!is_null($this->_subject->{$relationship}['mappedAs']) && !is_object($this->_subject->{$relationship}['mappedAs'])) { return; } $mapper =& Piece_ORM_Mapper_Factory::factory($relationship['table']); if (Piece_ORM_Error::hasErrors()) { return; } $mapper->delete($this->_subject->{$relationship}['mappedAs']); }
/** * Loads a value with a result object. * * @param MDB2_Result &$result * @return string * @throws PIECE_ORM_ERROR_CANNOT_INVOKE * @since Method available since Release 0.3.0 */ function _loadValue(&$result) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $value = $result->fetchOne(); PEAR::staticPopErrorHandling(); if (MDB2::isError($value)) { Piece_ORM_Error::pushPEARError($value, PIECE_ORM_ERROR_CANNOT_INVOKE, "Failed to invoke MDB2_Driver_{$this->_dbh->phptype}::fetchOne() for any reasons."); return; } return $value; }
/** * Removes associated objects from a table. * * @param array $relationship * @throws PIECE_ORM_ERROR_INVALID_CONFIGURATION */ function delete($relationship) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "This operation does not supported for the relationship type [ {$relationship['type']} ]. Please check your configuration."); }
/** * Gets the database handle for the current database. * * @return MDB2_Driver_Common * @throws PIECE_ORM_ERROR_CANNOT_INVOKE */ function &getConnection() { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $dbh =& MDB2::singleton($this->getDSN(), $this->getOptions()); PEAR::staticPopErrorHandling(); if (MDB2::isError($dbh)) { Piece_ORM_Error::pushPEARError($dbh, PIECE_ORM_ERROR_CANNOT_INVOKE, 'Failed to invoke MDB2::singleton() for any reasons.'); $return = null; return $return; } $dbh->setFetchMode(MDB2_FETCHMODE_ASSOC); $nativeTypeMapperClass = 'Piece_ORM_MDB2_NativeTypeMapper_' . ucwords(strtolower(substr(strrchr(get_class($dbh), '_'), 1))); include_once str_replace('_', '/', $nativeTypeMapperClass) . '.php'; $nativeTypeMapper =& new $nativeTypeMapperClass(); $nativeTypeMapper->mapNativeType($dbh); if ($this->getUseMapperNameAsTableName()) { if ($dbh->phptype == 'pgsql') { $dbh->options['quote_identifier'] = true; $dbh->options['portability'] &= ~MDB2_PORTABILITY_FIX_CASE; } elseif ($dbh->phptype == 'mysql') { $dbh->options['portability'] |= MDB2_PORTABILITY_FIX_CASE; $dbh->options['field_case'] = CASE_LOWER; } elseif ($dbh->phptype == 'mssql') { $dbh->options['portability'] |= MDB2_PORTABILITY_FIX_CASE; $dbh->options['field_case'] = CASE_LOWER; } } return $dbh; }
/** * Loads all associated objects into appropriate objects. * * @param Piece_ORM_Mapper_Common &$mapper * @param integer $relationshipIndex */ function loadAll(&$mapper, $relationshipIndex) { $mapper->setPreloadCallback($this->_getPreloadCallback()); $mapper->setPreloadCallbackArgs(array($relationshipIndex)); $associatedObjects = $mapper->findAllWithQuery($this->_buildQuery($relationshipIndex) . (is_null($this->_relationships[$relationshipIndex]['orderBy']) ? '' : " ORDER BY {$this->_relationships[$relationshipIndex]['orderBy']}")); $mapper->setPreloadCallback(null); $mapper->setPreloadCallbackArgs(null); if (Piece_ORM_Error::hasErrors()) { return; } $relationshipKeyPropertyName = Piece_ORM_Inflector::camelize($this->_getRelationshipKeyFieldNameInSecondaryQuery($this->_relationships[$relationshipIndex]), true); for ($j = 0, $count = count($associatedObjects); $j < $count; ++$j) { $this->_associateObject($associatedObjects[$j], $mapper, $relationshipKeyPropertyName, $relationshipIndex); } }
/** * Creates a Piece_ORM_Metadata object from a database. * * @param string $tableName * @return Piece_ORM_Metadata * @throws PIECE_ORM_ERROR_CANNOT_INVOKE * @throws PIECE_ORM_ERROR_NOT_FOUND */ function &_createMetadataFromDatabase($tableName) { $context =& Piece_ORM_Context::singleton(); $dbh =& $context->getConnection(); if (Piece_ORM_Error::hasErrors()) { $return = null; return $return; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $result = $dbh->setLimit(1); PEAR::staticPopErrorHandling(); if (MDB2::isError($result)) { Piece_ORM_Error::pushPEARError($result, PIECE_ORM_ERROR_CANNOT_INVOKE, "Failed to invoke MDB2_Driver_{$dbh->phptype}::setLimit() for any reasons."); $return = null; return $return; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $result = $dbh->query('SELECT 1 FROM ' . $dbh->quoteIdentifier($tableName)); PEAR::staticPopErrorHandling(); if (MDB2::isError($result)) { if ($result->getCode() != MDB2_ERROR_NOSUCHTABLE) { Piece_ORM_Error::pushPEARError($result, PIECE_ORM_ERROR_CANNOT_INVOKE, "Failed to invoke MDB2_Driver_{$dbh->phptype}::query() for any reasons."); $return = null; return $return; } Piece_ORM_Error::pushPEARError($result, PIECE_ORM_ERROR_NOT_FOUND, "Failed to invoke MDB2_Driver_{$dbh->phptype}::query() for any reasons."); $return = null; return $return; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $reverse =& $dbh->loadModule('Reverse'); PEAR::staticPopErrorHandling(); if (MDB2::isError($reverse)) { Piece_ORM_Error::pushPEARError($reverse, PIECE_ORM_ERROR_CANNOT_INVOKE, 'Failed to invoke $dbh->loadModule() for any reasons.'); $return = null; return $return; } if ($dbh->phptype == 'mssql') { include_once 'Piece/ORM/MDB2/Decorator/Reverse/Mssql.php'; $reverse =& new Piece_ORM_MDB2_Decorator_Reverse_Mssql($reverse); } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $tableInfo = $reverse->tableInfo($tableName); PEAR::staticPopErrorHandling(); if (MDB2::isError($tableInfo)) { Piece_ORM_Error::pushPEARError($tableInfo, PIECE_ORM_ERROR_CANNOT_INVOKE, 'Failed to invoke $reverse->tableInfo() for any reasons.'); $return = null; return $return; } if ($dbh->phptype == 'mysql') { foreach (array_keys($tableInfo) as $fieldName) { if ($tableInfo[$fieldName]['nativetype'] == 'datetime' && $tableInfo[$fieldName]['notnull'] && $tableInfo[$fieldName]['default'] == '0000-00-00 00:00:00') { $tableInfo[$fieldName]['flags'] = str_replace('default_0000-00-00%2000%3A00%3A00', '', $tableInfo[$fieldName]['flags']); $tableInfo[$fieldName]['default'] = ''; } } } $metadata =& new Piece_ORM_Metadata($tableInfo); return $metadata; }
/** * Loads associated objects into appropriate objects. */ function _loadAssociatedObjects() { for ($i = 0, $count = count($this->_relationships); $i < $count; ++$i) { $mapper =& Piece_ORM_Mapper_Factory::factory($this->_relationships[$i]['table']); if (Piece_ORM_Error::hasErrors()) { return; } $this->_associatedObjectLoaders[$this->_relationships[$i]['type']]->loadAll($mapper, $i); if (Piece_ORM_Error::hasErrors()) { return; } } }
function doActivityOnProcessDelete() { $mapper =& Piece_ORM::getMapper('Entry'); if (Piece_ORM_Error::hasErrors('exception')) { return; } $affectedRows = $mapper->delete($this->_entry); if ($affectedRows) { return 'DisplayDeleteFinishFromProcessDelete'; } else { return 'DisplayErrorFromProcessDelete'; } }
/** * Creates an object from the metadata. * * @param string $mapperName * @return stdClass * @throws PIECE_ORM_ERROR_INVALID_OPERATION */ function &createObject($mapperName) { if (!$GLOBALS['PIECE_ORM_Configured']) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_OPERATION, __FUNCTION__ . ' method must be called after calling configure().'); $return = null; return $return; } $mapper =& Piece_ORM_Mapper_Factory::factory($mapperName); if (Piece_ORM_Error::hasErrors()) { $return = null; return $return; } return $mapper->createObject(); }
/** * Normalizes a relationship definition. * * @return array * @throws PIECE_ORM_ERROR_INVALID_CONFIGURATION * @throws PIECE_ORM_ERROR_NOT_FOUND */ function normalize() { if (!array_key_exists('table', $this->_relationship)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'The element [ table ] is required to generate a relationship property declaration.'); return; } if (!array_key_exists('mappedAs', $this->_relationship)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'The element [ mappedAs ] is required to generate a relationship property declaration.'); return; } $this->_relationshipMetadata =& Piece_ORM_Metadata_Factory::factory($this->_relationship['table']); if (Piece_ORM_Error::hasErrors()) { return; } if ($this->_checkHavingSinglePrimaryKey()) { if (!$this->_relationshipMetadata->getPrimaryKey()) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, 'A single primary key field is required in the table [ ' . $this->_relationshipMetadata->getTableName(true) . ' ].'); return; } } if (!array_key_exists('column', $this->_relationship)) { if (!$this->_normalizeColumn()) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'A single primary key field is required, if the element [ column ] in the element [ relationship ] omit.'); return; } } if (!$this->_relationshipMetadata->hasField($this->_relationship['column'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "The field [ {$this->_relationship['column']} ] not found in the table [ " . $this->_relationshipMetadata->getTableName(true) . ' ].'); return; } if (!array_key_exists('referencedColumn', $this->_relationship)) { if (!$this->_normalizeReferencedColumn()) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, 'A single primary key field is required, if the element [ referencedColumn ] in the element [ relationship ] omit.'); return; } } if ($this->_referencedColumnRequired && !$this->_metadata->hasField($this->_relationship['referencedColumn'])) { Piece_ORM_Error::push(PIECE_ORM_ERROR_INVALID_CONFIGURATION, "The field [ {$this->_relationship['referencedColumn']} ] not found in the table [ " . $this->_metadata->getTableName(true) . ' ].'); return; } if (!array_key_exists('orderBy', $this->_relationship)) { $this->_relationship['orderBy'] = null; } $this->_normalizeOrderBy(); $this->_normalizeThrough(); if (Piece_ORM_Error::hasErrors()) { return; } return $this->_relationship; }
/** * Enables the last callback. * * @since Method available since Release 1.1.0 */ function enableCallback() { Piece_ORM_Error::popCallback(); }
/** * Loads the LOB data of this field. * * @return string * @throws PIECE_ORM_ERROR_CANNOT_INVOKE * @throws PIECE_ORM_ERROR_UNEXPECTED_VALUE */ function load() { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $datatype =& $this->_dbh->loadModule('Datatype'); PEAR::staticPopErrorHandling(); if (MDB2::isError($datatype)) { Piece_ORM_Error::pushPEARError($datatype, PIECE_ORM_ERROR_CANNOT_INVOKE, 'Failed to invoke $dbh->loadModule() for any reasons.'); return; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $lob = $datatype->convertResult($this->_value, $this->_metadata->getDatatype($this->_fieldName)); PEAR::staticPopErrorHandling(); if (MDB2::isError($lob)) { Piece_ORM_Error::pushPEARError($lob, PIECE_ORM_ERROR_CANNOT_INVOKE, 'Failed to invoke $datatype->convertResult() for any reasons.'); return; } if (!is_resource($lob)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_UNEXPECTED_VALUE, 'An unexpected value detected. $datatype->convertResult() should return a resource.'); return; } $data = ''; while (!feof($lob)) { $data .= fread($lob, 8192); } $datatype->destroyLOB($lob); return $data; }
/** * Executes a query with the given criteria. * * @param string $methodName * @param stdClass $criteria * @return MDB2_Result_Common|integer */ function &executeWithCriteria($methodName, $criteria) { $queryBuilder =& new Piece_ORM_Mapper_QueryBuilder($this->_mapper, $methodName, $criteria, $this->_isManip); list($query, $sth) = $queryBuilder->build(); if (Piece_ORM_Error::hasErrors()) { $return = null; return $return; } $result =& $this->execute($query, $sth); if (Piece_ORM_Error::hasErrors()) { $return = null; return $return; } return $result; }
/** * Returns the value of an ID field if a table has an ID field. * * @return integer * @throws PIECE_ORM_ERROR_CANNOT_INVOKE * @since Method available since Release 1.1.0 */ function _getLastInsertID() { if ($this->_metadata->hasID()) { $dbh =& $this->_mapper->getConnection(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $id = $dbh->lastInsertID($this->_metadata->getTableName(true), $this->_metadata->getPrimaryKey()); PEAR::staticPopErrorHandling(); if (MDB2::isError($id)) { Piece_ORM_Error::pushPEARError($id, PIECE_ORM_ERROR_CANNOT_INVOKE, "Failed to invoke MDB2_Driver_{$this->_dbh->phptype}::lastInsertID() for any reasons."); return; } return $id; } }
/** * Creates a Piece_ORM_Config object from a configuration file or * a cache. * * @param string $configDirectory * @param string $cacheDirectory * @return Piece_ORM_Config * @static */ function &factory($configDirectory = null, $cacheDirectory = null) { if (is_null($configDirectory)) { $config =& new Piece_ORM_Config(); return $config; } if (!file_exists($configDirectory)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, "The configuration directory [ {$configDirectory} ] not found."); $return = null; return $return; } $configFile = "{$configDirectory}/piece-orm-config.yaml"; if (!file_exists($configFile)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_FOUND, "The configuration file [ {$configFile} ] not found."); $return = null; return $return; } if (!is_readable($configFile)) { Piece_ORM_Error::push(PIECE_ORM_ERROR_NOT_READABLE, "The configuration file [ {$configFile} ] is not readable."); $return = null; return $return; } if (is_null($cacheDirectory)) { return Piece_ORM_Config_Factory::_createConfigurationFromFile($configFile); } if (!file_exists($cacheDirectory)) { trigger_error("The cache directory [ {$cacheDirectory} ] is not found.", E_USER_WARNING); return Piece_ORM_Config_Factory::_createConfigurationFromFile($configFile); } if (!is_readable($cacheDirectory) || !is_writable($cacheDirectory)) { trigger_error("The cache directory [ {$cacheDirectory} ] is not readable or writable.", E_USER_WARNING); return Piece_ORM_Config_Factory::_createConfigurationFromFile($configFile); } return Piece_ORM_Config_Factory::_getConfiguration($configFile, $cacheDirectory); }
/** * Removes associated objects from a table. * * @param array $relationship */ function delete($relationship) { $property = Piece_ORM_Inflector::camelize($relationship['through']['referencedColumn'], true); if (!array_key_exists($property, $this->_subject)) { return; } $mapper =& Piece_ORM_Mapper_Factory::factory($relationship['through']['table']); if (Piece_ORM_Error::hasErrors()) { return; } $mapper->executeQuery("DELETE FROM {$relationship['through']['table']} WHERE {$relationship['through']['column']} = " . $mapper->quote($this->_subject->{$property}, $relationship['through']['column']), true); }