/** * Fetches a key, branch, tree, or an entire user's keystore from the key cache. * * If an object is not in the cache yet, it will be retrieved from the database * and added to the cache. Multiple items in the *lowest level group* specified * can be retrieved in a single query by passing their names or id's as an array. * * WRONG: get( $id=1, $tree = array(3, 6, 7, 2), $branch=7, $key="gender") * ^^^^^^^^^^^^^^^^^^^^^^^^ * RIGHT: get( $id=1, $tree=2, $branch=7, $key=array("fans","likes","gender") * * @version 1.0 * @since 1.0 * * @param int/array $user_id | Single $user_id as int. Multiple as array of ints. * @param int/array $tree | Single $tree as int. Multiple as array of ints. * @param int/array $branch | Single $branch as int. Multiple as array of ints. * @param string/array $key | Single key name as string. Multiple as array of strings. * @param bool &$valid | True if the object exists. False if not. * @param array &$error | Array containing numeric and text error information * @return bool | False on failure. True on success. */ public function get($user_id, $tree = null, $branch = null, $key = null, &$valid = null) { global $rad; $db = new FOX_db(); $args = array(); // Key or group of keys // ============================= if ($user_id && $tree && $branch && $key) { if (is_array($user_id) || is_array($tree) || is_array($branch)) { throw new FOX_exception(array('numeric' => 1, 'text' => "Attempted to pass multiple user id's, tree's, or branches when specifying key", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } // If the user_id is not present in the class cache array, try to load it // from the persistent cache if (!$this->cache[$user_id]) { try { $this->cache[$user_id] = $rad->cache->get("FOX_uData", $user_id, $valid); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Cache get exception", 'data' => array("user_id" => $user_id, "tree" => $tree, "branch" => $branch, "key" => $key), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } // Single key if (!is_array($key)) { $single = true; $key = array($key); } else { $single = false; } // Find all the keys that have been requested but are not in the cache $missing_keys = array(); $branch_cached = FOX_sUtil::keyTrue($branch, $this->cache[$user_id]["branch"][$tree]); $tree_cached = FOX_sUtil::keyTrue($tree, $this->cache[$user_id]["tree"]); $user_cached = FOX_sUtil::keyTrue("all_cached", $this->cache[$user_id]); if (!$branch_cached && !$tree_cached && !$user_cached) { foreach ($key as $key_name) { if (!FOX_sUtil::keyExists($key_name, $this->cache[$user_id]["keys"][$tree][$branch])) { $missing_keys[] = $key_name; } } unset($key_name); } // Load missing keys if (count($missing_keys) != 0) { try { $this->load($user_id, $tree, $branch, $missing_keys, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Load exception", 'data' => array("user_id" => $user_id, "tree" => $tree, "branch" => $branch, "missing_keys" => $missing_keys), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } $result = array(); // Build an array of the requested keys foreach ($key as $key_name) { if (FOX_sUtil::keyExists($key_name, $this->cache[$user_id]["keys"][$tree][$branch])) { $result[$key_name] = $this->cache[$user_id]["keys"][$tree][$branch][$key_name]; } else { $result[$key_name] = null; } } unset($key_name); // Only set the $valid flag true if every requested key was successfully fetched if (count($result) == count($key)) { $valid = true; } else { $valid = false; } // If only one key was requested, and the key was successfully retrieved from the db, // lift the result array up one level if ($single == true && count($result) == 1) { $result = $result[$key[0]]; } return $result; } elseif ($user_id && $tree && $branch && !$key) { if (is_array($user_id) || is_array($tree)) { throw new FOX_exception(array('numeric' => 4, 'text' => "Attempted to pass multiple user id's or tree's when specifying branch", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } // If the user_id is not present in the class cache array, try to load it // from the persistent cache if (!$this->cache[$user_id]) { try { $this->cache[$user_id] = $rad->cache->get("FOX_uData", $user_id, $valid); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "Cache get exception", 'data' => array("user_id" => $user_id, "tree" => $tree, "branch" => $branch), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } // Single branch if (!is_array($branch)) { $single = true; $branch = array($branch); } else { $single = false; } // Find all the branches that have been requested but are not in the cache $missing_branches = array(); foreach ($branch as $branch_name) { $branch_cached = FOX_sUtil::keyTrue($branch_name, $this->cache[$user_id]["branch"][$tree]); $tree_cached = FOX_sUtil::keyTrue($tree_name, $this->cache[$user_id]["tree"]); $user_cached = FOX_sUtil::keyTrue("all_cached", $this->cache[$user_id]); if (!$branch_cached && !$tree_cached && !$user_cached) { $missing_branches[] = $branch_name; } } unset($branch_name); // Load missing branches if (count($missing_branches) != 0) { try { $this->load($user_id, $tree, $missing_branches, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 6, 'text' => "Load exception", 'data' => array("user_id" => $user_id, "tree" => $tree, "missing_branches" => $missing_branches), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } $result = array(); // Build an array of the requested branches foreach ($branch as $branch_name) { if (FOX_sUtil::keyExists($branch_name, $this->cache[$user_id]["keys"][$tree])) { $result[$branch_name] = $this->cache[$user_id]["keys"][$tree][$branch_name]; } else { $result[$branch_name] = null; } } unset($branch_name); // Only set the $valid flag true if every requested branch was successfully fetched if (count($result) == count($branch)) { $valid = true; } else { $valid = false; } // If only one branch was requested, and the branch was successfully retrieved from the db, // lift the result array up one level if ($single == true && count($result) == 1) { $result = $result[$branch[0]]; } return $result; } elseif ($user_id && $tree && !$branch && !$key) { if (is_array($user_id)) { throw new FOX_exception(array('numeric' => 7, 'text' => "Attempted to pass multiple user id's when specifying tree", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } // If the user_id is not present in the class cache array, try to load it // from the persistent cache if (!$this->cache[$user_id]) { try { $this->cache[$user_id] = $rad->cache->get("FOX_uData", $user_id, $valid); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 8, 'text' => "Cache get exception", 'data' => array("user_id" => $user_id, "tree" => $tree), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } // Single tree if (!is_array($tree)) { $single = true; $tree = array($tree); } else { $single = false; } // Find all the trees that have been requested but are not in the cache $missing_trees = array(); foreach ($tree as $tree_name) { $tree_cached = FOX_sUtil::keyTrue($tree_name, $this->cache[$user_id]["tree"]); $user_cached = FOX_sUtil::keyTrue("all_cached", $this->cache[$user_id]); if (!$tree_cached && !$user_cached) { $missing_trees[] = $tree_name; } } unset($tree_name); // Load missing trees if (count($missing_trees) != 0) { try { $this->load($user_id, $missing_trees, null, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 9, 'text' => "Load exception", 'data' => array("user_id" => $user_id, "missing_trees" => $missing_trees), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } $result = array(); // Build an array of the requested trees foreach ($tree as $tree_name) { if (FOX_sUtil::keyExists($tree_name, $this->cache[$user_id]["keys"])) { $result[$tree_name] = $this->cache[$user_id]["keys"][$tree_name]; } else { $result[$tree_name] = null; } } unset($tree_name); // Only set the $valid flag true if every requested tree was successfully fetched if (count($result) == count($tree)) { $valid = true; } else { $valid = false; } // If only one tree was requested, and the tree was successfully retrieved from the db, // lift the result array up one level if ($single == true && count($result) == 1) { $result = $result[$tree[0]]; } return $result; } elseif ($user_id && !$tree && !$branch && !$key) { if (!is_array($user_id)) { $single = true; $user_id = array($user_id); } else { $single = false; } // Find all the user_id's that have been requested but are not in the cache $missing_trees = array(); foreach ($user_id as $current_user_id) { if (!FOX_sUtil::keyTrue("all_cached", $this->cache[$current_user_id])) { $missing_users[] = $current_user_id; } } unset($current_user_id); // Load missing user_id's if (count($missing_users) != 0) { try { $this->load($missing_users, null, null, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 10, 'text' => "Load exception", 'data' => array("missing_users" => $missing_users), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } $result = array(); // Build an array of the requested users foreach ($user_id as $current_user_id) { if (FOX_sUtil::keyExists($current_user_id, $this->cache)) { $result[$current_user_id] = $this->cache[$current_user_id]["keys"]; } else { $result[$current_user_id] = null; } } unset($current_user_id); // Only set the $valid flag true if every requested tree was successfully fetched if (count($result) == count($user_id)) { $valid = true; } else { $valid = false; } // If only one user_id was requested, and the user_id was successfully retrieved from the db, // lift the result array up one level if (($single = true) && count($result) == 1) { $result = $result[$user_id[0]]; } return $result; } else { throw new FOX_exception(array('numeric' => 10, 'text' => "Bad input args", 'data' => array("user_id" => $user_id, "tree" => $tree, "branch" => $branch, "key" => $key), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null)); } }
/** * Returns all targets that belong to the specified location or locations * * @version 1.0 * @since 1.0 * * @param string/array $locations | Single location name as string. Multiple location names as array of strings. * @return null/array | Exception on failure. Null or empty array on nonexistent. Array of row data arrays on success. */ public function getLocation($locations = null) { // CASE 1: Fetch all locations in database // ============================================================= if (empty($locations)) { // If the all_cached flag isn't set in the class cache, reload the class // cache from the persistent cache. if (!FOX_sUtil::keyTrue("all_cached", $this->cache)) { try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Cache read error", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // If the all_cached flag isn't set in the class cache after reloading from // the persistent cache, load the module data from the db. if (!FOX_sUtil::keyTrue("all_cached", $this->cache)) { try { self::load(null, true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Error in self::load()", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } } return $this->cache["data"]; } else { // Handle single string $location if (!is_array($locations)) { $locations = array($locations); } // Build a list of all locations that are not in the cache // ======================================================== if (!FOX_sUtil::keyTrue("all_cached", $this->cache)) { $missing_locations = array(); $cache_reloaded = false; foreach ($locations as $location) { if (!FOX_sUtil::keyExists($location, $this->cache["locations"])) { // If the location is not present in the class cache, try reloading // the class cache from the persistent cache. if (!$cache_reloaded) { try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Cache read error", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } $cache_reloaded = true; // If the location is still not present in the class cache after reloading from // the persistent cache, add it to the array of locations to fetch from the db. if (!FOX_sUtil::keyExists($location, $this->cache["locations"])) { $missing_locations[] = $location; } } else { $missing_locations[] = $location; } } } unset($location); // Cache all missing locations (uses a single query) // ======================================================== if ($missing_locations) { try { self::load(array("location" => $missing_locations), $cache_reloaded); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 4, 'text' => "Error in self::load()", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } } // If only one location was requested, just return the contents of its db row. If // multiple locations were requested, return them as a set of arrays // ======================================================================================= if (count($locations) == 1) { $result = $this->cache["data"][$locations[0]]; } else { $result = array(); foreach ($locations as $location) { if (FOX_sUtil::keyExists($location, $this->cache["data"])) { $result[$location] = $this->cache["data"][$location]; } } unset($location); } return $result; } }
/** * Given a *minimum spanning trie* of objects to check, returns a minimum spanning trie * of objects in the original trie which don't have authority in the class cache. * * @see FOX_trie::clipAssocTrie() * * @version 1.0 * @since 1.0 * * @param array $data | array of L5's in the form "L5_id"=>"L4s" * => ARR @param array $L4s | array of L4's in the form "L4_id"=>"L3s" * => ARR @param array $L3s | array of L3's in the form "L3_id"=>"L2s" * => ARR @param array $L2s | array of L2's in the form "L2_id"=>"L1s" * => ARR @param array $L1s | array of L1's in the form "L1_id"=>"L1_value" * => KEY @param int/string | L1 id * => VAL @param NULL * * @param array $cache_image | cache image to check against * * @return array | Exception on failure. Data array on success. */ public function notInClassCache($data, $cache_image) { // 1) If an object has authority in the class cache skip it // 2) If the object doesn't have authority and has no descendents, flag it // 3) Otherwise, repeat the algorithm on the object's descendents 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()))))); } $result = array(); foreach ($data as $L5 => $L4s) { $L5_has_auth = FOX_sUtil::keyTrue('all_cached', $cache_image[$L5]); if (!$L5_has_auth) { // Handle "true", "null" etc end nodes. The algorithm is implemented this // way to avoid excessive if-else nesting indentation. We know that any // non-array keys are valid end nodes because the trie passed validation // in the caller method if (!is_array($L4s)) { $L4s = array(); } if (count($L4s) == 0) { $result[$L5] = array(); } foreach ($L4s as $L4 => $L3s) { $L4_has_auth = FOX_sUtil::keyTrue($L4, $cache_image[$L5][$this->L4_col]); if (!$L4_has_auth) { if (!is_array($L3s)) { // Handle "true", "null" etc end nodes $L3s = array(); } if (count($L3s) == 0) { $result[$L5][$L4] = array(); } foreach ($L3s as $L3 => $L2s) { $L3_has_auth = FOX_sUtil::keyTrue($L3, $cache_image[$L5][$this->L3_col][$L4]); if (!$L3_has_auth) { if (!is_array($L2s)) { // Handle "true", "null" etc end nodes $L2s = array(); } if (count($L2s) == 0) { $result[$L5][$L4][$L3] = array(); } foreach ($L2s as $L2 => $L1s) { $L2_has_auth = FOX_sUtil::keyTrue($L2, $cache_image[$L5][$this->L2_col][$L4][$L3]); if (!$L2_has_auth) { if (!is_array($L1s)) { // Handle "true", "null" etc end nodes $L1s = array(); } if (count($L1s) == 0) { $result[$L5][$L4][$L3][$L2] = array(); } foreach ($L1s as $L1 => $val) { if (!FOX_sUtil::keyExists($L1, $cache_image[$L5]["keys"][$L4][$L3][$L2])) { $result[$L5][$L4][$L3][$L2][$L1] = true; } } unset($L1, $val); } } unset($L2, $L1s); } } unset($L3, $L2s); } } unset($L4, $L3s); } } unset($L5, $L4s); 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 $result; }
/** * Fetches a node, branch, tree, or all nodes from the cache or database * * If an object is not in the cache yet, it will be retrieved from the database * and added to the cache. Multiple items in the *lowest level group* specified * can be retrieved in a single query by passing their names or id's as an array. * * @version 1.0 * @since 1.0 * * @param int/array $tree | Single $tree as int. Multiple as array of ints. * @param int/array $branch | Single $branch as int. Multiple as array of ints. * @param string/array $node | Single node name as string. Multiple as array of strings. * @param bool &$valid | True if all requested objects exist in the db. False if not. * * @return mixed | Exception on failure. Requested objects on success. */ public function get($trees = null, $branches = null, $nodes = null, &$valid = null) { $valid = true; // CASE 1: One or more $nodes // ===================================================================== if ($trees && $branches && $nodes) { // Trap attempting to pass array of tree's, or branches when specifying node if (is_array($trees) || is_array($branches)) { throw new FOX_exception(array('numeric' => 1, 'text' => "Attempted to specify multiple trees or branches when specifying nodes", 'data' => array('trees' => $trees, 'branch' => $branches, 'nodes' => $nodes), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } if (!is_array($nodes)) { $nodes = array($nodes); } // Find all the nodes that have been requested but are not in the cache $missing_nodes = array(); $cache_loaded = false; foreach ($nodes as $node) { $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); $tree_cached = FOX_sUtil::keyTrue($trees, $this->cache["trees"]); $branch_cached = FOX_sUtil::keyTrue($branch, $this->cache["branches"][$trees]); $node_exists = FOX_sUtil::keyExists($node, $this->cache["keys"][$trees][$branches]); // If the node doesn't exist in the class cache array, fetch it from the persistent cache if (!$all_cached && !$tree_cached && !$branch_cached && !$node_exists && !$cache_loaded) { 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)); } $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); $tree_cached = FOX_sUtil::keyTrue($trees, $this->cache["trees"]); $branch_cached = FOX_sUtil::keyTrue($branch, $this->cache["branches"][$trees]); $node_exists = FOX_sUtil::keyExists($node, $this->cache["keys"][$trees][$branches]); $cache_loaded = true; } // If the requested node doesn't exist in the persistent cache, add it to the missing nodes array if (!$all_cached && !$tree_cached && !$branch_cached && !$node_exists) { $missing_nodes[] = $node; } } unset($node); // Load all missing keys in a single query if (count($missing_nodes) > 0) { try { $valid = self::load($trees, $branches, $missing_nodes, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Error in self::load()", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested nodes foreach ($nodes as $node) { $result[$node] = $this->cache["keys"][$trees][$branches][$node]; } unset($node); return $result; } elseif ($trees && $branches && !$nodes) { // Trap attempting to pass array of tree's when specifying branch if (is_array($trees) || is_array($branches)) { throw new FOX_exception(array('numeric' => 4, 'text' => "Attempted to specify multiple trees when specifying branch", 'data' => array('trees' => $trees, 'branch' => $branches, 'nodes' => $nodes), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } if (!is_array($branches)) { $branches = array($branches); } // Find all the branches that have been requested but are not in the cache $missing_branches = array(); $cache_loaded = false; foreach ($branches as $branch) { $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); $tree_cached = FOX_sUtil::keyTrue($trees, $this->cache["trees"]); $branch_cached = FOX_sUtil::keyTrue($branch, $this->cache["branches"][$trees]); // If the branch doesn't exist in the class cache array, fetch it from the persistent cache if (!$all_cached && !$tree_cached && !$branch_cached && !$cache_loaded) { try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); $tree_cached = FOX_sUtil::keyTrue($trees, $this->cache["trees"]); $branch_cached = FOX_sUtil::keyTrue($branch, $this->cache["branches"][$trees]); $cache_loaded = true; } // If the branch doesn't exist in the persistent cache, add it to the missing branches array if (!$all_cached && !$tree_cached && !$branch_cached) { $missing_branches[] = $branch; } } unset($branch); // Load all missing branches in a single query if (count($missing_branches) != 0) { try { $valid = self::load($trees, $missing_branches, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 6, 'text' => "Error in self::load()", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested branches foreach ($branches as $branch) { $result[$branch] = $this->cache["keys"][$trees][$branch]; } unset($branch); return $result; } elseif ($trees && !$branches && !$nodes) { if (!is_array($trees)) { $trees = array($trees); } // Find all the trees that have been requested but are not in the cache $missing_trees = array(); $cache_loaded = false; foreach ($trees as $tree) { $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); $tree_cached = FOX_sUtil::keyTrue($tree, $this->cache["trees"]); // If the tree doesn't exist in the class cache array, fetch it from the persistent cache if (!$all_cached && !$tree_cached && !$cache_loaded) { try { self::loadCache(); } 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)); } $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); $tree_cached = FOX_sUtil::keyTrue($tree, $this->cache["trees"]); $cache_loaded = true; } // If the tree doesn't exist in the persistent cache, add it to the missing branches array if (!$all_cached && !$tree_cached) { $missing_trees[] = $tree; } } unset($tree); // Load all missing branches in a single query if (count($missing_trees) != 0) { try { $valid = self::load($missing_trees, null, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 8, 'text' => "Error in self::load()", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested branches foreach ($tree as $tree) { $result[$tree] = $this->cache["keys"][$tree]; } unset($tree); return $result; } elseif (!$trees && !$branches && !$nodes) { $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); // If the tree doesn't exist in the class cache array, fetch it from the persistent cache if (!$all_cached) { try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 9, 'text' => "Cache read error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } $all_cached = FOX_sUtil::keyTrue("all_cached", $this->cache); } if (!$all_cached) { $valid = self::load(null, null, null, $skip_load = true); } return $this->cache["keys"]; } else { throw new FOX_exception(array('numeric' => 10, 'text' => "Bad input format", 'data' => array('trees' => $trees, 'branches' => $branches, 'nodes' => $nodes), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } }
/** * Fetches a key_id, branch_id, type_id, or an entire module's keystore from the key cache. * * If an object is not in the cache yet, it will be retrieved from the database * and added to the cache. Multiple items in the *lowest level group* specified * can be retrieved in a single query by passing their names or id's as an array. * * WRONG: get( $module_id=1, $type_ids = array(3, 6, 7, 2), $branch_ids="foo") * ^^^^^^^^^^^^^^^^^^^^^^^^ * RIGHT: get( $module_id=1, $type_ids=7, $branch_ids=array("foo","bar","baz") * * @version 1.0 * @since 1.0 * * @param int/array $module_ids | Single $module_id as int. Multiple as array of ints. * @param int/array $type_ids | Single $type_id as int. Multiple as array of ints. * @param string/array $branch_ids | Single key type as string. Multiple key types as array of strings. * @param bool &$valid | True if the object exists. False if not. * * @return bool | Exception on failure. True on success. */ public function get($module_id, $type_ids = null, $branch_ids = null, $key_ids = null, &$valid = null) { // CASE 1: One or more $key_ids // ===================================================================== if ($module_id && $type_ids && $branch_ids && $key_ids) { if (is_array($module_id) || is_array($type_ids) || is_array($branch_ids)) { throw new FOX_exception(array('numeric' => 1, 'text' => "Attempted to pass multiple module id's, type_ids, or branch_id's when specifying key_id", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } // If the module_id is not present in the class cache array, try to load it // from the persistent cache if (!FOX_sUtil::keyExists($module_id, $this->cache)) { try { $this->cache[$module_id] = self::readCache($module_id); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Cache get error", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "key_id" => $key_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } // Single key if (!is_array($key_ids)) { $single = true; $key_ids = array($key_ids); } else { $single = false; } // Find all the keys that have been requested but are not in the cache $missing_keys = array(); $module_cached = FOX_sUtil::keyTrue("all_cached", $this->cache[$module_id]); $type_id_cached = FOX_sUtil::keyTrue($type_ids, $this->cache[$module_id]["type_id"]); $type_cached = FOX_sUtil::keyTrue($branch_ids, $this->cache[$module_id]["branch_id"][$type_ids]); if (!$module_cached && !$type_id_cached && !$type_cached) { foreach ($key_ids as $key_id) { if (!FOX_sUtil::keyExists($key_id, $this->cache[$module_id]["keys"][$type_ids][$branch_ids])) { $missing_keys[] = $key_id; } } unset($key_id); } // Load missing keys if (count($missing_keys) != 0) { try { $this->load($module_id, $type_ids, $branch_ids, $missing_keys, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 3, 'text' => "Load error", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "missing_keys" => $missing_keys), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested keys foreach ($key_ids as $key_id) { if (FOX_sUtil::keyExists($key_id, $this->cache[$module_id]["keys"][$type_ids][$branch_ids])) { $result[$key_id] = $this->cache[$module_id]["keys"][$type_ids][$branch_ids][$key_id]; } else { $result[$key_id] = null; } } unset($key_id); // Only set the $valid flag true if every requested key was successfully fetched if (count($result) == count($key_ids)) { $valid = true; } else { $valid = false; } // If only one key was requested, and the key was successfully retrieved from the db, // lift the result array up one level if ($single == true && count($result) == 1) { $result = $result[$key_ids[0]]; } return $result; } // CASE 2: One or more $branch_ids // ===================================================================== if ($module_id && $type_ids && $branch_ids && !$key_ids) { if (is_array($module_id) || is_array($type_ids)) { throw new FOX_exception(array('numeric' => 4, 'text' => "Attempted to pass multiple module id's, or type_ids when specifying branch_id", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } // If the module_id is not present in the class cache array, try to load it // from the persistent cache if (!FOX_sUtil::keyExists($module_id, $this->cache)) { try { $this->cache[$module_id] = self::readCache($module_id); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 5, 'text' => "Cache get error", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "key_id" => $key_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } // Single key if (!is_array($branch_ids)) { $single = true; $branch_ids = array($branch_ids); } else { $single = false; } // Find all the branch_ids that have been requested but are not in the cache $missing_types = array(); $module_cached = FOX_sUtil::keyTrue("all_cached", $this->cache[$module_id]); $type_id_cached = FOX_sUtil::keyTrue($type_ids, $this->cache[$module_id]["type_id"]); $type_cached = FOX_sUtil::keyTrue($branch_ids, $this->cache[$module_id]["branch_id"][$type_ids]); if (!$module_cached && !$type_id_cached && !$type_cached) { foreach ($branch_ids as $branch_id) { if (!FOX_sUtil::keyExists($branch_id, $this->cache[$module_id]["keys"][$type_ids])) { $missing_types[] = $branch_id; } } unset($branch_id); } // Load missing keys if (count($missing_types) != 0) { try { $this->load($module_id, $type_ids, $missing_types, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 6, 'text' => "Load error", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "missing_types" => $missing_types), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested keys foreach ($branch_ids as $branch_id) { if (FOX_sUtil::keyExists($branch_id, $this->cache[$module_id]["keys"][$type_ids])) { $result[$branch_id] = $this->cache[$module_id]["keys"][$type_ids][$branch_id]; } else { $result[$branch_id] = null; } } unset($branch_id); // Only set the $valid flag true if every requested key was successfully fetched if (count($result) == count($branch_ids)) { $valid = true; } else { $valid = false; } // If only one key was requested, and the key was successfully retrieved from the db, // lift the result array up one level if ($single == true && count($result) == 1) { $result = $result[$branch_ids[0]]; } return $result; } elseif ($module_id && $type_ids && !$branch_ids && !$key_ids) { if (is_array($module_id)) { throw new FOX_exception(array('numeric' => 7, 'text' => "Attempted to pass multiple module id's when specifying type_id", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } // If the module_id is not present in the class cache, try to load it // from the persistent cache if (!FOX_sUtil::keyExists($module_id, $this->cache)) { try { $this->cache[$module_id] = self::readCache($module_id); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 8, 'text' => "Cache get error", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "key_id" => $key_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } // Single type_id if (!is_array($type_ids)) { $single = true; $type_ids = array($type_ids); } else { $single = false; } // Find all the type_ids that have been requested but are not in the cache $missing_type_ids = array(); foreach ($type_ids as $type_id) { $module_cached = FOX_sUtil::keyTrue("all_cached", $this->cache[$module_id]); $type_id_cached = FOX_sUtil::keyTrue($type_id, $this->cache[$module_id]["type_id"]); if (!$module_cached && !$type_id_cached) { $missing_type_ids[] = $type_id; } } unset($type_id); // Load missing type_ids if (count($missing_type_ids) != 0) { try { self::load($module_id, $missing_type_ids, null, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 9, 'text' => "Load error", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "key_id" => $key_ids, "missing_type_ids" => $missing_type_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested type_ids foreach ($type_ids as $type_id) { if (FOX_sUtil::keyExists($type_id, $this->cache[$module_id]["keys"])) { $result[$type_id] = $this->cache[$module_id]["keys"][$type_id]; } else { $result[$type_id] = null; } } unset($type_id); // Only set the $valid flag true if every requested type_id was successfully fetched if (count($result) == count($type_ids)) { $valid = true; } else { $valid = false; } // If only one type_id was requested, and the type_id was successfully retrieved from the db, // lift the result array up one level if ($single == true && count($result) == 1) { $result = $result[$type_ids[0]]; } return $result; } elseif ($module_id && !$type_ids && !$branch_ids && !$key_ids) { if (!is_array($module_id)) { $single = true; $module_id = array($module_id); } else { $single = false; } // Find all the module_id's that have been requested but are not in the cache $missing_module_ids = array(); foreach ($module_id as $current_module_id) { if (!FOX_sUtil::keyTrue("all_cached", $this->cache[$current_module_id])) { $missing_module_ids[] = $current_module_id; } } unset($current_module_id); // Load missing module_id's if (count($missing_module_ids) != 0) { try { self::load($missing_module_ids, null, null, null, $skip_load = true); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 13, 'text' => "Load error", 'data' => array("missing_module_ids" => $missing_module_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child)); } } $result = array(); // Build an array of the requested module_ids foreach ($module_id as $current_module_id) { if (FOX_sUtil::keyExists($current_module_id, $this->cache)) { $result[$current_module_id] = $this->cache[$current_module_id]["keys"]; } else { $result[$current_module_id] = null; } } unset($current_module_id); // Only set the $valid flag true if every requested module_id was successfully fetched if (count($result) == count($module_id)) { $valid = true; } else { $valid = false; } // If only one module_id was requested, and the module_id was successfully retrieved from the db, // lift the result array up one level if (($single = true) && count($result) == 1) { $result = $result[$module_id[0]]; } return $result; } else { throw new FOX_exception(array('numeric' => 14, 'text' => "Bad input args", 'data' => array("module_id" => $module_id, "type_id" => $type_ids, "branch_id" => $branch_ids, "key_id" => $key_ids), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null)); } }
/** * Returns an array containing all data for all modules * * @version 1.0 * @since 1.0 * * @return array | Exception on failure. Array of class names on success. */ public function getAllModules() { 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 the all_cached flag isn't set in the class cache, reload the class // cache from the persistent cache. if (!FOX_sUtil::keyTrue("all_cached", $this->cache)) { // Load the class cache from the persistent cache // ================================================= try { self::loadCache(); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 1, 'text' => "Cache get error", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } // If the all_cached flag isn't set in the class cache after reloading from // the persistent cache, load both caches from the db. if (!FOX_sUtil::keyTrue("all_cached", $this->cache)) { try { self::load($data = null); } catch (FOX_exception $child) { throw new FOX_exception(array('numeric' => 2, 'text' => "Load error", 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child)); } } } // At this point, all modules should be in the cache if (FOX_sUtil::keyExists("module_id", $this->cache)) { $result = $this->cache["module_id"]; } else { // Handle no modules installed on system $result = array(); } return $result; }