Ejemplo n.º 1
0
 /**
  * Constructs the PostgreSQL adapter and sets the default port to 5432.
  *
  * @param array $config Configuration options for this class. Available options
  *                      defined by this class:
  *                      - `'host'`    : _string_ The IP or machine name where PostgreSQL is running,
  *                                      followed by a colon, followed by a port number or socket.
  *                                      Defaults to `'localhost:5432'`.
  *                      - `'schema'`  : _string_ The name of the database schema to use. Defaults to 'public'
  *                      - `'timezone'`: _stirng_ The database timezone. Defaults to `null`.
  */
 public function __construct($config = [])
 {
     $defaults = ['host' => 'localhost:5432', 'schema' => 'public', 'timezone' => null, 'classes' => ['dialect' => 'sql\\dialect\\PostgreSql'], 'handlers' => ['cast' => ['boolean' => function ($value, $options = []) {
         return $value === 't';
     }], 'datasource' => ['boolean' => function ($value, $options = []) {
         return $value ? 'true' : 'false';
     }, 'array' => function ($data) {
         $data = (array) $data;
         $result = [];
         foreach ($data as $value) {
             if (is_array($value)) {
                 $result[] = $this->_handlers['datasource']['array']($value);
             } else {
                 $value = str_replace('"', '\\"', $value);
                 if (!is_numeric($value)) {
                     $value = '"' . $value . '"';
                 }
                 $result[] = $value;
             }
         }
         return '{' . join(",", $result) . '}';
     }]]];
     $config = Set::merge($defaults, $config);
     parent::__construct($config + $defaults);
     $this->formatter('datasource', 'array', $this->_handlers['datasource']['array']);
 }
Ejemplo n.º 2
0
 /**
  * Configures the schema class.
  *
  * @param array $config Possible options are:
  *                      - `'conventions'` _array_: Allow to override the default convention rules for generating
  *                                                 primary or foreign key as well as for table/collection names
  *                                                 from an entity class name.
  */
 public function config($config = [])
 {
     $defaults = ['conventions' => ['source' => function ($class) {
         $basename = substr(strrchr($class, '\\'), 1);
         return Inflector::underscore($basename);
     }, 'primaryKey' => function () {
         return 'id';
     }, 'foreignKey' => function ($class) {
         $pos = strrpos($class, '\\');
         $basename = substr($class, $pos !== false ? $pos + 1 : 0);
         return Inflector::underscore(Inflector::singularize($basename)) . '_id';
     }, 'fieldName' => function ($class) {
         $pos = strrpos($class, '\\');
         $basename = substr($class, $pos !== false ? $pos + 1 : 0);
         return Inflector::underscore(Inflector::singularize($basename));
     }, 'usingName' => function ($name) {
         return Inflector::singularize($name);
     }, 'getter' => function ($name) {
         return 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $name)));
     }, 'setter' => function ($name) {
         return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $name)));
     }]];
     $config = Set::merge($defaults, $config);
     $this->_conventions = $config['conventions'];
 }
Ejemplo n.º 3
0
 /**
  * Constructor.
  *
  * @param array $config Possible options are:
  *                      - `'classes'`     _array_  : The class dependencies.
  *                      - `'connection'`  _object_ : The connection instance.
  */
 public function __construct($config = [])
 {
     $defaults = ['classes' => ['schema' => 'chaos\\database\\Schema', 'model' => 'chaos\\Model'], 'connection' => null, 'fixtures' => []];
     $config = Set::merge($defaults, $config);
     $this->_classes = $config['classes'];
     $this->_connection = $config['connection'];
     $this->_fixtures = $config['fixtures'];
 }
Ejemplo n.º 4
0
 /**
  * Constructor.
  *
  * @param array $config Possible options are:
  *                      - `'connection'`  _object_ : The connection instance.
  */
 public function __construct($config = [])
 {
     $defaults = ['connection' => null, 'model' => $this->_model, 'meta' => [], 'alters' => $this->_alters];
     $config = Set::merge($defaults, $config);
     $this->_connection = $config['connection'];
     $this->_meta = $config['meta'];
     $this->_alters = $config['alters'];
     $this->_model = $config['model'];
     $model = $this->_model;
     $model::config(['connection' => $this->connection()]);
 }
