/** * Edits fields for an existing key, given the key's key_id * * @version 1.0 * @since 1.0 * * @param array $data | one or more arrays, each descrribing a key to create * => VAL @param int $key_id | key_id for the key to edit * => VAL @param string $tree | tree name for key (max 32 chars) * => VAL @param string $branch | branch name for key (max 32 chars) * => VAL @param string $name | name for key (max 32 chars) * => VAL @param string $descr | admin description for key (max 255 chars) * * @return bool | False on failure. True on success. */ public function editKey($data) { global $fox; $db = new FOX_db(); // Get the column values for the current key // ========================================= // Trap missing $key_id if (!$data["key_id"]) { return false; } $columns = array("mode" => "exclude", "col" => array("key_id")); $ctrl = array("format" => "row"); try { $old = $db->runSelectQueryCol(self::$struct, "key_id", "=", $data["key_id"], $columns, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "DB select exception", 'data' => array("col" => "key_id", "op" => "=", "val" => $data["key_id"], "columns" => $columns, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // If the key's $tree, $branch, or $name fields are being modified, check that a // key with the new combination does not already exist in the database // =================================================================================== $args = array(); // Tree // ========== if ($data["tree"] && $old["tree"] != $data["tree"]) { $args[] = array("col" => "tree", "op" => "=", "val" => $data["tree"]); $dupe_check_required = true; } else { $args[] = array("col" => "tree", "op" => "=", "val" => $old["tree"]); } // Branch // ========== if ($data["branch"] && $old["branch"] != $data["branch"]) { $args[] = array("col" => "branch", "op" => "=", "val" => $data["branch"]); $dupe_check_required = true; } else { $args[] = array("col" => "branch", "op" => "=", "val" => $old["branch"]); } // Name // ========== if ($data["name"] && $old["name"] != $data["name"]) { $args[] = array("col" => "name", "op" => "=", "val" => $data["name"]); $dupe_check_required = true; } else { $args[] = array("col" => "name", "op" => "=", "val" => $old["name"]); } if ($dupe_check_required) { $ctrl = array("count" => true, "format" => "var"); try { $key_exists = $db->runSelectQuery(self::$struct, $args, $columns = null, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "DB select exception", 'data' => array("args" => $args, "ctrl" => $ctrl), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } // If possible, update the key in the database // ========================================================== if ($key_exists) { // Changes to the "Tree", "Branch" or "Name" fields would create a // collision with a key that already exists in the database. throw new FOX_exception(array('numeric' => 3, 'text' => "FOX_uKeyType::editKey - Attempted to rename a key to a value that would create a collission with an existing key.", 'data' => array("tree" => $data['tree'], "branch" => $data['branch'], "key" => $data['name']), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } else { // Add the key to the db and persistent cache $args = array(array("col" => "key_id", "op" => "=", "val" => $data["key_id"])); $columns = array("mode" => "exclude", "col" => array("key_id")); try { $result = $db->runUpdateQuery(self::$struct, $data, $args, $columns); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "DB update exception", 'data' => array("data" => $data, "args" => $args, "columns" => $columns), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if ($result) { // 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 old class cache entry unset($this->cache["keys"][$old["tree"]][$old["branch"]][$old["name"]]); // Set the new class cache entry $this->cache["keys"][$data["tree"]][$data["branch"]][$data["name"]] = $data["key_id"]; // 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; } } }
/** * Updates the ranks of all levels within an object type * * @version 1.0 * @since 1.0 * * @param int $module_id | id of module that owns the object type * @param int $type_id | id of object type that owns the level id's * @param array $ranks | array of ranks to apply to the object type's access levels in the form "type_id"=>"rank" * * @return bool | Exception on failure. False on no change. True on success. */ public function setRanks($module_id, $type_id, $ranks) { $db = new FOX_db(); $result_array = array(); // Check that the $ranks array has no missing ranks // ======================================================================== asort($ranks); $rank_check = 1; foreach ($ranks as $rank) { if ($rank != $rank_check) { throw new FOX_exception(array('numeric' => 1, 'text' => "Missing rank key", 'data' => array('module_id' => $module_id, 'type_id' => $type_id, 'ranks' => $ranks), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } $rank_check++; } unset($rank, $rank_check); // If *all* of the levels for a type_id have been cached, there will be an // array containing it's level_id's in $this->cache["type_levels"][$type_id], // if it exists, we can use the cached data instead of querying the database // ======================================================================== if (FOX_sUtil::keyExists($this->cache["type_levels"], $type_id)) { $levels = $this->cache["type_levels"][$type_id]; foreach ($levels as $level_id) { $result_array[$level_id] = $this->cache["keys"][$level_id]; } unset($levels, $level_id); } else { try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } if (FOX_sUtil::keyExists($this->cache["type_levels"], $type_id)) { $levels = $this->cache["type_levels"][$type_id]; foreach ($levels as $level_id) { $result_array[$level_id] = $this->cache["keys"][$level_id]; } unset($levels, $level_id); } else { $args = array(array("col" => "module_id", "op" => "=", "val" => $module_id), array("col" => "type_id", "op" => "=", "val" => $type_id)); $ctrl = array("format" => "array_key_array", "key_col" => array("level_id")); try { $db_result = $db->runSelectQuery($this->_struct(), $args, $columns = null, $ctrl); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error reading from database", 'data' => array('args' => $args, 'ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } if ($db_result) { foreach ($db_result as $level_id => $row_data) { $result_array[$level_id] = $row_data; } unset($level_id, $row_data); } } } // Check the number of keys in the $ranks array matches the number of // levels that the object type has // ======================================================================== $ranks_count = count($ranks); $db_count = count($result_array); if ($ranks_count > $db_count) { throw new FOX_exception(array('numeric' => 4, 'text' => "Rank array has more keys than database", 'data' => array('ranks' => $ranks, 'result_array' => $result_array), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } elseif ($ranks_count < $db_count) { throw new FOX_exception(array('numeric' => 5, 'text' => "Rank array has less keys than database", 'data' => array('ranks' => $ranks, 'result_array' => $result_array), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } // @@@@@@ BEGIN TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ try { $db->beginTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 6, 'text' => "Couldn't initiate transaction", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Lock the cache // =============================== try { $cache_image = self::lockCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 7, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } $rows_changed = 0; foreach ($result_array as $level_id => $row_data) { if ($ranks[$level_id] != $row_data["rank"]) { $row_data["rank"] = $ranks[$level_id]; $args = array(array("col" => "module_id", "op" => "=", "val" => $module_id), array("col" => "type_id", "op" => "=", "val" => $type_id), array("col" => "level_id", "op" => "=", "val" => $level_id)); try { $rows_changed += (int) $db->runUpdateQuery($this->_struct(), $row_data, $args, $columns = null); } catch (FOX_exception $child) { try { $db->rollbackTransaction(); } catch (FOX_exception $child_2) { throw new FOX_exception(array('numeric' => 8, 'text' => "Error writing to database. Rollback failed.", 'data' => array('rollback_exception' => $child_2, 'args' => $args, 'columns' => $columns, 'ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } throw new FOX_exception(array('numeric' => 9, 'text' => "Error writing to database. Rollback successful.", 'data' => array('row_data' => $row_data, 'args' => $args), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } } unset($level_id, $row_data); try { $db->commitTransaction(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 10, 'text' => "Couldn't commit transaction", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // @@@@@@ END TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // Rebuild the cache image // ====================================== foreach ($result_array as $level_id => $row_data) { if ($ranks[$level_id] != $row_data["rank"]) { $row_data["rank"] = $ranks[$level_id]; $cache_image["slug_to_level_id"][$row_data["module_id"]][$row_data["type_id"]][$row_data["level_slug"]] = $level_id; $cache_image["keys"][$level_id] = $row_data; } } unset($level_id, $row_data); $cache_image["type_levels"][$type_id] = array_keys($ranks); // Update the persistent cache, releasing our lock // ================================================ try { self::writeCache($cache_image); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 11, 'text' => "Cache write error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } // Overwrite the class cache $this->cache = $cache_image; return (bool) $rows_changed; }
/** * Edits a a module's table entry * * @version 1.0 * @since 1.0 * * @param array $data | * => VAL @param string $location | Display location. * => VAL @param int/string $target | Module target. Must be (int) for pages, (string) for all other locations. * => VAL @param string $tab_title | Title for the module's tab (not used for pages). * => VAL @param int $tab_position | Tab position (0-255) (not used for pages). * => VAL @param int $module_id | Page module id. * * @return int | Exception on failure. Int number of rows changed on success. */ public function edit($data) { $db = new FOX_db(); $struct = self::_struct(); // Trap bad input // ============================================================= if (!$data["module_id"]) { throw new FOX_exception(array('numeric' => 1, 'text' => "Must supply module_id", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!$data["target"] && !$data["tab_title"] && !$data["tab_position"]) { throw new FOX_exception(array('numeric' => 2, 'text' => "Must supply at least 1 field to change", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } // Trap nonexistent module_id // ============================================================= try { $db_record = self::getID($data["module_id"]); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error in self::getID()", 'data' => $data["module_id"], 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } if (!$db_record) { throw new FOX_exception(array('numeric' => 4, 'text' => "Supplied module_id doesn't have a database record", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } $update = array(); // CASE 1: Changing the location // ============================================================= if ($data["location"] && $data["location"] != $db_record["location"]) { // CASE 1A: Changing from slug to page // ------------------------------------------ if ($data["location"] == "page") { if (!$data["target"]) { throw new FOX_exception(array('numeric' => 5, 'text' => "Target must be set when changing location from a slug to a page", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!is_int($data["target"])) { throw new FOX_exception(array('numeric' => 6, 'text' => "Attempted to use non-int value as a page target", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } $update["location"] = $data["location"]; $update["target"] = (int) $data["target"]; $update["tab_title"] = null; $update["tab_position"] = null; } elseif ($db_record["location"] == "page") { if (!$data["target"]) { throw new FOX_exception(array('numeric' => 7, 'text' => "Target must be set when changing location from a page to a slug", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!$data["tab_title"] || !$data["tab_position"]) { throw new FOX_exception(array('numeric' => 8, 'text' => "The tab_title and tab_position fields must be set when changing location from a page to a slug", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!is_int($data["tab_position"])) { throw new FOX_exception(array('numeric' => 9, 'text' => "Attempted to use non-int value as a tab position", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } $update["location"] = $data["location"]; $update["target"] = (string) $data["target"]; $update["tab_title"] = (string) $data["tab_title"]; $update["tab_position"] = (int) $data["tab_position"]; } else { $update["location"] = $data["location"]; if ($data["target"]) { $update["target"] = (string) $data["target"]; } if ($data["tab_title"]) { $update["tab_title"] = (string) $data["tab_title"]; } if ($data["tab_position"]) { if (!is_int($data["tab_position"])) { throw new FOX_exception(array('numeric' => 10, 'text' => "Attempted to use non-int value as a tab position", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } $update["tab_position"] = (int) $data["tab_position"]; } } } else { // CASE 2A: Editing a page // ------------------------------------------ if ($db_record["location"] == "page") { if ($data["target"]) { if (!is_int($data["target"])) { throw new FOX_exception(array('numeric' => 11, 'text' => "Attempted to use non-int value as a page target", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } $update["target"] = (int) $data["target"]; } } else { if ($data["target"]) { $update["target"] = (string) $data["target"]; } if ($data["tab_title"]) { $update["tab_title"] = (string) $data["tab_title"]; } if ($data["tab_position"]) { if (!is_int($data["tab_position"])) { throw new FOX_exception(array('numeric' => 12, 'text' => "Attempted to use non-int value as a tab position", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } $update["tab_position"] = (int) $data["tab_position"]; } } } // Lock the cache // =========================================================== try { $cache_image = self::lockCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 13, 'text' => "Error locking cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the database // =========================================================== $args = array(array("col" => "module_id", "op" => "=", "val" => $data["module_id"])); $columns = array("mode" => "exclude", "col" => array("module_id")); try { $rows_changed = $db->runUpdateQuery($struct, $update, $args, $columns); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 14, 'text' => "Error writing to database", 'data' => array('update' => $update, 'args' => $args, 'columns' => $columns), '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' => 15, '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' => 16, 'text' => "Error flushing cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } return (int) $rows_changed; }
/** * Edits a module_slug table entry * * @version 1.0 * @since 1.0 * * @param array $data | * => VAL @param string $module_type | module type * => VAL @param int $module_id | id of the module * => VAL @param string $php_class | PHP class for the page module * => VAL @param int $module_slug | module module_slug * * @return int | Exception on failure. Int number of rows changed on success. */ public function edit($data) { $db = new FOX_db(); $struct = self::_struct(); // Trap bad input // ============================================================= if (!$data["module_type"] || !$data["module_id"]) { throw new FOX_exception(array('numeric' => 1, 'text' => "Must supply module_type and module_id", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } if (!$data["php_class"] && !$data["module_slug"]) { throw new FOX_exception(array('numeric' => 2, 'text' => "Must specify either php_class or module_slug", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } // Lock the cache // =========================================================== try { self::lockCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error locking cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // Update the database // =========================================================== $update = array(); if ($data["module_slug"]) { $update["module_slug"] = $data["module_slug"]; } if ($data["php_class"]) { $update["php_class"] = $data["php_class"]; } $args = array(array("col" => "module_type", "op" => "=", "val" => $data["module_type"]), array("col" => "module_id", "op" => "=", "val" => $data["module_id"])); $columns = array("mode" => "exclude", "col" => array("module_type", "module_id")); try { $rows_changed = $db->runUpdateQuery($struct, $update, $args, $columns); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Error updating database", 'data' => array('update' => $update, 'args' => $args, 'columns' => $columns), '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' => 5, 'text' => "Error flushing cache", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } return (int) $rows_changed; }