/** * Drops one or more items of the specified level from ALL WALKS in the datastore. * * @version 1.0 * @since 1.0 * @param int $level | Level to drop items from * @param int/string/array $items | Single item as int/string, multiple as array of int/string. * * @return int | Exception on failure. Number of rows changed on success. */ public function dropGlobal($level, $items, $ctrl = null) { if (!$this->init) { throw new FOX_exception(array('numeric' => 0, 'text' => "Descendent class must call init() before using class methods", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } 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()))))); } $col = "L" . $level . "_col"; $ctrl_default = array("validate" => true); $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default); // Validate // =================================================== if ($ctrl['validate'] != false) { if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "validate_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } // Each variable has to be validated individually. If we spin the variables // into a trie, PHP will automatically convert strings that map to ints ("17") // into (int) keys, which will defeat the validators $struct = $this->_struct(); try { $validator = new FOX_dataStore_validator($struct); // If a single item is sent in, we validate it *before* spinning it into an array, // so we can trap strings that PHP automatically converts to ints ("17") if (!is_array($items)) { $is_valid = $validator->validateKey(array('type' => $struct['columns'][$this->{$col}]['php'], 'format' => 'scalar', 'var' => $items)); } else { foreach ($items as $key => $val) { $is_valid = $validator->validateKey(array('type' => $struct['columns'][$this->{$col}]['php'], 'format' => 'scalar', 'var' => $val)); // Break the loop if we hit an invalid key if ($is_valid !== true) { break; } } unset($key, $val); } } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Error in validator", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // This structure has to be outside the validator try-catch block to prevent it from // catching the exceptions we throw (which would cause confusing exception chains) if ($is_valid !== true) { throw new FOX_exception(array('numeric' => 2, 'text' => "Invalid item", 'data' => $is_valid, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "validate_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } } // ENDOF: if($ctrl['validate'] != false){ // Lock the entire cache namespace // =========================================================== if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "persistent_cache_lock_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } try { self::lockNamespace(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error locking cache namespace", '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' => "persistent_cache_lock_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "db_delete_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } $args = array(array("col" => $this->{$col}, "op" => "=", "val" => $items)); try { $rows_changed = $this->db->runDeleteQuery($struct, $args, $ctrl = null); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Error while deleting from database", 'data' => $args, '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' => "db_delete_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } // Since this operation affects ALL L5 pages, we have to flush the // entire cache namespace if ($this->debug_on) { extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "persistent_cache_flush_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } try { self::flushCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "Cache flush error", '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' => "persisent_cache_flush_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars()))))); } 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 (int) $rows_changed; }
/** * Test fixture for validateKey() method * * @version 1.0 * @since 1.0 * * ======================================================================================= */ public function test_validateKey() { $struct = array("table" => "FOX_dataStore_validators", "engine" => "InnoDB", "cache_namespace" => "FOX_dataStore_validators", "cache_strategy" => "paged", "cache_engine" => array("memcached", "redis", "apc", "thread"), "columns" => array("X3" => array("php" => "int", "sql" => "int", "format" => "%d", "width" => null, "flags" => "NOT NULL", "auto_inc" => false, "default" => null, "index" => true), "X2" => array("php" => "string", "sql" => "varchar", "format" => "%s", "width" => 32, "flags" => "NOT NULL", "auto_inc" => false, "default" => null, "index" => true), "X1" => array("php" => "int", "sql" => "int", "format" => "%d", "width" => null, "flags" => "NOT NULL", "auto_inc" => false, "default" => null, "index" => true), "X0" => array("php" => "serialize", "sql" => "longtext", "format" => "%s", "width" => null, "flags" => "", "auto_inc" => false, "default" => null, "index" => false))); $cls = new FOX_dataStore_validator($struct); // SCALAR INT // ################################################################# // PASS on scalar int when scalar int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'scalar', 'var' => 7)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $result); // FAIL on string when scalar int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'scalar', 'var' => 'foo')); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on int equivalent string when scalar int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'scalar', 'var' => '17')); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on null when scalar int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'scalar', 'var' => null)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on int array when scalar int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'scalar', 'var' => array(1, 2))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on empty array when scalar int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'scalar', 'var' => array())); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // ARRAY INT // ################################################################# // PASS on array int when array int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => array(7))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $result); // PASS on empty array when array int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => array())); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $result); // FAIL on null when array int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => null)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on scalar int when array int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => 7)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on array string when array int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => array('foo', 'bar'))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on array mixed when array int expected // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => array(1, 'bar', 7, 8))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on int equivalent string keys // =========================================== try { $result = $cls->validateKey(array('type' => 'int', 'format' => 'array', 'var' => array(1, '2', 7, 8))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // SCALAR STRING // ################################################################# // PASS on scalar string when scalar string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'scalar', 'var' => 'foo')); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $result); // FAIL on int when scalar string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'scalar', 'var' => 7)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on int equivalent string when scalar string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'scalar', 'var' => '17')); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on null when scalar string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'scalar', 'var' => null)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on string array when scalar string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'scalar', 'var' => array('foo', 'bar'))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on empty array when scalar string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'scalar', 'var' => array())); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // ARRAY STRING // ################################################################# // PASS on array string when array string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => array('foo'))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $result); // PASS on empty array when array string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => array())); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertEquals(true, $result); // FAIL on null when array string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => null)); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on scalar string when array string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => 'foo')); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on array int when array string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => array(1, 2))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on array mixed when array string expected // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => array('foo', 'bar', 7, 'baz'))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // FAIL on int equivalent string keys // =========================================== try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'array', 'var' => array('A', '2', 'B', 'C'))); } catch (FOX_exception $child) { $this->fail($child->dumpString(1)); } $this->assertNotEquals(true, $result); // EXCEPTION - invalid 'type' parameter // #################################################################### try { $result = $cls->validateKey(array('type' => 'fail', 'format' => 'array', 'var' => array('A', '2', 'B', 'C'))); // Execution will halt on the previous line if validateKey() throws an exception $this->fail("Method validateKey() failed to throw an exception on invalid 'type' parameter"); } catch (FOX_exception $child) { } // EXCEPTION - invalid 'format' parameter // #################################################################### try { $result = $cls->validateKey(array('type' => 'string', 'format' => 'fail', 'var' => array('A', '2', 'B', 'C'))); // Execution will halt on the previous line if validateKey() throws an exception $this->fail("Method validateKey() failed to throw an exception on invalid 'format' parameter"); } catch (FOX_exception $child) { } }
/** * Deletes one or more plugins from the datastore * * @version 1.0 * @since 1.0 * * @param string/array $plugin | Single plugin as string. Multiple plugins as array of string. * @return int | Exception on failure. Number of db rows changed on success. */ public function dropPlugin($plugin) { $struct = $this->_struct(); $validator_result = array(); try { // All of the validator calls are wrapped in a single try{} block to reduce code size. If // a validator throws an exception, it will contain all info needed for debugging $validator = new FOX_dataStore_validator($struct); // If a single tree name is sent in, we validate it individually instead of automatically // spinning it into an array and validating the array. This lets us trap strings that PHP // automatically converts to ints ("17") if (!is_array($plugin)) { $validator_result['plugin'] = $validator->validateKey(array('type' => $struct['columns'][$this->L4_col]['php'], 'format' => 'scalar', 'var' => $plugin)); } else { foreach ($plugin as $key => $val) { $validator_result['plugin'] = $validator->validateKey(array('type' => $struct['columns'][$this->L4_col]['php'], 'format' => 'scalar', 'var' => $val)); if ($validator_result['plugin'] !== true) { break; } } unset($key, $val); } } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Error in validator class", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // This structure has to be outside the validator try-catch block to prevent it from // catching the exceptions we throw (which would cause confusing exception chains) foreach ($validator_result as $key => $val) { if ($val !== true) { throw new FOX_exception(array('numeric' => 2, 'text' => "Invalid " . $key . " name", 'data' => array('plugin' => $plugin, 'msg' => $val), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } } unset($key, $val); $drop_ctrl = array('validate' => false); try { $rows_changed = parent::dropL4($plugin, $drop_ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error calling parent::dropL4()", 'data' => array('plugin' => $plugin), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } return (int) $rows_changed; }