Ejemplo n.º 5
0
 /**
  * Constructor
  *
  * @param array $config The config array. Possible values are:
  *                      - `'handlers'` _array_ : Some custom handlers.
  */
 public function __construct($config = [])
 {
     $defaults = ['meta' => [], 'handlers' => [], 'classes' => $this->_classes, 'error' => function ($name, $options, $meta = []) {
         return Text::insert($options['message'] ?: $this->message($name), $options);
     }];
     $config = Set::merge($defaults, $config);
     $this->_classes = $config['classes'];
     $this->set($config['handlers']);
     $this->error($config['error']);
     $this->meta($config['meta']);
 }
Ejemplo n.º 6
0
 /**
  * Creates the database object and set default values for it.
  *
  * Options defined:
  *  - `'dns'`       : _string_ The full dsn connection url. Defaults to `null`.
  *  - `'database'`  : _string_ Name of the database to use. Defaults to `null`.
  *  - `'host'`      : _string_ Name/address of server to connect to. Defaults to 'localhost'.
  *  - `'username'`  : _string_ Username to use when connecting to server. Defaults to 'root'.
  *  - `'password'`  : _string_ Password to use when connecting to server. Defaults to `''`.
  *  - `'encoding'`  : _string_ The database character encoding.
  *  - `'persistent'`: _boolean_ If true a persistent connection will be attempted, provided the
  *                    adapter supports it. Defaults to `true`.
  *  - `'dialect'`       : _object_ A SQL dialect adapter
  *
  * @param  $config array Array of configuration options.
  * @return Database object.
  */
 public function __construct($config = [])
 {
     $defaults = ['classes' => ['cursor' => 'chaos\\database\\Cursor', 'schema' => 'chaos\\database\\Schema', 'dialect' => 'sql\\Dialect'], 'client' => null, 'connect' => true, 'meta' => ['key' => 'id', 'locked' => true], 'persistent' => true, 'host' => 'localhost', 'username' => 'root', 'password' => '', 'database' => null, 'encoding' => null, 'dsn' => null, 'options' => [], 'dialect' => null, 'handlers' => []];
     $config = Set::merge($defaults, $config);
     $this->_config = $config;
     $this->_classes = $this->_config['classes'] + $this->_classes;
     $this->_client = $this->_config['client'];
     unset($this->_config['client']);
     $this->_dialect = $config['dialect'];
     unset($this->_config['dialect']);
     $this->_handlers = Set::merge($this->_handlers(), $config['handlers']);
     if ($this->_dialect === null) {
         $dialect = $this->_classes['dialect'];
         $this->_dialect = new $dialect(['quoter' => function ($string) {
             return $this->quote($string);
         }, 'caster' => function ($value, $states = []) {
             $type = isset($states['type']) ? $states['type'] : gettype($value);
             if (is_array($type)) {
                 $type = call_user_func($type, $states['name']);
             }
             return $this->format('datasource', $type, $value);
         }]);
     }
     if ($this->_config['connect']) {
         $this->connect();
     }
     $handlers = $this->_handlers;
     $this->formatter('cast', 'id', $handlers['cast']['integer']);
     $this->formatter('cast', 'serial', $handlers['cast']['integer']);
     $this->formatter('cast', 'integer', $handlers['cast']['integer']);
     $this->formatter('cast', 'float', $handlers['cast']['float']);
     $this->formatter('cast', 'decimal', $handlers['cast']['decimal']);
     $this->formatter('cast', 'date', $handlers['cast']['date']);
     $this->formatter('cast', 'datetime', $handlers['cast']['datetime']);
     $this->formatter('cast', 'boolean', $handlers['cast']['boolean']);
     $this->formatter('cast', 'null', $handlers['cast']['null']);
     $this->formatter('cast', 'string', $handlers['cast']['string']);
     $this->formatter('cast', '_default_', $handlers['cast']['string']);
     $this->formatter('datasource', 'id', $handlers['datasource']['string']);
     $this->formatter('datasource', 'serial', $handlers['datasource']['string']);
     $this->formatter('datasource', 'integer', $handlers['datasource']['string']);
     $this->formatter('datasource', 'float', $handlers['datasource']['string']);
     $this->formatter('datasource', 'decimal', $handlers['datasource']['string']);
     $this->formatter('datasource', 'date', $handlers['datasource']['date']);
     $this->formatter('datasource', 'datetime', $handlers['datasource']['datetime']);
     $this->formatter('datasource', 'boolean', $handlers['datasource']['boolean']);
     $this->formatter('datasource', 'null', $handlers['datasource']['null']);
     $this->formatter('datasource', 'string', $handlers['datasource']['quote']);
     $this->formatter('datasource', 'object', $handlers['datasource']['object']);
     $this->formatter('datasource', '_default_', $handlers['datasource']['quote']);
 }
