Beispiel #1
0
 /**
  * Construct association object
  * 
  * @param   string  $assocName
  * @param   array   $options
  * @param   object  $model
  */
 public function __construct($assocName, $options, Mad_Model_Base $model)
 {
     $valid = array('className', 'foreignKey', 'primaryKey', 'include', 'order', 'dependent' => 'nullify');
     $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);
     $toClass = ucfirst($toMethod);
     $this->_methods = array($toMethod => 'getObject', $toMethod . '=' => 'setObject', 'build' . $toClass => 'buildObject', 'create' . $toClass => 'createObject');
 }
Beispiel #2
0
 /**
  * Pluralize the $singular word unless $count is one.  If $plural
  * form is not supplied, inflector will be used.
  *
  * @param  integer      $count      Count determines singular or plural
  * @param  string       $singular   Singular form
  * @param  string|null  $plural     Plural form (optional)
  */
 public function pluralize($count, $singular, $plural = null)
 {
     if ($count == '1') {
         $word = $singular;
     } else {
         if ($plural) {
             $word = $plural;
         } else {
             $word = Mad_Support_Inflector::pluralize($singular);
         }
     }
     return "{$count} {$word}";
 }
 /**
  * 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');
 }
Beispiel #4
0
 /**
  * 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');
 }
Beispiel #5
0
 /**
  * Given a status parameter, determine whether it needs to be converted
  * to a string. If it is an integer, use the $statusCodes hash to lookup
  * the default message. If it is a string, build $symbolToStatusCode
  * and convert it.  
  *
  *   interpret(404)         => "404 Not Found"
  *   interpret("notFound")  => "404 Not Found"
  *
  * Differences from Rails:
  *   - $status is camelized, not underscored.
  *   - an unknown status raises an exception
  *
  * @param  string|integer  Status code or "symbol"
  * @return string          Header
  */
 public static function interpret($status)
 {
     // Status from integer or numeric string
     if (is_numeric($status)) {
         if (isset(self::$statusCodes[$status])) {
             return "{$status} " . self::$statusCodes[$status];
         } else {
             $msg = "Unknown status code: {$status}";
             throw new InvalidArgumentException($msg);
         }
         // Status from string
     } else {
         if (is_string($status)) {
             // Build a string-to-integer lookup for converting a symbol (like
             // 'created' or 'notImplemented') into its corresponding HTTP status
             // code (like 200 or 501).
             static $symbolToStatusCode = array();
             if (empty($symbolToStatusCode)) {
                 foreach (self::$statusCodes as $code => $message) {
                     $symbol = Mad_Support_Inflector::camelize($message, $first = 'lower');
                     $symbolToStatusCode[$symbol] = $code;
                 }
             }
             // Convert status symbol to integer code, return header
             if (isset($symbolToStatusCode[$status])) {
                 return self::interpret($symbolToStatusCode[$status]);
             }
             // Error: Status symbol could not be converted to an integer code
             // Try to help if the developer mixed up underscore/camel
             $msg = "Unknown status: '{$status}'";
             if (strpos($status, '_')) {
                 $status = Mad_Support_Inflector::camelize($status, $first = 'lower');
                 if (isset($symbolToStatusCode[$status])) {
                     $msg .= " (underscore), did you mean '{$status}' (camel)?";
                 }
             }
             throw new InvalidArgumentException($msg);
             // Status is an unknown type
         } else {
             $msg = '$status must be numeric or string, got ' . gettype($status);
             throw new InvalidArgumentException($msg);
         }
     }
 }
