/** * Deletes all data from a database table * * @version 1.0 * @since 1.0 * @return bool | Exception on failure. True on success. */ public function truncate() { if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } $db = new FOX_db(array('pid' => $this->process_id)); try { $db->runTruncateTable($this->_struct()); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Failed to truncate table", 'data' => array('struct' => $this->_struct()), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } return true; }
/** * Returns an array of logged events based on supplied parameters. This function integrates with a jQuery * datagrid control in the admin screens, allowing arbitrary sorting and filtering of events. * * @param array $args | Args in the form: array("col"=>column_name, "op" => "<, >, =, !=", "val" => "int | string | array()") * => ARR @param array $args | Args in the form: array("col"=>column_name, "op"=>"<, >, =, !=", "val"=>"int | string | array()") * => ARR @param int '' | Array index * => VAL @param string $col | Name of the column this key describes * * => VAL @param string $op | SQL comparison operator to use: ">=" | "<=" | ">" | "<" | "=" | "!=" | "<>" * => VAL @param int/string/array $val | Value or values to test against. Single value as int/string. Multiple values as array. * * * @param object/array $columns | Either array with specific columns to include/exclue or anything else to return all columns. * => ARR @param int '' | Array index * => VAL @param string $table_class | Class of table that the column is from. * => VAL @param string $table_alias | Alias table that the column is from. Used instead of table_class not required * => VAL @param string $col_name | Name of the column * => VAL @param string $col_alias | Alias of the column * => VAL @param bool $count | True to count this column * => VAL @param bool/array $sum | True sum this column, array sums multiple columns * => ARR @param int '' | Array index * => VAL @param string $table_alias | Table alias of table that the column is from. if table alias is not set the default is t(number) * => VAL @param string $col_name | Name of the column * => VAL @param string $col_alias | Column alias used instead of table alias and col_name * => VAL @param bool $count | True to count this column * => VAL @param string $op | Operation to perform on column value +,- or *(muliple) default + * * @param array $ctrl | Control parameters for the query * => VAL @param int $page | Set current page (used when traversing multi-page data sets) * => VAL @param int $per_page | Max number of rows to return in a query / number of rows to return per page when transversing a multi-page data set * => VAL @param int $offset | Shift results page forward or backward "n" items within the returned data set * => ARR @param array $sort | Sort results by supplied parameters. Multi-dimensional sorts possible by passing multiple arrays. * => ARR @param int '' | Array index * => VAL @param string $class | Class name that owns the table * => VAL @param string $col | Name of column to sort by * => VAL @param string $col_alias | Column alias used instead of class and col. not required * => VAL @param string/array $sort | Direction to sort in. "ASC", "DESC", array(val, val, val) where position in array * is the desired position in the results set for the row or rows with columm matching val * => ARR @param array $group | Apply SQL GROUP to columns. Multi-dimensional group possible by passing multiple arrays. * => ARR @param int '' | Array index * => VAL @param string $class | Class name that owns the table * => VAL @param string $col | Name of column to apply GROUP to * => VAL @param string $col_alias | Column alias used instead of class and col. not required * => VAL @param string $sort | Direction to sort in. "ASC" | "DESC" * => VAL @param string $format | @see FOX_db::runQuery() for detailed info on format string * => VAL @param string $key_col | Column name to get key names from when using $format="key" or $format="asc" * => VAL @param string $asc_col | Column name to use as value when using $format="asc" * * @param bool $return_tokens | True to use dictionary and return words for tree, branch and node * * @return bool/int/array | False on failure. Int on count. Array of rows on success. */ public function query($args = null, $columns = null, $ctrl = null, $return_tokens = true) { if (!isset($ctrl)) { $ctrl = array(); } if (!isset($ctrl['format'])) { $ctrl['format'] = "array_array"; } $join_args = array("tree" => array(), "branch" => array(), "node" => array()); if (is_array($args)) { // Process args in case dic entries are used instead of numbers foreach ($args as $arg) { // check dic columns if (in_array($arg["col"], array('tree', 'branch', 'node'))) { // if val is string or array of strings if (!is_numeric($arg["val"]) || is_array($arg["val"]) && !is_numeric($arg["val"][0])) { // if val is string or array of strings then add to join_args and don't add to processed_args $join_args[$arg['col']][] = $args; continue; } } $processed_args[] = $arg; } } $db = new FOX_db(); // Check if need to use runSelectLeftJoin $num_join_args = count($join_args['tree']) + count($join_args['branch']) + count($join_args['node']); if ($return_tokens || $num_join_args > 0) { if (!isset($ctrl['group'])) { $ctrl["group"] = array(array("class" => self::$struct, "col" => "id", "sort" => "ASC")); } $primary = array("class" => self::$struct, "args" => $processed_args); $join = array(array("class" => "FOX_log_dictionary_tree", "on" => array("pri" => "tree", "op" => "=", "sec" => "id"), "args" => $join_args['tree']), array("class" => "FOX_log_dictionary_branch", "on" => array("pri" => "branch", "op" => "=", "sec" => "id"), "args" => $join_args['branch']), array("class" => "FOX_log_dictionary_node", "on" => array("pri" => "node", "op" => "=", "sec" => "id"), "args" => $join_args['node'])); if (is_null($columns)) { if ($return_tokens) { $columns = array(array("table_alias" => "t1", "col_name" => "id", "col_alias" => "id"), array("table_alias" => "t2", "col_name" => "token", "col_alias" => "tree"), array("table_alias" => "t3", "col_name" => "token", "col_alias" => "branch"), array("table_alias" => "t4", "col_name" => "token", "col_alias" => "node"), array("table_alias" => "t1", "col_name" => "user_id", "col_alias" => "user_id"), array("table_alias" => "t1", "col_name" => "level", "col_alias" => "level"), array("table_alias" => "t1", "col_name" => "date", "col_alias" => "date"), array("table_alias" => "t1", "col_name" => "summary", "col_alias" => "summary"), array("table_alias" => "t1", "col_name" => "data", "col_alias" => "data")); } else { $columns = array(array("table_alias" => "t1", "col_name" => "id", "col_alias" => "id"), array("table_alias" => "t1", "col_name" => "tree", "col_alias" => "tree"), array("table_alias" => "t1", "col_name" => "branch", "col_alias" => "branch"), array("table_alias" => "t1", "col_name" => "node", "col_alias" => "node"), array("table_alias" => "t1", "col_name" => "user_id", "col_alias" => "user_id"), array("table_alias" => "t1", "col_name" => "level", "col_alias" => "level"), array("table_alias" => "t1", "col_name" => "date", "col_alias" => "date"), array("table_alias" => "t1", "col_name" => "summary", "col_alias" => "summary"), array("table_alias" => "t1", "col_name" => "data", "col_alias" => "data")); } } try { $result = $db->runSelectQueryLeftJoin($primary, $join, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error reading from DB \n", 'data' => array('primary' => $primary, 'join' => $join, 'columns' => $columns, 'ctrl' => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); return false; } } else { if (!is_null($columns) && count($columns) > 0) { $select_columns["mode"] = "include"; if (count($columns) == 1) { $select_columns["col"] = $columns[0]["col_name"]; } else { foreach ($columns as $col) { $select_columns["col"][] = $col["col_name"]; } } } try { $result = $db->runSelectQuery(self::$struct, $processed_args, $select_columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Error reading from DB \n", 'data' => array('primary' => $primary, 'join' => $join, 'columns' => $columns, 'ctrl' => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); return false; } } if ($result == 0) { return false; } else { return $result; } }
/** * Deletes the entire keyring for one or more groups * * @version 1.0 * @since 1.0 * * @param int $group_id | id of the group as int. Multiple groups as array of int. * @return int | Number of keys affected. */ public function dropGroup($group_id) { global $fox; $db = new FOX_db(); // Drop the keys from the db $args = array(array("col" => "group_id", "op" => "=", "val" => $group_id)); try { $result = $db->runDeleteQuery(self::$struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the cache if ($result) { if (!is_array($group_id)) { $group_id = array($group_id); } foreach ($group_id as $group) { unset($this->cache["keys"][$group]); unset($this->cache["groups"][$group]); } unset($group); try { $cache_ok = self::saveCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "saveCache exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($cache_ok) { return $result; } else { return false; } } else { return $result; } }
/** * Removes one or more modules from the database and cache. * * @version 1.0 * @since 1.0 * * @param string $module_type | Single module_type as string. * @param int/array $module_ids | Single module_id as int. Multiple module_id's as array of int. * * @return int | Exception on failure. Int number of db rows changed on success. */ public function deleteModule($module_type, $module_ids) { $db = new FOX_db(); $struct = self::_struct(); if (empty($module_type) || !is_string($module_type)) { throw new FOX_exception(array('numeric' => 1, 'text' => "Invalid module_types parameter", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (empty($module_ids)) { throw new FOX_exception(array('numeric' => 2, 'text' => "Invalid module_ids parameter", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!is_array($module_ids)) { // Handle single int as input $module_ids = array($module_ids); } // Lock the cache // =========================================================== try { self::lockCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Error locking cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the database // =========================================================== $args = array(array("col" => "module_type", "op" => "=", "val" => $module_type), array("col" => "module_id", "op" => "=", "val" => $module_ids)); try { $rows_changed = $db->runDeleteQuery($struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error deleting from database", 'data' => array('args' => $args), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Flush the cache // ============================================================= // NOTE: this is a case where it's not practical to rebuild the cache. We'd have to run an // additional query to fetch the old module_slug and php_class values to clear them from the cache try { self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Error flushing cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } return (int) $rows_changed; }
/** * Test fixture for addMulti() method (matrix mode) * * @version 1.0 * @since 1.0 * * ======================================================================================= */ function test_addMulti_matrix() { $test_obj = new stdClass(); $test_obj->foo = "11"; $test_obj->bar = "test_Bar"; $test_data = array(array('L4' => 'A', 'L3' => 'X', 'L2' => 'K', 'L1' => 1, 'L0' => null), array('L4' => 'A', 'L3' => 'X', 'L2' => 'K', 'L1' => 2, 'L0' => false), array('L4' => 'A', 'L3' => 'X', 'L2' => 'K', 'L1' => 5, 'L0' => true), array('L4' => 'A', 'L3' => 'X', 'L2' => 'Z', 'L1' => 3, 'L0' => (int) 0), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'K', 'L1' => 1, 'L0' => (int) 1), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'K', 'L1' => 2, 'L0' => (int) -1), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'K', 'L1' => 3, 'L0' => (double) 1.7), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'Z', 'L1' => 4, 'L0' => (double) -1.6), array('L4' => 'B', 'L3' => 'X', 'L2' => 'K', 'L1' => 1, 'L0' => (string) "foo"), array('L4' => 'B', 'L3' => 'X', 'L2' => 'K', 'L1' => 2, 'L0' => array(null, true, false, 1, 1.0, "foo")), array('L4' => 'B', 'L3' => 'X', 'L2' => 'Z', 'L1' => 3, 'L0' => $test_obj)); // Load class with data // =============================================================== try { $ctrl = array('mode' => 'matrix'); $set_ok = $this->cls->addMulti($test_data, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(array('depth' => 50, 'data' => true))); } // Should return number of L1's added $this->assertEquals(11, $set_ok); // Test adding some duplicate itemes // =============================================================== try { $dupe_data = array(array('L4' => 'A', 'L3' => 'X', 'L2' => 'K', 'L1' => 1, 'L0' => null), array('L4' => 'A', 'L3' => 'X', 'L2' => 'K', 'L1' => 2, 'L0' => false), array('L4' => 'A', 'L3' => 'X', 'L2' => 'K', 'L1' => 1, 'L0' => true), array('L4' => 'A', 'L3' => 'X', 'L2' => 'Z', 'L1' => 3, 'L0' => (int) 0), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'K', 'L1' => 1, 'L0' => (int) 1), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'K', 'L1' => 2, 'L0' => (int) -1), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'K', 'L1' => 3, 'L0' => (double) 1.7), array('L4' => 'A', 'L3' => 'Y', 'L2' => 'Z', 'L1' => 4, 'L0' => (double) -1.6)); $ctrl = array('mode' => 'matrix'); $this->cls->addMulti($dupe_data, $ctrl); // Execution will halt on the previous line if addMulti() throws an exception $this->fail("Method addMulti() failed to throw an exception on duplicate entry"); } catch (FOX_exception $child) { } // Check cache state // =============================================================== // NOTE: the LUT's won't be set at this point, because we haven't done any // database reads that give objects authority $check = array('A' => array('keys' => array('X' => array('K' => array(1 => null, 2 => false, 5 => true), 'Z' => array(3 => (int) 0)), 'Y' => array('K' => array(1 => (int) 1, 2 => (int) -1, 3 => (double) 1.7), 'Z' => array(4 => (double) -1.6)))), 'B' => array('keys' => array('X' => array('K' => array(1 => (string) "foo", 2 => array(null, true, false, 1, 1.0, "foo")), 'Z' => array(3 => $test_obj))))); $this->assertEquals($check, $this->cls->cache); // Check db state // =============================================================== $check = array('A' => array('X' => array('K' => array(1 => null, 2 => false, 5 => true), 'Z' => array(3 => (int) 0)), 'Y' => array('K' => array(1 => (int) 1, 2 => (int) -1, 3 => (double) 1.7), 'Z' => array(4 => (double) -1.6))), 'B' => array('X' => array('K' => array(1 => (string) "foo", 2 => array(null, true, false, 1, 1.0, "foo")), 'Z' => array(3 => $test_obj)))); $db = new FOX_db(); $columns = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('L4', 'L3', 'L2', 'L1')); try { $struct = $this->cls->_struct(); $result = $db->runSelectQuery($struct, $args = null, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals($check, $result); }
function test_dropId_Multi() { // load db // ====================================================== $add_tokens = array("one", "two", "three", "four", "five"); try { $add_result = $this->cls->addToken($add_tokens); } catch (FOX_exception $child) { $this->fail($child->dumpString(array('depth' => 50, 'data' => true))); } // Test single dropId // ====================================================== try { $drop_ids = array(1, 2, 3, 4, 5); $this->assertEquals(5, $this->cls->dropId($drop_ids)); } catch (FOX_exception $child) { $this->fail($child->dumpString(array('depth' => 50, 'data' => true))); } // Check Db has no rows // ====================================================== try { $db = new FOX_db(); $this->assertEquals(false, $db->runSelectQuery(FOX_test_dictionary::$struct)); } catch (FOX_exception $child) { $this->fail($child->dumpString(array('depth' => 50, 'data' => true))); } // Check Class cache is empty $this->assertEquals(array('ids' => array(), 'tokens' => array()), $this->cls->cache); }
/** * Test fixture for setMulti() method (matrix mode) * * @version 1.0 * @since 1.0 * * ======================================================================================= */ function test_setMulti_matrix() { $test_obj = new stdClass(); $test_obj->foo = "11"; $test_obj->bar = "test_Bar"; $test_data = array(array('L5' => 1, 'L4' => 'X', 'L3' => 'K', 'L2' => 'K', 'L1' => 1, 'L0' => null), array('L5' => 1, 'L4' => 'X', 'L3' => 'K', 'L2' => 'K', 'L1' => 2, 'L0' => false), array('L5' => 1, 'L4' => 'X', 'L3' => 'K', 'L2' => 'T', 'L1' => 1, 'L0' => true), array('L5' => 1, 'L4' => 'X', 'L3' => 'Z', 'L2' => 'Z', 'L1' => 3, 'L0' => (int) 0), array('L5' => 1, 'L4' => 'Y', 'L3' => 'K', 'L2' => 'K', 'L1' => 1, 'L0' => (int) 1), array('L5' => 1, 'L4' => 'Y', 'L3' => 'K', 'L2' => 'K', 'L1' => 2, 'L0' => (int) -1), array('L5' => 1, 'L4' => 'Y', 'L3' => 'K', 'L2' => 'T', 'L1' => 3, 'L0' => (double) 1.7), array('L5' => 1, 'L4' => 'Y', 'L3' => 'Z', 'L2' => 'Z', 'L1' => 4, 'L0' => (double) -1.6), array('L5' => 2, 'L4' => 'X', 'L3' => 'K', 'L2' => 'K', 'L1' => 1, 'L0' => (string) "foo"), array('L5' => 2, 'L4' => 'X', 'L3' => 'K', 'L2' => 'K', 'L1' => 2, 'L0' => array(null, true, false, 1, 1.0, "foo")), array('L5' => 2, 'L4' => 'X', 'L3' => 'Z', 'L2' => 'Z', 'L1' => 3, 'L0' => $test_obj)); // Load class with data // =============================================================== try { $ctrl = array('mode' => 'matrix'); $set_ok = $this->cls->setMulti($test_data, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(array('depth' => 50, 'data' => true))); } // Should return number of L1's added $this->assertEquals(11, $set_ok); // Test adding some duplicate itemes // =============================================================== try { $dupe_data = array(array('L5' => 1, 'L4' => 'X', 'L3' => 'K', 'L2' => 'K', 'L1' => 1, 'L0' => null), array('L5' => 1, 'L4' => 'X', 'L3' => 'K', 'L2' => 'K', 'L1' => 2, 'L0' => false), array('L5' => 1, 'L4' => 'X', 'L3' => 'K', 'L2' => 'T', 'L1' => 1, 'L0' => true), array('L5' => 1, 'L4' => 'X', 'L3' => 'Z', 'L2' => 'Z', 'L1' => 3, 'L0' => (int) 0), array('L5' => 1, 'L4' => 'Y', 'L3' => 'K', 'L2' => 'K', 'L1' => 1, 'L0' => (int) 1), array('L5' => 1, 'L4' => 'Y', 'L3' => 'K', 'L2' => 'K', 'L1' => 2, 'L0' => (int) -1), array('L5' => 1, 'L4' => 'Y', 'L3' => 'K', 'L2' => 'T', 'L1' => 3, 'L0' => (double) 1.7), array('L5' => 1, 'L4' => 'Y', 'L3' => 'Z', 'L2' => 'Z', 'L1' => 4, 'L0' => (double) -1.6)); $ctrl = array('mode' => 'matrix'); $rows_changed = $this->cls->setMulti($dupe_data, $ctrl); // Should return (int)0 to indicate no rows were changed $this->assertEquals(0, $rows_changed); } catch (FOX_exception $child) { // Shouldn't throw an exception because the set() method allows // existing rows to be overwritten $this->fail($child->dumpString(array('depth' => 50, 'data' => true))); } // Check cache state // =============================================================== // NOTE: the LUT's won't be set at this point, because we haven't done any // database reads that give objects authority $check = array(1 => array('keys' => array('X' => array('K' => array('K' => array(1 => null, 2 => false), 'T' => array(1 => true)), 'Z' => array('Z' => array(3 => (int) 0))), 'Y' => array('K' => array('K' => array(1 => (int) 1, 2 => (int) -1), 'T' => array(3 => (double) 1.7)), 'Z' => array('Z' => array(4 => (double) -1.6))))), 2 => array('keys' => array('X' => array('K' => array('K' => array(1 => (string) "foo", 2 => array(null, true, false, 1, 1.0, "foo"))), 'Z' => array('Z' => array(3 => $test_obj)))))); $this->assertEquals($check, $this->cls->cache); // Check db state // =============================================================== $check = array(1 => array('X' => array('K' => array('K' => array(1 => null, 2 => false), 'T' => array(1 => true)), 'Z' => array('Z' => array(3 => (int) 0))), 'Y' => array('K' => array('K' => array(1 => (int) 1, 2 => (int) -1), 'T' => array(3 => (double) 1.7)), 'Z' => array('Z' => array(4 => (double) -1.6)))), 2 => array('X' => array('K' => array('K' => array(1 => (string) "foo", 2 => array(null, true, false, 1, 1.0, "foo"))), 'Z' => array('Z' => array(3 => $test_obj))))); $db = new FOX_db(); $columns = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('L5', 'L4', 'L3', 'L2', 'L1')); try { $struct = $this->cls->_struct(); $result = $db->runSelectQuery($struct, $args = null, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals($check, $result); }
/** * Test fixture for dropGlobal() method, L4, multi item * * @version 1.0 * @since 1.0 * * ======================================================================================= */ public function test_dropGlobal_L4_multi() { self::loadData(); // Drop objects // #################################################################### $drop_ctrl = array("validate" => true); try { $rows_changed = $this->cls->dropGlobal(4, array('X', 'Y'), $drop_ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } // Should report 19 rows were dropped $this->assertEquals(19, $rows_changed); // Verify db state // #################################################################### $db = new FOX_db(); $columns = null; $args = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('L5', 'L4', 'L3', 'L2', 'L1')); try { $result = $db->runSelectQuery($this->cls->_struct(), $args, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(null, $result); // Check class cache state // #################################################################### $check_cache = array(); $this->assertEquals($check_cache, $this->cls->cache); // Verify persistent cache state by reading-back all items // #################################################################### $request = array(1 => array(), 2 => array(), 3 => array()); $valid = false; try { $result = $this->cls->getMulti($request, $ctrl, $valid); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(false, $valid); // Should report invalid because // a requested L5 doesn't exist $this->assertEquals(array(), $result); }
/** * Drops one or more branches for ALL TREES in the datastore * * @version 1.0 * @since 1.0 * * @param string/array $branches | single branch as string. Multiple branches as array of string. * @return int | Exception on failure. Number of db rows changed on success. */ public function dropSiteBranch($branches) { $db = new FOX_db(); $struct = $this->_struct(); // Lock the cache // =========================================================== try { self::lockCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Error locking cache", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Update the database // =========================================================== $args = array(array("col" => "branch", "op" => "=", "val" => $branches)); try { $rows_changed = $db->runDeleteQuery($struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Error deleting from database", 'data' => array('args' => $args), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Flush the cache // =========================================================== try { self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error flushing cache", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } return (int) $rows_changed; }
/** * Deletes the entire module data store, and flushes the cache. Generally * used for testing and debug. * * @version 1.0 * @since 1.0 * @return bool | Exception on failure. True on success. */ public function dropAll() { $db = new FOX_db(); $struct = $this->_struct(); try { $db->runTruncateTable($struct); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Error while clearing the database", 'data' => null, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Since this operation affects *all* module_id's, we have to flush // the entire cache namespace try { self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Cache flush error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } }
/** * Drops one or more keys from the database and cache for ALL USERS ON THE SITE. Generally used when * uninstalling or upgfoxing apps, or for managing admin-assigned arbitrary keys. * * @version 1.0 * @since 1.0 * * @param int/array $key_id | Single key_id as int. Multiple key_id's as array of ints. * @return bool | False on failure. True on success. */ public function revokeKeySitewide($key_id) { global $fox; $db = new FOX_db(); $args = array(array("col" => "key_id", "op" => "=", "val" => $key_id)); try { $rows_changed = $db->runDeleteQuery(self::$struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB delete exception", 'data' => array("args" => $args), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Because multiple user_id's are affected by this operation, we have // to flush the entire cache try { $cache_ok = self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "flushCache exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($cache_ok) { return $rows_changed; } else { return false; } }
/** * Test fixture for dropGlobal() method, L1, multiple items * * @version 1.0 * @since 1.0 * * ======================================================================================= */ public function test_dropGlobal_L1_multi() { self::loadData(); // Drop objects // #################################################################### $drop_ctrl = array("validate" => true); try { $rows_changed = $this->cls->dropGlobal(1, array(1, 2), $drop_ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } // Should report 12 rows were dropped $this->assertEquals(10, $rows_changed); // Verify db state // #################################################################### $db = new FOX_db(); $columns = null; $args = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('L2', 'L1')); try { $result = $db->runSelectQuery($this->cls->_struct(), $args, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } // NOTE: the datastore will automatically clip empty branches $test_obj = new stdClass(); $test_obj->foo = "11"; $test_obj->bar = "test_Bar"; $check = array('X' => array(5 => true, 3 => (int) 0), 'Y' => array(3 => (double) 1.7, 4 => (double) -1.6), 'Z' => array(3 => $test_obj), 'A' => array(5 => true, 3 => (int) 0), 'B' => array(3 => (double) 1.7, 4 => (double) -1.6)); $this->assertEquals($check, $result); // Check class cache state // #################################################################### $check_cache = array(); $this->assertEquals($check_cache, $this->cls->cache); // Verify persistent cache state by reading-back all items // #################################################################### $request = array('X' => array(), 'Y' => array(), 'Z' => array(), 'A' => array(), 'B' => array()); $valid = false; try { $result = $this->cls->getMulti($request, $ctrl, $valid); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $valid); // Should report valid because all // requested L2's exist $this->assertEquals($check, $result); }
/** * Test fixture for processHTMLForm() method, data integrity * * @version 1.0 * @since 1.0 * * ======================================================================================= */ public function test_processHTMLForm_dataIntegrity() { self::loadData(); // Missing key names string // =============================================================== $check = array('plugin_1^X^K^N' => true, 'plugin_1^X^K^N2' => false, 'plugin_1^X^Z^N3' => 2, 'plugin_1^Y^Z^N4' => -1.6); try { $result = $this->cls->processHTMLForm($check); // Execution will halt on the previous line if processHTMLForm() throws an exception $this->fail("Method processHTMLForm() failed to throw an exception on missing key names parameter"); } catch (FOX_exception $child) { } // Invalid plugin name // =============================================================== $check = array('key_names' => '1^X^K^N1,plugin_1^X^K^N2,plugin_1^X^Z^N3,plugin_1^Y^Z^N4', 'plugin_1^X^K^N' => true, 'plugin_1^X^K^N2' => false, 'plugin_1^X^Z^N3' => 2, 'plugin_1^Y^Z^N4' => -1.6); try { $result = $this->cls->processHTMLForm($check); // Execution will halt on the previous line if processHTMLForm() throws an exception $this->fail("Method processHTMLForm() failed to throw an exception on invalid plugin name"); } catch (FOX_exception $child) { } // Invalid tree name // =============================================================== $check = array('key_names' => 'plugin_1^1^K^N1,plugin_1^X^K^N2,plugin_1^X^Z^N3,plugin_1^Y^Z^N4', 'plugin_1^X^K^N' => true, 'plugin_1^X^K^N2' => false, 'plugin_1^X^Z^N3' => 2, 'plugin_1^Y^Z^N4' => -1.6); try { $result = $this->cls->processHTMLForm($check); // Execution will halt on the previous line if processHTMLForm() throws an exception $this->fail("Method processHTMLForm() failed to throw an exception on invalid tree name"); } catch (FOX_exception $child) { } // Invalid branch name // =============================================================== $check = array('key_names' => 'plugin_1^X^1^N1,plugin_1^X^K^N2,plugin_1^X^Z^N3,plugin_1^Y^Z^N4', 'plugin_1^X^K^N' => true, 'plugin_1^X^K^N2' => false, 'plugin_1^X^Z^N3' => 2, 'plugin_1^Y^Z^N4' => -1.6); try { $result = $this->cls->processHTMLForm($check); // Execution will halt on the previous line if processHTMLForm() throws an exception $this->fail("Method processHTMLForm() failed to throw an exception on invalid branch name"); } catch (FOX_exception $child) { } // Invalid node name // =============================================================== $check = array('key_names' => 'plugin_1^X^K^1,plugin_1^X^K^N2,plugin_1^X^Z^N3,plugin_1^Y^Z^N4', 'plugin_1^X^K^N' => true, 'plugin_1^X^K^N2' => false, 'plugin_1^X^Z^N3' => 2, 'plugin_1^Y^Z^N4' => -1.6); try { $result = $this->cls->processHTMLForm($check); // Execution will halt on the previous line if processHTMLForm() throws an exception $this->fail("Method processHTMLForm() failed to throw an exception on invalid node name"); } catch (FOX_exception $child) { } // Nonexistent node // =============================================================== $check = array('key_names' => 'plugin_1^X^K^N6,plugin_1^X^K^N2,plugin_1^X^Z^N3,plugin_1^Y^Z^N4', 'plugin_1^X^K^N' => true, 'plugin_1^X^K^N2' => false, 'plugin_1^X^Z^N3' => 2, 'plugin_1^Y^Z^N4' => -1.6); try { $result = $this->cls->processHTMLForm($check); // Execution will halt on the previous line if processHTMLForm() throws an exception $this->fail("Method processHTMLForm() failed to throw an exception on nonexistent node"); } catch (FOX_exception $child) { } // Check db state // =============================================================== $test_obj = new stdClass(); $test_obj->foo = "11"; $test_obj->bar = "test_Bar"; $check = array("plugin_1" => array('X' => array('K' => array('N1' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => null), 'N2' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => false), 'N5' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => true)), 'Z' => array('N3' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => (int) 0))), 'Y' => array('K' => array('N1' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => (int) 1), 'N2' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => (int) -1), 'N3' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => (double) 1.7)), 'Z' => array('N4' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => (double) -1.6)))), "plugin_2" => array('X' => array('K' => array('N1' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => (string) "foo"), 'N2' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => array(null, true, false, 1, 1.0, "foo"))), 'Z' => array('N3' => array('filter' => 'debug', 'filter_ctrl' => false, 'val' => $test_obj))))); $db = new FOX_db(); $columns = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('plugin', 'tree', 'branch', 'node')); try { $struct = $this->cls->_struct(); $result = $db->runSelectQuery($struct, $args = null, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals($check, $result); }
/** * Fetches the level_id of one or more slugs * * @version 1.0 * @since 1.0 * * @param int $module_id | module_id that owns the object type_id * @param int $type_id | Object type_id that owns the level_id * @param string $level_slug | Single level_slug as string. Multiple slugs as array of strings. * * @return array | Exception on failure. False on nonexistent. Array "level_slug"=>"level_id" on success */ public function slugToTypeId($module_id, $type_id, $level_slug) { $db = new FOX_db(); if (!is_array($level_slug)) { $level_slug = array($level_slug); } // Load as many id's as possible from the cache // ============================================ $result = array(); $missing_slugs = array(); $persistent_cache_loaded = false; foreach ($level_slug as $slug) { // If a requested slug is in the class cache, add its level_id to the the results array if (FOX_sUtil::keyExists($slug, $this->cache["slug_to_level_id"][$module_id][$type_id])) { $result[$slug] = $this->cache["slug_to_level_id"][$module_id][$type_id][$slug]; } elseif (!$persistent_cache_loaded) { try { self::loadCache(); $persistent_cache_loaded = true; } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } if (FOX_sUtil::keyExists($slug, $this->cache["slug_to_level_id"][$module_id][$type_id])) { $result[$slug] = $this->cache["slug_to_level_id"][$module_id][$type_id][$slug]; } else { $missing_slugs[] = $slug; } } else { $missing_slugs[] = $slug; } } unset($slug); // Fetch any missing "level_slug"-"level_id" pairs from the db // =========================================================== if (count($missing_slugs) > 0) { $args = array(array("col" => "module_id", "op" => "=", "val" => $module_id), array("col" => "type_id", "op" => "=", "val" => $type_id), array("col" => "level_slug", "op" => "=", "val" => $missing_slugs)); $columns = array("mode" => "include", "col" => array("level_slug", "level_id")); $ctrl = array("format" => "array_key_single", "key_col" => "level_slug", "val_col" => "level_id"); try { $db_result = $db->runSelectQuery($this->_struct(), $args, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Error reading from database", 'data' => array('args' => $args, 'columns' => $columns, 'ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Update the cache // ============================== if ($db_result) { $result = array_merge($result, $db_result); try { $cache_image = self::readCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Rebuild cache image foreach ($db_result as $slug => $level_id) { $cache_image["slug_to_level_id"][$module_id][$type_id][$slug] = $level_id; } unset($slug, $level_id); try { self::writeCache($cache_image); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Cache write error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Overwrite the class cache $this->cache = $cache_image; } } if (count($result) >= 1) { return $result; } else { return false; } }
/** * Returns all type_ids owned by a module * * @version 1.0 * @since 1.0 * @param int $module_id| Single module_id as int. * @return array | Exception on failure. False on nonexistent. Array of type_ids on success. */ public function getTypes($module_id) { $db = new FOX_db(); $result = array(); // If the module_id doesn't exist in the class cache array, fetch it from the persistent cache if (!FOX_sUtil::keyExists($module_id, $this->cache["module_id_types"])) { try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // If the module_id doesn't exist in the persistent cache, load it from the db if (!FOX_sUtil::keyExists($module_id, $this->cache["module_id_types"])) { $columns = array("mode" => "include", "col" => array("type_id")); $ctrl = array("format" => "col"); try { $db_result = $db->runSelectQueryCol($this->_struct(), "module_id", "=", $module_id, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Error reading from database", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Update the cache // ============================== if ($db_result) { try { $cache_image = self::readCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Rebuild the cache image foreach ($db_result as $type_id) { $result[] = $type_id; $cache_image["module_id_types"][$module_id][$type_id] = true; } unset($type_id); try { self::writeCache($cache_image); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Cache write error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Overwrite the class cache $this->cache = $cache_image; } else { // The module_id doesn't exist return false; } } } // Build the result array $type_ids = $this->cache["module_id_types"][$module_id]; $result = array_keys($type_ids); return $result; }
function tearDown() { $tdb = new FOX_db(); $tdb->runDropTable(self::$struct); parent::tearDown(); }
/** * Loads the class instance with the test data set, and verifies it was correctly written * to the database and cache * * @version 1.0 * @since 1.0 * * ======================================================================================= */ public function loadData() { $test_obj = new stdClass(); $test_obj->foo = "11"; $test_obj->bar = "test_Bar"; $test_data = array(array("L4" => 'A', "L3" => "X", "L2" => "K", "L1" => 1, "L0" => null), array("L4" => 'A', "L3" => "X", "L2" => "K", "L1" => 2, "L0" => false), array("L4" => 'A', "L3" => "X", "L2" => "K", "L1" => 5, "L0" => true), array("L4" => 'A', "L3" => "X", "L2" => "Z", "L1" => 3, "L0" => (int) 0), array("L4" => 'A', "L3" => "Y", "L2" => "K", "L1" => 1, "L0" => (int) 1), array("L4" => 'A', "L3" => "Y", "L2" => "K", "L1" => 2, "L0" => (int) -1), array("L4" => 'A', "L3" => "Y", "L2" => "K", "L1" => 3, "L0" => (double) 1.7), array("L4" => 'A', "L3" => "Y", "L2" => "Z", "L1" => 4, "L0" => (double) -1.6), array("L4" => 'B', "L3" => "X", "L2" => "K", "L1" => 1, "L0" => (string) "foo"), array("L4" => 'B', "L3" => "X", "L2" => "K", "L1" => 2, "L0" => array(null, true, false, 1, 1.0, "foo")), array("L4" => 'B', "L3" => "X", "L2" => "Z", "L1" => 3, "L0" => $test_obj)); // Load class with data // =============================================================== try { $rows_changed = $this->cls->setL1_multi($test_data, $ctrl = null); } catch (FOX_exception $child) { $this->fail($child->dumpString(array('depth' => 1, 'data' => true))); } // Should return (int)11 to indicate 11 keys were added $this->assertEquals(11, $rows_changed); // Check cache state // =============================================================== // NOTE: the LUT's won't be set at this point, because we haven't done any // database reads that give objects authority $check = array('A' => array('keys' => array('X' => array('K' => array(1 => null, 2 => false, 5 => true), 'Z' => array(3 => (int) 0)), 'Y' => array('K' => array(1 => (int) 1, 2 => (int) -1, 3 => (double) 1.7), 'Z' => array(4 => (double) -1.6)))), 'B' => array('keys' => array('X' => array('K' => array(1 => (string) "foo", 2 => array(null, true, false, 1, 1.0, "foo")), 'Z' => array(3 => $test_obj))))); $this->assertEquals($check, $this->cls->cache); // Check db state // =============================================================== $check = array('A' => array('X' => array('K' => array(1 => null, 2 => false, 5 => true), 'Z' => array(3 => (int) 0)), 'Y' => array('K' => array(1 => (int) 1, 2 => (int) -1, 3 => (double) 1.7), 'Z' => array(4 => (double) -1.6))), 'B' => array('X' => array('K' => array(1 => (string) "foo", 2 => array(null, true, false, 1, 1.0, "foo")), 'Z' => array(3 => $test_obj)))); $db = new FOX_db(); $columns = null; $args = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('L4', 'L3', 'L2', 'L1')); try { $result = $db->runSelectQuery($this->cls->_struct(), $args, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals($check, $result); }
/** * Drops all groups for a single user_id from the database and cache. Generally * used when deleting user profiles. * * @version 1.0 * @since 1.0 * * @param int $user_id | ID of the user * @return bool | False on failure. Number of rows affected on success. */ public function dropUser($user_id) { global $fox; $db = new FOX_db(); $args = array(array("col" => "user_id", "op" => "=", "val" => $user_id)); try { $rows_changed = $db->runDeleteQuery(self::$struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } unset($this->cache[$user_id]); $cache_ok = $fox->cache->del("FOX_uGroupMember", $user_id); if ($cache_ok) { return $rows_changed; } else { return false; } }
/** * Test fixture for dropMulti() method, matrix mode, hot cache * * @version 1.0 * @since 1.0 * * ======================================================================================= */ public function test_dropMulti_matrix_HOT() { self::loadData(); // Load the cache // #################################################################### $request = array('A' => array(), 'B' => array(), 'C' => array()); $valid = false; try { $result = $this->cls->getMulti($request, $ctrl, $valid); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } // HOT CACHE - All items in cache have authority from previous GET operation // =================================================================== // Drop objects // #################################################################### $data = array(array("L3" => 'A', "L2" => "X", "L1" => 1), array("L3" => 'A', "L2" => "Y"), array("L3" => 'B'), array("L3" => 'C')); $ctrl = array('validate' => true, 'mode' => 'matrix', 'trap_*' => true); try { $rows_changed = $this->cls->dropMulti($data, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } // Should return (int)1 to indicate 18 rows were dropped $this->assertEquals(16, $rows_changed); // Verify db state // #################################################################### $db = new FOX_db(); $columns = null; $args = null; $ctrl = array('format' => 'array_key_array', 'key_col' => array('L3', 'L2', 'L1')); try { $result = $db->runSelectQuery($this->cls->_struct(), $args, $columns, $ctrl); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } // NOTE: the datastore will automatically clip empty branches $check = array('A' => array('X' => array(2 => false, 3 => (int) 0, 5 => true))); $this->assertEquals($check, $result); // Check cache state // #################################################################### // Since we're working with a hot cache, the all_cached flag will be set for all // nodes that already exist in the database. The L2 and L3 LUT's for these // nodes will be missing, because the all_cached flag takes priority. // PASS 1: Check the L4 nodes individually to simplify debugging // ==================================================================== $check_cache_A = array('all_cached' => true, 'L2' => null, 'keys' => array('X' => array(2 => false, 3 => (int) 0, 5 => true))); $this->assertEquals($check_cache_A, $this->cls->cache['A']); // PASS 2: Combine the L4 nodes into a single array and check it // again. This finds L4 keys that aren't supposed to be there. // ==================================================================== $check_cache = array('A' => $check_cache_A); $this->assertEquals($check_cache, $this->cls->cache); // Verify persistent cache state by reading-back all items // #################################################################### $request = array('A' => array(), 'B' => array(), 'C' => array()); $valid = false; try { $result = $this->cls->getMulti($request, $ctrl, $valid); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(false, $valid); // Should report invalid because // the '2' and '3' L4's don't exist $this->assertEquals($check, $result); }
function test_deleteItem_multi_withMedias() { // Clear the albums table, medias table, and caches // =================================================== $this->alb->truncate(); $this->alb->flushCache(); $this->med->truncate(); $this->med->flushCache(); // Load albums class with test data // =================================================== $test_data = array(array('date_created' => "2011-01-01 15:14:13", 'title' => "Test Title", 'caption' => "Test Caption", 'privacy' => 3, 'module_id' => 1), array('date_created' => "2011-01-01 15:14:14", 'title' => "Test Title", 'caption' => "Test Caption", 'privacy' => 2, 'module_id' => 1), array('date_created' => "2011-01-01 15:14:15", 'title' => "Test Title", 'caption' => "Test Caption", 'privacy' => 1, 'module_id' => 2)); $result = $this->alb->addItemMulti($user_id = 1, $test_data, $error); $this->assertEquals(true, $result, FOX_debug::formatError_print($error)); // Add media items to test albums // =================================================== $test_data = array('owner_id' => 1, 'album_id' => 1, 'title' => "Test Media Title 01", 'caption' => "Test Media Caption 01", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(1, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 1, 'title' => "Test Media Title 02", 'caption' => "Test Media Caption 02", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(2, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 1, 'title' => "Test Media Title 03", 'caption' => "Test Media Caption 03", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(3, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 2, 'title' => "Test Media Title 04", 'caption' => "Test Media Caption 04", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(4, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 2, 'title' => "Test Media Title 05", 'caption' => "Test Media Caption 05", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(5, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 2, 'title' => "Test Media Title 06", 'caption' => "Test Media Caption 06", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(6, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 3, 'title' => "Test Media Title 07", 'caption' => "Test Media Caption 07", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(7, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 3, 'title' => "Test Media Title 08", 'caption' => "Test Media Caption 08", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(8, $result, FOX_debug::formatError_print($error)); $test_data = array('owner_id' => 1, 'album_id' => 3, 'title' => "Test Media Title 09", 'caption' => "Test Media Caption 09", 'date_created' => "2011-02-02 17:18:19", 'module_slug' => "slug_01"); $result = $this->med->addItem($test_data, $media_object, $error); $this->assertEquals(9, $result, FOX_debug::formatError_print($error)); // Delete albums // =================================================== $result = $this->alb->deleteItem($user_id = 1, $album_id = array(1, 3), $error); $this->assertEquals(2, $result, FOX_debug::formatError_print($error)); // Verify albums were deleted // =================================================== $result = $this->alb->get(array(1, 2, 3)); $check_array = array(new FOX_album(array("id" => 2, 'owner_id' => 1, 'cover_image' => 4, 'display_order' => array(4, 5, 6), 'date_created' => "2011-01-01 15:14:14", 'title' => "Test Title", 'caption' => "Test Caption", 'privacy' => 2, 'module_id' => 1))); $this->assertEquals($check_array, $result); // Verify medias were deleted // =================================================== $db = new FOX_db(); $args = array(array("col" => "owner_id", "op" => "=", "val" => 1)); $ctrl = array("format" => "array_array"); $db_result = $db->runSelectQuery(FOX_media::_struct(), $args, $columns = null, $ctrl); $check_data = array(array("id" => 4, 'owner_id' => 1, 'album_id' => 2, 'date_created' => "2011-02-02 17:18:19", 'title' => "Test Media Title 04", 'caption' => "Test Media Caption 04", 'privacy' => 2, 'module_id' => 1, 'pixels_x' => 1000, 'pixels_y' => 2000, 'bytes_master' => 1111, 'module_id' => 1, 'master_id' => "ABC1111"), array("id" => 5, 'owner_id' => 1, 'album_id' => 2, 'date_created' => "2011-02-02 17:18:19", 'title' => "Test Media Title 05", 'caption' => "Test Media Caption 05", 'privacy' => 2, 'module_id' => 1, 'pixels_x' => 1000, 'pixels_y' => 2000, 'bytes_master' => 1111, 'module_id' => 1, 'master_id' => "ABC1111"), array("id" => 6, 'owner_id' => 1, 'album_id' => 2, 'date_created' => "2011-02-02 17:18:19", 'title' => "Test Media Title 06", 'caption' => "Test Media Caption 06", 'privacy' => 2, 'module_id' => 1, 'pixels_x' => 1000, 'pixels_y' => 2000, 'bytes_master' => 1111, 'module_id' => 1, 'master_id' => "ABC1111")); $this->assertEquals($check_data, $db_result); }
function test_dropId_Multi() { // load db // ====================================================== $add_tokens = array("one", "two", "three", "four", "five"); try { $add_result = $this->cls->addToken($add_tokens); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "addToken exception", 'data' => array("tokens" => $add_tokens), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); return false; } // Test single dropId // ====================================================== try { $drop_ids = array(1, 2, 3, 4, 5); $this->assertEquals(5, $this->cls->dropId($drop_ids)); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "dropId exception", 'data' => array("drop ids" => $drop_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); return false; } // Check Db has no rows // ====================================================== try { $db = new FOX_db(); $this->assertEquals(false, $db->runSelectQuery(FOX_test_dictionary::$struct)); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "DB select exception", 'data' => array("ctrl" => array("count" => true, "format" => "var")), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); return false; } // Check Class cache is empty $this->assertEquals(array('ids' => array(), 'tokens' => array()), $this->cls->cache); }
/** * Removes one or more modules from the database and cache. * * @version 1.0 * @since 1.0 * @param int/array $module_ids | Single module_id as int. Multiple module_id's as array of int. * @return int | Exception on failure. Int number of db rows changed on success. */ public function dropModule($module_ids) { $db = new FOX_db(); $struct = self::_struct(); if (empty($module_ids)) { throw new FOX_exception(array('numeric' => 1, 'text' => "Invalid module_ids parameter", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!is_array($module_ids)) { // Handle single int as input $module_ids = array($module_ids); } // Lock the cache // =========================================================== try { $cache_image = self::lockCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Error locking cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the database // =========================================================== $args = array(array("col" => "module_id", "op" => "=", "val" => $module_ids)); try { $rows_changed = $db->runDeleteQuery($struct, $args, $ctrl = null); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error deleting from database", 'data' => array('args' => $args), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the persistent cache // =========================================================== if (!$rows_changed) { // If no rows were changed, we can just write-back the // cache image to release our lock try { self::writeCache($cache_image); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Error writing to cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } else { // If rows were changed, we have to flush the entire cache try { self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "Error flushing cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } return (int) $rows_changed; }
/** * Deletes the entire user data store, and flushes the cache. Generally * used for testing and debug. * * @version 1.0 * @since 1.0 * * @return bool | False on failure. True on success. */ public function dropAll(&$error = null) { global $rad; $db = new FOX_db(); try { $query_ok = $db->runTruncateTable(self::$struct); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Error while clearing the database", 'data' => null, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Since this operation affects *all* user_id's, we have to flush the cache try { $cache_ok = self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Cache flush exception", 'data' => null, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($cache_ok) { return true; } else { return false; } }
/** * Deletes a single group, given its group_id * * @version 1.0 * @since 1.0 * * @param int $group_id | id of the group * @return bool | False on failure. True on success. */ public function deleteGroup($group_id) { global $fox; $db = new FOX_db(); $columns = array("mode" => "include", "col" => array("is_default", "name")); $ctrl = array("format" => "row_array"); try { $group = $db->runSelectQueryCol(self::$struct, "group_id", "=", $group_id, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB select exception", 'data' => array("data" => $data, "col" => "group_id", "op" => "=", "val" => $group_id, "columns" => $columns, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // If the group we're trying to delete is the default group, reject the action. There must *always* be a // default group on the system. If the admin wants to delete the default group, they have to make // another group the default group first. if ($group["is_default"] == true) { //echo "\nclass.user.group.types::deleteGroup() - attempted delete on default group\n"; return false; } // Trap trying to delete a nonexistent group if (!$group) { //echo "\nclass.user.group.types::deleteGroup() - attempted delete on nonexistent group: $group_id \n"; return false; } // Get the user_id of every user in the group we're deleting $columns = array("mode" => "include", "col" => "user_id"); $ctrl = array("format" => "col"); try { $user_ids = $db->runSelectQueryCol(FOX_uGroupMember::_struct(), "group_id", "=", $group_id, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "DB select exception", 'data' => array("data" => $data, "col" => "group_id", "op" => "=", "val" => $group_id, "columns" => $columns, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // CASE 1: There are users that are members of the group // =============================================================================== if ($user_ids) { // Load all of the groups that each user is currently in, except // the group we're removing them from $args = array(array("col" => "user_id", "op" => "=", "val" => $user_ids), array("col" => "group_id", "op" => "!=", "val" => $group_id)); $ctrl = array("format" => "array_key_array_grouped", "key_col" => array("user_id", "group_id")); try { $in_groups = $db->runSelectQuery(FOX_uGroupMember::_struct(), $args, $columns = null, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "DB select exception", 'data' => array("args" => $args, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // @@@@@@ BEGIN TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ try { $started_transaction = $db->beginTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "beginTransaction exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($started_transaction) { $keys_ok = true; try { $gk = new FOX_uGroupKeyRing(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "FOX_uGroupKeyRing constructor exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } foreach ($user_ids as $user) { // Get the combined keyring of all the user's other groups try { $keep_keys = $gk->getKeys($in_groups[$user]); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "FOX_uGroupKeyRing getKeys exception", 'data' => array("user" => $in_groups[$user]), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Get the keyring of the group we're removing the user from try { $drop_keys = $gk->getKeys($group_id); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 6, 'text' => "FOX_uGroupKeyRing getKeys exception", 'data' => array("group_id" => $group_id), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Intersect the $keep_keys and $drop_keys arrays to get // a list of keys we need to revoke from the user if ($keep_keys && $drop_keys) { $revoke_keys = array_diff($drop_keys, $keep_keys); } else { $revoke_keys = $drop_keys; } // Revoke all the keys we previously calculated if ($revoke_keys) { $ks = new FOX_uKeyRing(); try { $revoke_ok = $ks->revokeKey($user, $revoke_keys); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 7, 'text' => "FOX_uKeyRing revokeKeys exception", 'data' => array("user" => $user, "revoke_keys" => $revoke_keys), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if (!$revoke_ok) { $keys_ok = false; } } else { // Handle no keys to revoke $keys_ok = true; } } unset($user); // Because we are inside a transaction, we have to directly delete items from // the other class's db tables. If we deleted items using the other class's // functions, the other classes would remove them from their caches before we // could confirm all steps in the transaction were successful. // ============================================================================ // Drop the group-user pairs from the group members table $args = array(array("col" => "group_id", "op" => "=", "val" => $group_id)); try { $gm_ok = $db->runDeleteQuery(FOX_uGroupMember::_struct(), $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 8, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Drop the group-key pairs from the group keyring table $args = array(array("col" => "group_id", "op" => "=", "val" => $group_id)); try { $gk_ok = $db->runDeleteQuery(FOX_uGroupKeyRing::_struct(), $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 9, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Drop the group from the group types table $args = array(array("col" => "group_id", "op" => "=", "val" => $group_id)); try { $gt_ok = $db->runDeleteQuery(self::$struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 10, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the cache if ($keys_ok && $gm_ok !== false && $gk_ok !== false && $gt_ok) { // Handle groups with no members and // groups with no keys returning (int)0 try { $commit_ok = $db->commitTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 11, 'text' => "commitTransaction exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($commit_ok) { // Because we directly modified other class's db tables, we have to // flush the cache for the affected classes try { $fox->cache->flushNamespace("FOX_uGroupMember"); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 12, 'text' => "FOX_uGroupMember flushNamespace exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } try { $fox->cache->flushNamespace("FOX_uGroupKeyRing"); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 13, 'text' => "FOX_uGroupKeyRing flushNamespace exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Load, update, writeback try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 14, 'text' => "FOX_uGroupKeyRing getKeys exception", 'data' => array("user" => $group_id), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } unset($this->cache["ids"][$group["name"]]); $cache_ok = self::saveCache(); return $cache_ok; } else { return false; } } } else { // If we couldn't start a transaction, return false return false; } // @@@@@@ END TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } else { // @@@@@@ BEGIN TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ try { $started_transaction = $db->beginTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 15, 'text' => "beginTransaction exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($started_transaction) { // Because we are inside a transaction, we have to directly delete items from // the other class's db tables. If we deleted items using the other class's // functions, the other classes would remove them from their caches before we // could confirm all steps in the transaction were successful. // ============================================================================ // Drop the group-key pairs from the group keyring table $args = array(array("col" => "group_id", "op" => "=", "val" => $group_id)); try { $gk_ok = $db->runDeleteQuery(FOX_uGroupKeyRing::_struct(), $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 16, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Drop the group from the group types table $args = array(array("col" => "group_id", "op" => "=", "val" => $group_id)); try { $gt_ok = $db->runDeleteQuery(self::$struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 17, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the cache if ($gk_ok !== false && $gt_ok) { // Handle groups with no keys // returning (int)0 try { $commit_ok = $db->commitTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 18, 'text' => "commitTransaction exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($commit_ok) { // Because we directly modified another class's db table, we // have to flush the cache for the affected class try { $fox->cache->flushNamespace("FOX_uGroupKeyRing"); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "FOX_uGroupKeyRing flushNamespace exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Load, update, writeback try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 19, 'text' => "loadCache exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } unset($this->cache["ids"][$group["name"]]); try { $cache_ok = self::saveCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 20, 'text' => "saveCache exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } return $cache_ok; } else { return false; } } } else { // If we couldn't start a transaction, return false return false; } // @@@@@@ END TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } // It might be possible to do this using a sophisticated query // Remove all keys granted by the group, from every user on the site, unless another group grants // the key, and the user is a member of that other group // ======================================================== // DELETE kst // FROM user_keystore_table AS kst // INNER JOIN group_members_table AS gmt ON kst.user_id = gmt.user_id // user has to be a member of the deleted group // INNER JOIN group_keyring_table AS gkt ON gmt.group_id = gkt.group_id // key has to be granted by the deleted group // WHERE kst.key_id NOT IN (SELECT key_id // FROM group_keyring_table AS gkt2 // INNER JOIN group_members_table AS gmt2 ON gkt2.group_id = gmt2.group_id // WHERE gmt2.group_id != gmt.group_id // where the key does not belong to another group // AND gmt2.user_id = gmt.user_id ) // and the user is a member of that group // AND gkt.group_id = [this group] // AND gmt.group_id = [this group] // ...It also might be possible to do this using MySQL "foreign keys" }
/** * Deletes an entire tree of keys * * @version 1.0 * @since 1.0 * * @param string $tree | The tree name * @return bool | False on failure. True on success. */ public function dropTree($tree) { global $fox; $db = new FOX_db(); // Fetch the key_id's for all matching keys from the db $args = array(array("col" => "tree", "op" => "=", "val" => $tree)); $columns = array("mode" => "include", "col" => array("key_id")); $ctrl = array("format" => "col"); try { $drop_ids = $db->runSelectQuery(self::$struct, $args, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB select exception", 'data' => array("args" => $args, "columns" => $columns, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // @@@@@@ BEGIN TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ try { $started_transaction = $db->beginTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "beginTransaction exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($started_transaction) { $args = array(array("col" => "key_id", "op" => "=", "val" => $drop_ids)); try { $db->runDeleteQuery(self::$struct, $args); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "DB delete exception", 'data' => $args, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // TODO: // 1) drop the keys from the user keystore // 2) purge the dropped keys from the user keystore cache // 3) drop the keys from all groups that grant them try { $query_ok = $db->commitTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "commitTransaction exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } else { $query_ok = false; } // @@@@@@ END TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // Update the cache if ($query_ok) { // Update the class cache from the persistent cache try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "loadCache exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Flush the deleted branch from the class cache unset($this->cache["keys"][$tree_name]); unset($this->cache["branches"][$tree_name]); unset($this->cache["trees"][$tree_name]); // Write the updated class cache array to the persistent cache try { $cache_ok = self::saveCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 6, 'text' => "saveCache exception", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } return $cache_ok; } else { return false; } }
/** * Deletes an existing user class. Users in this class will be moved to the class's "transfer_to" * class. If the "transfer_to" class was not set, users will be moved to the site's "default" class. * * @version 1.0 * @since 1.0 * * @param int $id | id of this class to delete * @return bool/int | False on failure. Numer of affected users on success. */ public function deleteClass($id) { // Fetch the db entry for this user class // ============================================================================================ $db = new FOX_db(); $columns = array("format" => "include", "col" => array("id", "is_default", "transfer_to")); $ctrl = array("format" => "row_array"); try { $result = $db->runSelectQueryCol(self::$struct, "id", "=", $id, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB select exception", 'data' => array("col" => "id", "op" => "=", "val" => $id, "columns" => $columns, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Trap user trying to delete the default class // ============================================================================================ if ($result["is_default"] == true) { echo "\nERROR: You cannot delete a class that is set as the default user class. To delete this "; echo "class, set another class as the default class, then come back and delete this one.\n"; die; } // If the old class has a "transfer_to" class, use it. If the old class doesn't list a // "transfer_to" class, find the class that has the "default" flag, and use that class instead. // ============================================================================================ if (!empty($result["transfer_to"])) { $dest_class = $result["transfer_to"]; } else { $columns = array("format" => "include", "col" => "id"); $ctrl = array("format" => "var"); try { $dest_class = $db->runSelectQueryCol(self::$struct, "is_default", "=", true, $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "DB select exception", 'data' => array("col" => "is_default", "op" => "=", "val" => true, "columns" => $columns, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } // Run the update query // ============================================================================================ $update = array("user_class_id" => $dest_class, "when_class_set" => gmdate("Y-m-d H:i:s"), "when_class_expires" => null); try { $result = $db->runUpdateQueryCol(FOX_user::_struct(), $update, "user_class_id", "=", $id); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "DB update exception", 'data' => array("data" => $update, "col" => "usewr_class_id", "op" => "=", "val" => $id), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // TODO: Although this code will move the users to the new class and delete the old class, it will cause // huge problems if the classes have different limitations. For example, if the old class allowed video // uploads in albums, and the new class does not. Or if the old class allowed 10 instances of an album // type and the new one does not, etc. We need to come up with ways to resolve these problems. }