/** * Construct association object * * @param string $assocName * @param array $options * @param object $model */ public function __construct($assocName, $options, Mad_Model_Base $model) { $valid = array('className', 'conditions', 'order', 'foreignKey', 'primaryKey', 'associationForeignKey', 'associationPrimaryKey', 'joinTable', 'uniq', 'include', 'finderSql', 'deleteSql', 'insertSql'); $this->_options = Mad_Support_Base::assertValidKeys($options, $valid); $this->_assocName = $assocName; $this->_model = $model; $this->_conn = $model->connection(); // get inflections $toMethod = Mad_Support_Inflector::camelize($this->_assocName, 'lower'); $toMethod = str_replace('/', '_', $toMethod); $singular = Mad_Support_Inflector::singularize($toMethod); $toClass = ucfirst($singular); $this->_methods = array($toMethod => 'getObjects', $toMethod . '=' => 'setObjects', $singular . 'Ids' => 'getObjectIds', $singular . 'Ids=' => 'setObjectIds', $singular . 'Count' => 'getObjectCount', 'add' . $toClass => 'addObject', Mad_Support_Inflector::pluralize('replace' . $toClass) => 'replaceObjects', Mad_Support_Inflector::pluralize('delete' . $toClass) => 'deleteObjects', Mad_Support_Inflector::pluralize('clear' . $toClass) => 'clearObjects', Mad_Support_Inflector::pluralize('find' . $toClass) => 'findObjects'); }
/** * Construct association object * * @param string $assocName * @param array $options */ public function __construct($assocName, $options, Mad_Model_Base $model) { $valid = array('className', 'foreignKey', 'associationForeignKey', 'primaryKey', 'associationPrimaryKey', 'include', 'select', 'conditions', 'order', 'finderSql', 'through', 'dependent' => 'nullify'); $this->_options = Mad_Support_Base::assertValidKeys($options, $valid); $this->_assocName = $assocName; $this->_model = $model; $this->_conn = $model->connection(); // throw fatal error if through option is invalid $this->_throughClass = Mad_Support_Inflector::classify($this->_options['through']); class_exists($this->_throughClass); // get inflections $toMethod = Mad_Support_Inflector::camelize($this->_assocName, 'lower'); $toMethod = str_replace('/', '_', $toMethod); $singular = Mad_Support_Inflector::singularize($toMethod); $toClass = ucfirst($singular); $this->_methods = array($toMethod => 'getObjects', $singular . 'Ids' => 'getObjectIds', $singular . 'Count' => 'getObjectCount', 'add' . $toClass => 'addObject', Mad_Support_Inflector::pluralize('delete' . $toClass) => 'deleteObjects', Mad_Support_Inflector::pluralize('clear' . $toClass) => 'clearObjects', Mad_Support_Inflector::pluralize('find' . $toClass) => 'findObjects'); }
/** * Convert array collection to XML * @param array $array * @param array $options */ public function arrayToXml($array, $options = array()) { $firstElt = current($array); $firstType = is_object($firstElt) ? get_class($firstElt) : gettype($firstElt); $sameTypes = true; foreach ($array as $element) { // either an array or object with toXml method if (!is_array($element) && !is_callable(array($element, 'toXml'))) { throw new Mad_Support_Exception("Not all elements respond to toXml"); } if (get_class($element) != $firstType) { $sameTypes = false; } } if (!isset($options['root'])) { if ($sameTypes && count($array) > 0) { $options['root'] = Mad_Support_Inflector::pluralize($firstType); } else { $options['root'] = 'records'; } } if (!isset($options['children'])) { $options['children'] = Mad_Support_Inflector::singularize($options['root']); } if (!isset($options['indent'])) { $options['indent'] = 2; } if (!isset($options['skipTypes'])) { $options['skipTypes'] = false; } if (empty($options['builder'])) { $options['builder'] = new Mad_Support_Builder(array('indent' => $options['indent'])); } $root = $options['root']; unset($options['root']); $children = $options['children']; unset($options['children']); if (!array_key_exists('dasherize', $options) || !empty($options['dasherize'])) { $root = Mad_Support_Inflector::dasherize($root); } if (empty($options['skipInstruct'])) { $options['builder']->instruct(); } $opts = array_merge($options, array('root' => $children)); $builder = $options['builder']; $attrs = $options['skipTypes'] ? array() : array('type' => 'array'); // no elements in array if (count($array) == 0) { $builder->tag($root, '', $attrs); // build xml from elements } else { $tag = $builder->startTag($root, '', $attrs); $opts['skipInstruct'] = true; foreach ($array as $element) { // associative array if (is_array($element) && !is_int(key($element))) { $this->hashToXml($element, $opts); // array } elseif (is_array($element)) { $this->arrayToXml($element, $opts); // object } else { $element->toXml($opts); } } $tag->end(); } return $builder->__toString(); }
/** * The foreign key name for the join table in an association. This is determined * automatically by the data object if not given in options. * * Example: * <code> * $this->hasAndBelongsToMany('Documents', array('associationForeignKey' => 'documentid')); * // returns 'documentid' * </code> * * @return string */ public function getAssocFkName() { if (!isset($this->_assocFkName)) { // key was given in options if (!empty($this->_options['associationForeignKey'])) { $this->_assocFkName = $this->_options['associationForeignKey']; } else { $table = $this->getAssocModel()->tableName(); $singularTable = Mad_Support_Inflector::singularize($table); $this->_assocFkName = "{$singularTable}_id"; } } return $this->_assocFkName; }
/** * Construct associations for model from record/row * * @param object $record * @param object $join * @param array $row */ protected function _constructAssociation(Mad_Model_Base $record, Mad_Model_Join_Base $join, $row) { // set that we've loaded this association $record->setAssociationLoaded($join->reflection()->getAssocName()); if ($record->id != $join->parent()->recordId($row) || empty($row[$join->aliasedPrimaryKey()])) { return; } $association = $join->instantiate($row); $macro = $join->reflection()->getMacro(); $singular = Mad_Support_Inflector::singularize($join->reflection()->getAssocName()); if ($macro == 'hasAndBelongsToMany' || $macro == 'hasMany' || $macro == 'hasManyThrough') { $addMethod = Mad_Support_Inflector::camelize('add' . ucfirst($singular), 'lower'); $addMethod = str_replace('/', '_', $addMethod); // make sure object isn't already included $getter = Mad_Support_Inflector::camelize($join->reflection()->getAssocName(), 'lower'); $getter = str_replace('/', '_', $getter); $exists = array(); foreach ($record->{$getter} as $val) { $exists[] = $val->id; } if (!in_array($association->id, $exists)) { $record->{$addMethod}($association); } } elseif ($macro == 'belongsTo' || $macro == 'hasOne') { $assignMethod = Mad_Support_Inflector::camelize($singular, 'lower'); $record->{$assignMethod} = $association; } return $association; }
/** * @param string $association * @param mixed $records * @param array $opts */ public function addAssociations($association, $records, $opts) { // association collection if (is_array($records)) { $name = $this->dasherize($association); if (empty($records)) { $this->getBuilder()->tag($name, '', array('type' => 'array')); } else { $tag = $this->getBuilder()->startTag($name, '', array('type' => 'array')); $associationName = Mad_Support_Inflector::singularize($association); foreach ($records as $record) { $type = get_class($record) == $associationName ? null : get_class($record); $options = array_merge($opts, array('root' => $associationName, 'type' => $type)); $record->toXml($options); } $tag->end(); } // single association } else { $records->toXml(array_merge($opts, array('root' => $association))); } }
public function testSingularize() { $this->assertEquals('briefcase', Mad_Support_Inflector::singularize('briefcases')); $this->assertEquals('category', Mad_Support_Inflector::singularize('categories')); }