Beispiel #6
0
 /**
  * Add associations specified via the <tt>:includes</tt> option.
  * Expects a block that takes as arguments:
  *   +association+ - name of the association
  *   +records+     - the association record(s) to be serialized
  *   +opts+        - options for the association records
  */
 public function addIncludes()
 {
     if (isset($this->_options['include'])) {
         $includeAssociations = (array) $this->_options['include'];
         unset($this->_options['include']);
     }
     if (empty($includeAssociations)) {
         return;
     }
     $baseOnlyOrExcept = array('except' => $this->_options['except'], 'only' => $this->_options['only']);
     // associative array includes have additional options
     $includeHasOptions = !is_int(key($includeAssociations));
     $associations = $includeHasOptions ? array_keys($includeAssociations) : $includeAssociations;
     // find records for each association
     foreach ($associations as $association) {
         $assoc = $this->_record->reflectOnAssociation($association);
         $type = $assoc->getMacro();
         $method = Mad_Support_Inflector::camelize($association, 'lower');
         if ($type == 'hasMany' || $type == 'hasAndBelongsToMany') {
             $records = $this->_record->{$method}()->getCollection();
         } elseif ($type == 'hasOne' || $type == 'belongsTo') {
             $records = $this->_record->{$method}();
         }
         if ($records === null) {
             continue;
         }
         // options
         if ($includeHasOptions) {
             $associationOptions = $includeAssociations[$association];
         } else {
             $associationOptions = $baseOnlyOrExcept;
         }
         // sub-records
         $opts = array_merge($this->_options, $associationOptions);
         $this->yieldRecords($association, $records, $opts);
     }
     $this->_options['include'] = $includeAssociations;
 }
Beispiel #7
0
 /**
  * Generate mailer class stubs
  */
 private function _generateMailerStubs()
 {
     $name = !empty($this->_args) ? array_shift($this->_args) : null;
     if (!$name) {
         $this->_exit("You did not specify the name of the Mailer to generate");
     }
     $name = str_replace('Mailer', '', $name);
     $mailerName = Mad_Support_Inflector::camelize($name) . 'Mailer';
     $this->_tpl->mailerName = $mailerName;
     $content = $this->_tpl->render('mailer.php');
     $this->_createFile(MAD_ROOT . "/app/models/{$mailerName}.php", $content);
     // CREATE DIRECTORIES
     $this->_createDir(MAD_ROOT . '/app/views/' . $mailerName);
 }
Beispiel #8
0
 /** 
  * Proxy to parent Mad_Support_ArrayObject#toXml, except that 
  * we know the explicit model type. 
  */
 public function toXml($options = array())
 {
     if (!isset($options['root'])) {
         $options['root'] = Mad_Support_Inflector::pluralize(get_class($this->_model));
     }
     return parent::toXml($options);
 }
Beispiel #9
0
 public function getJsonClassName()
 {
     return '"' . Mad_Support_Inflector::underscore($this->_className) . '"';
 }
Beispiel #10
0
 /**
  * Set the value for an attribute in this object.
  * 
  * @param   string  $name
  * @param   mixed   $value
  */
 protected function _setAttribute($name, $value)
 {
     // check for writer proxy method
     $underscore = Mad_Support_Inflector::underscore("set_{$name}");
     $methodName = Mad_Support_Inflector::camelize($underscore, 'lower');
     if (method_exists($this, $methodName)) {
         $this->{$methodName}($value);
     } else {
         $property = "_{$name}";
         if (property_exists($this, $property)) {
             $this->{$property} = $value;
         } else {
             $this->_attrValues[$name] = $value;
         }
     }
 }
Beispiel #11
0
 /**
  * @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)));
     }
 }
Beispiel #12
0
 /**
  * Actually return object, and not class
  *
  * @param   string  $migrationName
  * @param   int     $version
  * @return  Mad_Model_Migration_Base
  */
 protected function _getMigrationClass($migrationName, $version)
 {
     $className = Mad_Support_Inflector::camelize($migrationName);
     $migration = new $className();
     $migration->version = $version;
     return $migration;
 }
Beispiel #13
0
 public function testClearCache()
 {
     Mad_Support_Inflector::setCache('documents', 'singularize', 'document');
     Mad_Support_Inflector::clearCache();
     $this->assertEquals(false, Mad_Support_Inflector::getCache('documents', 'singularize'));
 }
