/**
  * @covers ::many_to_many_get
  */
 function test_many_to_many_get()
 {
     $admin = User::all()->root()->select();
     No2_SQLQuery::execute('INSERT INTO {users_roles_table}(user_id, role_id) VALUES (:id, :admin_role_id), (:id, :anonymous_role_id)', ['{users_roles_table}' => 'users_roles', ':id' => $admin->id, ':admin_role_id' => Role::ADMIN_ID, ':anonymous_role_id' => Role::ANONYMOUS_ID]);
     $user_roles = array_map(function ($r) {
         return $r->id;
     }, $admin->roles()->select());
     $this->assertCount(2, $user_roles, 'User should have two roles');
     $this->assertContains(Role::ADMIN_ID, $user_roles, 'User should have admin role');
     $this->assertContains(Role::ANONYMOUS_ID, $user_roles, 'User should have anonymous role');
 }
 /**
  * Links this model to the others: handles all the stuff about the join table.
  *
  * @param
  *  array $relation: The relation to use
  *
  *  Define the relation with an array containing 3 values:
  *    - The target key: the column linked to this model in the join table
  *    - The join table name
  *    - The linked key: the column linked to the other model in the join table
  *
  * @param
  *  array $others: An array of Models or of ids
  *
  * @throws
  *  InvalidArgumentException when the relation is not well defined
  *  LogicException when $this is a new record
  *
  * @return
  *  boolean: true on success, false otherwise
  */
 protected function many_to_many_set($relation, $others = null)
 {
     if ($this->is_new_record()) {
         throw new LogicException('many_to_many_set called on a new record');
     }
     if (!is_array($relation) || count($relation) < 3) {
         throw new InvalidArgumentException('The relation is not defined');
     }
     list($target_key, $join_table, $linked_key) = $relation;
     $delete = 'DELETE FROM {join_table} WHERE {target_key} = :id';
     $insert = 'INSERT INTO {join_table} ({target_key}, {linked_key}) VALUES';
     $insert_params = $delete_params = ['{join_table}' => $join_table, '{target_key}' => $target_key, '{linked_key}' => $linked_key, ':id' => $this->id];
     // build the VALUES (...) for the INSERT statment
     $values = [];
     if (is_array($others) && !empty($others)) {
         for ($i = 0, $n = count($others); $i < $n; $i++) {
             $other = $others[$i];
             $label = ":val_{$i}";
             $values[] = "(:id, {$label})";
             $insert_params[$label] = is_object($other) && isset($other->id) ? $other->id : $other;
         }
     }
     $values = join(', ', $values);
     $profile = $this->__db_profile;
     $options = ['profile' => $profile];
     if (empty($values)) {
         $success = No2_SQLQuery::execute($delete, $delete_params, $options) !== false;
     } else {
         // start a transaction if we're not already in one.
         $already_in_transaction = No2_SQLQuery::_inTransaction();
         if (!$already_in_transaction) {
             No2_SQLQuery::_beginTransaction($profile);
         }
         // do the work
         $success = No2_SQLQuery::execute($delete, $delete_params, $options) !== false && No2_SQLQuery::execute("{$insert} {$values}", $insert_params, $options) !== false;
         // terminate the transaction if we started it.
         if (!$already_in_transaction) {
             if ($success) {
                 No2_SQLQuery::_commitTransaction($profile);
             } else {
                 No2_SQLQuery::_rollBackTransaction($profile);
             }
         }
     }
     return $success;
 }
Ejemplo n.º 3
0
 /**
  * Find many rows with an SQL statment.
  *
  * Allow to create a complexe SELECT query that will return this type of
  * Model. This method is a wrapper around find_by_sql() which always return
  * an array.
  *
  * @see
  *   No2_SQLQuery::execute(), No2_Database::execute()
  *
  * @return
  *  An array with all instances found (one or zero results will still be
  *  returned in a array).
  */
 public static function find_all_by_sql($sql, $arguments = [], $options = [])
 {
     return No2_SQLQuery::execute($sql, $arguments, array_merge($options, ['factory' => get_called_class(), 'return_as_collection' => true]));
 }