Ejemplo n.º 7
0
 /**
  * Expands a collection of entities by adding their related data.
  *
  * @param  mixed $collection The collection to expand.
  * @return array             The collection of related entities.
  */
 public function embed(&$collection, $options = [])
 {
     $options = Set::merge(['fetchOptions' => ['collector' => $this->_collector($collection)]], $options);
     $name = $this->name();
     $through = $this->through();
     $using = $this->using();
     $from = $this->from();
     $relThrough = $from::relation($through);
     $middle = $relThrough->embed($collection, $options);
     $pivot = $relThrough->to();
     $relUsing = $pivot::schema()->relation($using);
     $related = $relUsing->embed($middle, $options);
     $this->_cleanup($collection);
     $fromKey = $this->keys('from');
     $indexes = $this->_index($related, $this->keys('to'));
     foreach ($collection as $index => $entity) {
         if (is_object($entity)) {
             foreach ($entity->{$through} as $key => $item) {
                 if (isset($item->{$using})) {
                     $value = $item->{$using};
                     if ($entity instanceof Model) {
                         $entity->__get($name);
                         // Too Many Magic Kill The Magic.
                     } else {
                         $entity->{$name}[] = $value;
                     }
                 }
             }
         } else {
             foreach ($entity[$through] as $key => $item) {
                 if (isset($indexes[$item[$fromKey]])) {
                     $collection[$index][$name][] = $related[$indexes[$item[$fromKey]]];
                     $collection[$index][$through][$key][$using] = $related[$indexes[$item[$fromKey]]];
                 }
             }
         }
     }
     return $related;
 }
Ejemplo n.º 8
0
 /**
  * Expands a collection of entities by adding their related data.
  *
  * @param  mixed $collection The collection to expand.
  * @param  array $options    The embedging options.
  * @return array             The collection of related entities.
  */
 public function embed(&$collection, $options = [])
 {
     $indexes = $this->_index($collection, $this->keys('from'));
     $related = $this->_find(array_keys($indexes), Set::merge(['fetchOptions' => ['collector' => $this->_collector($collection)]], $options));
     $name = $this->name();
     $this->_cleanup($collection);
     foreach ($related as $index => $entity) {
         if (is_object($entity)) {
             $value = $entity->{$this->keys('to')};
             if (isset($indexes[$value])) {
                 $source = $collection[$indexes[$value]];
                 $source->{$name}[] = $entity;
             }
         } else {
             $value = $entity[$this->keys('to')];
             if (isset($indexes[$value])) {
                 $collection[$indexes[$value]][$name][] = $entity;
             }
         }
     }
     return $related;
 }
Ejemplo n.º 9
0
 /**
  * Returns a nested tree representation of `'embed'` option.
  *
  * @return array The corresponding nested tree representation.
  */
 public function treeify($embed)
 {
     if (!$embed) {
         return [];
     }
     if ($embed === true) {
         $embed = $this->relations();
     }
     $embed = Set::expand(array_fill_keys(array_keys(Set::normalize((array) $embed)), null));
     $result = [];
     foreach ($embed as $relName => $value) {
         if (!isset($this->_relations[$relName])) {
             continue;
         }
         if ($this->_relations[$relName]['relation'] === 'hasManyThrough') {
             $rel = $this->relation($relName);
             $result[$rel->through()] = [$rel->using() => $value];
         }
         $result[$relName] = $value;
     }
     return $result;
 }
Ejemplo n.º 10
0
 /**
  * Constructs the MySQL adapter and sets the default port to 3306.
  *
  * @param array $config Configuration options for this class. Available options
  *                      defined by this class:
  *                      - `'host'`: _string_ The IP or machine name where MySQL is running,
  *                                  followed by a colon, followed by a port number or socket.
  *                                  Defaults to `'localhost:3306'`.
  */
 public function __construct($config = [])
 {
     $defaults = ['host' => 'localhost:3306', 'classes' => ['dialect' => 'sql\\dialect\\MySql'], 'handlers' => []];
     $config = Set::merge($defaults, $config);
     parent::__construct($config);
 }