Beispiel #14
0
 /**
  * Divine the controller name from the functional test name,
  * since the controller or request may not be available at
  * the time the URL needs to be generated.
  */
 protected function _getControllerNameFromTest()
 {
     $class = get_class($this);
     if (preg_match('/^(.*)ControllerTest$/', $class, $matches) == 0) {
         return null;
     }
     return Mad_Support_Inflector::underscore($matches[1]);
 }
Beispiel #15
0
 /**
  * Render a response that has no content (merely headers). The options
  * argument is interpreted to be a hash of header names and values.
  * This allows you to easily return a response that consists only of
  * significant headers:
  *
  *   head('created', array('location' => 'http://foo'))
  *   head(array('status' => 'created', 'location' => 'http://foo'))
  *
  * @param  integer|string|array  $first   Status code or options array
  * @param  array                 $second  Options array
  * @return void
  */
 protected function head($first, $second = array())
 {
     if (is_array($first)) {
         $options = $first;
         if (isset($options['status'])) {
             $status = $options['status'];
             unset($options['status']);
         } else {
             $status = 'ok';
         }
     } else {
         $status = $first;
         $options = $second;
     }
     $status = $this->interpretStatus($status);
     foreach ($options as $key => $value) {
         $dashed = Mad_Support_Inflector::dasherize($key);
         $spaced = str_replace('-', ' ', $dashed);
         $spaced = ucwords($spaced);
         $dashed = str_replace(' ', '-', $spaced);
         $this->_response->setHeader("{$dashed}: {$value}", $replace = true);
     }
     $this->_response->setStatus($status);
     $this->render(array('nothing' => true));
 }
Beispiel #16
0
 /**
  * Get the join table for hasAndBelongsToMany associations. Default to
  * tablename1_tablename2 by alpha (briefcases_documents)
  *
  * Example:
  * <code>
  * class Binder
  * ...
  *  $this->hasAndBelongsToMany('Documents');
  * ...
  *  // returns 'briefcases_documents' (by default)
  * </code>
  *
  * @return  string
  */
 public function getJoinTable()
 {
     if (!isset($this->_joinTable)) {
         $macro = $this->getMacro();
         // join table was given in options
         if (!empty($this->_options['joinTable'])) {
             $this->_joinTable = $this->_options['joinTable'];
             // join table from through association
         } elseif (!empty($this->_options['through'])) {
             $class = Mad_Support_Inflector::classify($this->_options['through']);
             $model = new $class();
             $this->_joinTable = $model->tableName();
             // determine table name by convention from DO data
         } elseif ($macro == 'hasAndBelongsToMany') {
             $tbls = array($this->_model->tableName(), $this->getAssocTable());
             sort($tbls);
             $this->_joinTable = implode('_', $tbls);
             // no join table
         } else {
             $this->_joinTable = null;
         }
     }
     return $this->_joinTable;
 }
