/**
  * Updates an existing node if the $tree-$branch-$node tuple already exists
  * in the db, or creates a new node if it doesn't.
  *
  * @version 1.0
  * @since 1.0
  *
  * @param string $tree | Tree name
  * @param string $branch | Branch name
  * @param string $node | Node name.
  * @param mixed  $val | Value to store to node
  * @param string $filter | The filter function to validate data stored to node
  * @param array $ctrl | Filter function's control args
  *
  * @return int | Exception on failure. Number of db rows changed on success.
  */
 public function writeNode($tree, $branch, $node, $val, $filter, $ctrl = null)
 {
     $db = new FOX_db();
     $struct = $this->_struct();
     // Trap empty keys, and keys that map to ints. We can't use ints as keys
     // or strings that map to keys due to the way PHP handles array indexing
     // in our trie structures. For example, if we had an array with the keys
     // "red", "green", "blue", and (string)"1"; PHP would *overwrite* the
     // "green" key when we tried to save key (string)"1", because it converts
     // it to (int)1 and addresses the array in indexed mode instead of associative
     // mode. There is no way to override this behavior in PHP.
     if ($tree == (int) $tree || !is_string($tree) || empty($tree) || ($branch == (int) $branch || !is_string($branch) || empty($branch)) || ($node == (int) $node || !is_string($node) || empty($node))) {
         throw new FOX_exception(array('numeric' => 1, 'text' => "Tree, Branch, and Node keys must be valid strings that do not map to ints", 'data' => array('tree' => $tree, 'branch' => $branch, 'node' => $node), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     // Trap attempting to use a nonexistent filter
     $cls = new FOX_sanitize();
     if (!method_exists($cls, $filter)) {
         throw new FOX_exception(array('numeric' => 2, 'text' => "Filter method doesn't exist", 'data' => array('tree' => $tree, 'branch' => $branch, 'node' => $node, 'filter' => $filter), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     // Run node value through the specified filter
     // =====================================================
     $filter_valid = null;
     $filter_error = null;
     // Passed by reference
     try {
         $processed_val = $cls->{$filter}($val, $ctrl, $filter_valid, $filter_error);
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 3, 'text' => "Error in filter function", 'data' => array('filter' => $filter, 'val' => $val, 'ctrl' => $ctrl, 'filter_valid' => $filter_valid, 'filter_error' => $filter_error), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     if (!$filter_valid) {
         throw new FOX_exception(array('numeric' => 4, 'text' => "Filter function reports value data isn't valid", 'data' => array('filter' => $filter, 'val' => $val, 'ctrl' => $ctrl, 'filter_valid' => $filter_valid, 'filter_error' => $filter_error), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     // Lock the cache
     // ===========================================================
     try {
         $cache_image = self::lockCache();
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 5, 'text' => "Error locking cache", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     // Update the database
     // ===========================================================
     $args = array("tree" => $tree, "branch" => $branch, "node" => $node, "val" => $processed_val, "filter" => $filter, "ctrl" => $ctrl);
     $columns = null;
     try {
         $rows_changed = $db->runIndateQuery($struct, $args, $columns);
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 6, 'text' => "Error writing to database", 'data' => array('args' => $args, 'columns' => $columns, 'ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     // Rebuild the cache image
     // ===========================================================
     $cache_image["keys"][$tree][$branch][$node]["val"] = $processed_val;
     $cache_image["keys"][$tree][$branch][$node]["filter"] = $filter;
     $cache_image["keys"][$tree][$branch][$node]["ctrl"] = $ctrl;
     // Write the image back to the persistent cache, releasing our lock
     // ===========================================================
     try {
         self::writeCache($cache_image);
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 7, 'text' => "Cache write error", 'data' => array('cache_image' => $cache_image), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     // Update the class cache
     $this->cache = $cache_image;
     return (int) $rows_changed;
 }
Ejemplo n.º 2
0
 /**
  * Creates or updates one or more keys.
  *
  * @version 1.0
  * @since 1.0
  *
  * @param array $data | Array of row arrays
  *	=> ARR @param int '' | Individual row array
  *	    => VAL @param int $user_id | user id
  *	    => VAL @param int $tree | tree id
  *	    => VAL @param int $branch | branch id
  *	    => VAL @param string $key | key name
  *	    => VAL @param bool/int/float/string/array/obj $val | key value
  * @return bool | False on failure. True on success.
  */
 public function setKeyMulti($data)
 {
     global $rad;
     $db = new FOX_db();
     //var_dump($data);
     $cache_update = array();
     $insert_data = array();
     // Process each row
     // ===========================================================
     foreach ($data as $row) {
         if (empty($row["user_id"])) {
             throw new FOX_exception(array('numeric' => 1, 'text' => "Empty user_id", 'data' => $row, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null));
         }
         if (empty($row["tree"])) {
             throw new FOX_exception(array('numeric' => 2, 'text' => "Empty tree name", 'data' => $row, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null));
         }
         if (empty($row["branch"])) {
             throw new FOX_exception(array('numeric' => 3, 'text' => "Empty branch name", 'data' => $row, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null));
         }
         if (empty($row["key"])) {
             throw new FOX_exception(array('numeric' => 4, 'text' => "Empty key name", 'data' => $row, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => null));
         }
         // Expand the key into a heirarchical array
         $update_data[$row["user_id"]][$row["tree"]][$row["branch"]][$row["key"]] = $row["val"];
     }
     unset($row);
     // Load the persistent cache records for all the module_id's into the temp class cache array
     try {
         $update_cache = $rad->cache->getMulti("FOX_uData", array_keys($update_data));
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 5, 'text' => "Cache get error", 'data' => $update_data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
     }
     // @@@@@@ BEGIN TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     try {
         $begin_ok = $db->beginTransaction();
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 6, 'text' => "Couldn't initiate transaction", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
     }
     foreach ($update_data as $user_id => $trees) {
         foreach ($trees as $tree => $branches) {
             foreach ($branches as $branch => $keys) {
                 foreach ($keys as $key => $val) {
                     $insert_data = array("user_id" => $user_id, "tree" => $tree, "branch" => $branch, "node" => $key, "val" => $val);
                     try {
                         $query_ok = $db->runIndateQuery(self::$struct, $insert_data, $columns = null);
                     } catch (FOX_exception $child) {
                         try {
                             $db->rollbackTransaction();
                         } catch (FOX_exception $child) {
                             throw new FOX_exception(array('numeric' => 8, 'text' => "rollbackTransaction", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
                         }
                         throw new FOX_exception(array('numeric' => 7, 'text' => "Error while writing to the database", 'data' => $insert_data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
                     }
                     // Overwrite the class cache array with the data set in the db query
                     $update_cache[$user_id]["keys"][$tree][$branch][$key] = $val;
                 }
                 unset($key, $val);
             }
             unset($branch, $key);
         }
         unset($tree, $branches);
     }
     unset($user_id, $trees);
     try {
         $commit_ok = $db->commitTransaction();
     } catch (FOX_exception $child) {
         // @@@@@@ END TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         throw new FOX_exception(array('numeric' => 8, 'text' => "Error commiting transaction to database", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
     }
     // Overwrite the persistent cache records with the temp class cache array items
     try {
         $cache_ok = $rad->cache->setMulti("FOX_uData", $update_cache);
     } catch (BPN_exception $child) {
         throw new FOX_exception(array('numeric' => 9, 'text' => "Cache set error", 'data' => $data, 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
     }
     // Write the temp class cache array items to the class cache array
     foreach ($update_cache as $key => $val) {
         $this->cache[$key] = $val;
     }
     unset($key, $val);
     return true;
 }
 /**
  * Creates or updates one or more keys.
  *
  * @version 1.0
  * @since 1.0
  *
  * @param array $data | Array of row arrays
  *	=> ARR @param int '' | Individual row array
  *	    => VAL @param int $module_id | module id
  *	    => VAL @param string $type_id | type_id id
  *	    => VAL @param string $branch_id | key type
  *	    => VAL @param int $key_id | key id
  *	    => VAL @param bool/int/float/string/array/obj $ctrl_val | key value
  *
  * @return int | Exception on failure. Int number of rows changed on success.
  */
 public function setKeyMulti($data)
 {
     $db = new FOX_db();
     $struct = $this->_struct();
     $update_data = array();
     $insert_data = array();
     if (!is_array($data) || count($data) < 1) {
         throw new FOX_exception(array('numeric' => 1, 'text' => "Empty data array", 'data' => $data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     // Process each row
     // ===========================================================
     foreach ($data as $row) {
         if (empty($row["module_id"])) {
             throw new FOX_exception(array('numeric' => 2, 'text' => "Empty module_id", 'data' => $row, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
         }
         if (empty($row["type_id"])) {
             throw new FOX_exception(array('numeric' => 4, 'text' => "Empty type_id name", 'data' => $row, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
         }
         if (empty($row["branch_id"])) {
             throw new FOX_exception(array('numeric' => 5, 'text' => "Empty key type", 'data' => $row, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
         }
         if (empty($row["key_id"])) {
             throw new FOX_exception(array('numeric' => 6, 'text' => "Empty key id", 'data' => $row, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
         }
         // Expand the key into a heirarchical array
         $update_data[$row["module_id"]][$row["type_id"]][$row["branch_id"]][$row["key_id"]] = $row["ctrl_val"];
     }
     unset($row);
     // CASE 1: Transactions aren't required.
     // ===========================================================
     if (count($data) == 1) {
         $row = $data[0];
         // Lock and load the cache key
         try {
             $page_image = self::lockCachePage($row["module_id"]);
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 7, 'text' => "Cache lock error", 'data' => $row, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         try {
             $rows_changed = $db->runIndateQuery($struct, $row, $columns = null);
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 8, 'text' => "Error while writing to the database", 'data' => $data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         // Update the key's value in the cache page
         $page_image["keys"][$row["type_id"]][$row["branch_id"]][$row["key_id"]] = $row["ctrl_val"];
         // Write the updated image back to the cache (which also releases our lock)
         try {
             self::writeCachePage(array($row["module_id"] => $page_image));
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 9, 'text' => "Cache set error", 'data' => $this->cache[$row["module_id"]], 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         // If the persistent cache write was successful, write the new page image
         // to the class cache
         $this->cache[$row["module_id"]] = $page_image;
         return (int) $rows_changed;
     } else {
         // Lock and load the persistent cache records for all the module_id's
         // into the temp class cache array
         try {
             $update_cache = self::lockCachePage(array_keys($update_data));
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 10, 'text' => "Cache get error", 'data' => $update_data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         // @@@@@@ BEGIN TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         try {
             $db->beginTransaction();
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 11, 'text' => "Couldn't initiate transaction", 'data' => $data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         $rows_changed = 0;
         foreach ($update_data as $module_id => $type_ids) {
             foreach ($type_ids as $type_id => $branch_ids) {
                 foreach ($branch_ids as $branch_id => $key_ids) {
                     foreach ($key_ids as $key_id => $ctrl_val) {
                         $insert_data = array("module_id" => $module_id, "type_id" => $type_id, "branch_id" => $branch_id, "key_id" => $key_id, "ctrl_val" => $ctrl_val);
                         try {
                             $rows_changed += (int) $db->runIndateQuery($struct, $insert_data, $columns = null);
                         } catch (FOX_exception $child) {
                             try {
                                 $db->rollbackTransaction();
                             } catch (FOX_exception $child_2) {
                                 throw new FOX_exception(array('numeric' => 12, 'text' => "Error while writing to the database. Error rolling back.", 'data' => array('rollback_exception' => $child_2), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
                             }
                             throw new FOX_exception(array('numeric' => 13, 'text' => "Error while writing to the database. Successful rollback.", 'data' => $data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
                         }
                         // Overwrite the temp class cache array with the data we set in the db query
                         $update_cache[$module_id]["keys"][$type_id][$branch_id][$key_id] = $ctrl_val;
                     }
                     unset($key_id, $ctrl_val);
                 }
                 unset($branch_id, $key_ids);
             }
             unset($type_id, $branch_ids);
         }
         unset($module_id, $type_ids);
         // @@@@@@ END TRANSACTION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         try {
             $db->commitTransaction();
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 14, 'text' => "Error commiting transaction to database", 'data' => $data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         // Overwrite the persistent cache records with the temp class cache array items
         try {
             self::writeCachePage($update_cache);
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 15, 'text' => "Cache set error", 'data' => $data, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         // Write the temp class cache array items to the class cache array
         foreach ($update_cache as $module_id => $module_data) {
             $this->cache[$module_id] = $module_data;
         }
         unset($module_id, $module_data);
         return (int) $rows_changed;
     }
 }