Ejemplo n.º 11
0
 /**
  * Gets all entities attached to a collection en entities.
  *
  * @param  mixed  $id An id or an array of ids.
  * @return object     A collection of items matching the id/ids.
  */
 protected function _find($id, $options = [])
 {
     $defaults = ['query' => [], 'fetchOptions' => []];
     $options += $defaults;
     $fetchOptions = $options['fetchOptions'];
     unset($options['fetchOptions']);
     if ($this->link() !== static::LINK_KEY) {
         throw new ChaosException("This relation is not based on a foreign key.");
     }
     $to = $this->to();
     if (!$id) {
         $collector = isset($fetchOptions['collector']) ? $fetchOptions['collector'] : null;
         return $to::create([], ['type' => 'set', 'collector' => $collector]);
     }
     if (is_array($id) && count($id) === 1) {
         $id = reset($id);
     }
     $query = Set::merge($options['query'], ['conditions' => [$this->keys('to') => $id]]);
     return $to::all($query, $fetchOptions);
 }
Ejemplo n.º 12
0
 protected function _applyHas()
 {
     $tree = Set::expand(array_fill_keys(array_keys($this->has()), false));
     $this->_applyJoins($this->model(), $tree, '', $this->alias());
     foreach ($this->has() as $path => $conditions) {
         $this->where($conditions, $this->alias($path));
     }
 }
Ejemplo n.º 13
0
 /**
  * Instantiates a new record or document object, initialized with any data passed in. For example:
  *
  * ```php
  * $post = Posts::create(['title' => 'New post']);
  * echo $post->title; // echoes 'New post'
  * $success = $post->save();
  * ```
  *
  * Note that while this method creates a new object, there is no effect on the database until
  * the `save()` method is called.
  *
  * In addition, this method can be used to simulate loading a pre-existing object from the
  * database, without actually querying the database:
  *
  * ```php
  * $post = Posts::create(['id' => $id, 'moreData' => 'foo'], ['exists' => true]);
  * $post->title = 'New title';
  * $success = $post->save();
  * ```
  *
  * This will create an update query against the object with an ID matching `$id`. Also note that
  * only the `title` field will be updated.
  *
  * @param  array  $data    Any data that this object should be populated with initially.
  * @param  array  $options Options to be passed to item.
  *                         - `'type'`       _string_ : can be `'entity'` or `'set'`. `'set'` is used if the passed data represent a collection
  *                           of entities. Default to `'entity'`.
  *                         - `'exists'`     _mixed_  : corresponds whether the entity is present in the datastore or not.
  *                         - `'autoreload'` _boolean_: sets the specific behavior when exists is `null`. A '`true`' value will perform a
  *                           reload of the entity from the datasource. Default to `'true'`.
  *                         - `'defaults'`   _boolean_: indicates whether the entity needs to be populated with their defaults values on creation.
  *                         - `'model'`      _string_ : the model to use for instantiating the entity. Can be useful for implementing
  *                                                     som Single Table Inheritance.
  * @return object          Returns a new, un-saved record or document object. In addition to
  *                         the values passed to `$data`, the object will also contain any values
  *                         assigned to the `'default'` key of each field defined in the schema.
  */
 public static function create($data = [], $options = [])
 {
     $defaults = ['type' => 'entity', 'exists' => false, 'model' => static::class];
     $options += $defaults;
     $options['defaults'] = !$options['exists'];
     if ($options['defaults'] && $options['type'] === 'entity') {
         $data = Set::merge(Set::expand(static::schema()->defaults()), $data);
     }
     $type = $options['type'];
     $class = $type === 'entity' ? $options['model'] : static::$_classes[$options['type']];
     $options = ['data' => $data] + $options;
     return new $class($options);
 }
Ejemplo n.º 14
0
 /**
  * Constructs the Sqlite adapter and sets the default port to 3306.
  *
  * @param array $config Configuration options for this class. Available options:
  *                      - `'database'` _string_ : database path. Defaults to `':memory:'`.
  */
 public function __construct($config = [])
 {
     $defaults = ['database' => ':memory:', 'classes' => ['dialect' => 'sql\\dialect\\Sqlite'], 'handlers' => []];
     $config = Set::merge($defaults, $config);
     parent::__construct($config);
 }