Beispiel #17
0
 /**
  * Load fixture(s) data into the database.
  *
  * <code>
  *  <?php
  *  ...
  *  // single
  *  $this->fixtures('briefcases');
  *
  *  // multiple
  *  $this->fixtures(array('briefcases', 'md_metadata'));
  *
  *  // 'only' for given test methods
  *  $this->fixtures('briefcases', array('only' => array('testMethod1', 'testMethod2')));
  *
  *  // all test methods 'except' given
  *  $this->fixtures('briefcases', array('except' => array('testMethod1', 'testMethod2')));
  *  ...
  *  ?>
  * </code>
  *
  * @param   string|array $ymlFiles
  * @param   array        $options
  */
 public function fixtures($args)
 {
     $ymlFiles = func_get_args();
     $last = end($ymlFiles);
     $options = is_array($last) ? array_pop($ymlFiles) : array();
     // don't load fixtures for these methods
     if (isset($options['except'])) {
         if (in_array($this->getName(), $options['except'])) {
             return;
         }
     }
     // only load fixtures for these methods
     if (isset($options['only'])) {
         if (!in_array($this->getName(), $options['only'])) {
             return;
         }
     }
     // Add fixtures to the existing fixtures when called more than once
     if (empty($this->_fixtures)) {
         $this->_fixtures = new Mad_Test_Fixture_Collection($this->_conn, $ymlFiles);
     } else {
         $this->_fixtures->addFixture($ymlFiles);
     }
     // Build models from fixture records
     foreach ($this->_fixtures->getFixtures() as $fixture) {
         $name = $fixture->getYmlName();
         if (isset($this->_fixtureClassNames[$name])) {
             $class = $this->_fixtureClassNames[$name];
         } else {
             $table = $fixture->getTableName();
             $class = Mad_Support_Inflector::classify($table);
         }
         // skip building model if class doesn't exist
         if (!Mad_Support_Base::modelExists($class)) {
             break;
         }
         $model = new $class();
         $this->_records[$name] = array();
         foreach ($fixture->getRecords() as $recordName => $attrs) {
             $this->_records[$name][$recordName] = $model->instantiate($attrs);
         }
     }
     // @deprecated - assign public properties based on fixture names
     foreach ($this->_fixtures->getRecords() as $recordName => $values) {
         if (isset($this->{$recordName})) {
             $this->{$recordName} = array_merge($this->{$recordName}, $values);
         } else {
             $this->{$recordName} = $values;
         }
         // make all values strings
         foreach ($this->{$recordName} as &$value) {
             $value = (string) $value;
         }
     }
 }
Beispiel #18
0
 /**
  * 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();
 }
Beispiel #19
0
 /**                
  * Serialize the collection to XML.
  */
 public function toXml($options = array())
 {
     if (!isset($options['root'])) {
         $options['root'] = Mad_Support_Inflector::pluralize(get_class($this->_model));
     }
     $conversion = new Mad_Support_ArrayConversion();
     return $conversion->toXml($this, $options);
 }
Beispiel #20
0
 /**
  * Stale the cache of inflection data
  */
 public static function clearCache()
 {
     self::$_inflections = array();
 }
Beispiel #21
0
 public function humanAttributeName($attr)
 {
     $attr = Mad_Support_Inflector::underscore($attr);
     return ucfirst(str_replace('_', ' ', $attr));
 }
Beispiel #22
0
 /**
  * Take the $matchdata returned by a Horde_Routes_Mapper match and add
  * in :controller and :action that are used by the rest of the framework.
  * 
  * Format controller names: my_stuff => MyStuffController
  * Format action names:     action_name => actionName
  * 
  * @param   array   $matchdata
  * @return  mixed   false | array
  */
 public function formatMatchdata($matchdata)
 {
     $ret = array();
     foreach ($matchdata as $key => $val) {
         if ($key == 'controller') {
             $ret['controller'] = $val;
             $ret[':controller'] = Mad_Support_Inflector::camelize($val) . 'Controller';
         } elseif ($key == 'action') {
             // Horde_Routes_Mapper->resource() and Python Routes are inconsistent
             // with Rails by using "delete" instead of "destroy".
             if ($val == 'delete') {
                 $val = 'destroy';
             }
             $ret['action'] = $val;
             $ret[':action'] = Mad_Support_Inflector::camelize($val, 'lower');
         } else {
             $ret[$key] = $val;
         }
     }
     return !empty($ret) && isset($ret['controller']) ? $ret : false;
 }
Beispiel #23
0
 /**
  * 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;
 }
Beispiel #24
0
 /**
  * Construct association object - simple factory
  * @param   string  $macro (format|length|numericality|presence|uniqueness)
  * @param   string  $attributes
  * @param   array   $options
  */
 public static function factory($macro, $attribute, $options)
 {
     $className = "Mad_Model_Validation_" . Mad_Support_Inflector::camelize($macro);
     return new $className($attribute, $options);
 }
Beispiel #25
0
 /**
  * Initialize the default helpers for use in the views
  */
 private function _initViewHelpers()
 {
     $controllerHelper = Mad_Support_Inflector::classify($this->_shortName . 'Helper');
     $this->_view->addHelper(new $controllerHelper($this->_view));
 }