/** *Renames a child node * @param I2CE_MagicDataNode $node *@param string $old *@param string $new *@returns boolean. True on success, false on failure */ public function renameChild($node, $old, $new) { $keys = array(self::TYPE => true, self::VALUE => true, self::CHILDREN => true); $result = $this->mcoll->findOne(array(self::PATH => $node->getPath(false)), $keys); if (!is_array($result) || count($result) == 0) { I2CE::raiseError("Could not update -- non-existing node"); return false; } if (($key = array_search($old, $result[self::CHILDREN])) === false) { I2CE::raiseError("Child {$old} on " . $node->getPath(false) . " does not exist"); return false; } $result[self::CHILDREN][$key] = $new; $newdata = array('$set' => array(self::CHILDREN => $result[self::CHILDREN])); if (!is_array($res = $this->mcoll->update(array(self::PATH => $node->getPath(false)), $newdata, array('safe' => true))) || array_key_exists('err', $res) && $res['err']) { I2CE::raiseError("Could not update new children:" . print_r($res, true)); return false; } return $this->renameDecendents($node, array($old => $new)); }
/** * Store the given magic data node (which should be a descendent * of this instance.) Starts storing at the last added storage * mechanism until it reaches the first storage mechanism. If it * fails saving at any storage mechanis, it will call the destroy * method on that storage mechanism and any remaining one. * * @param I2CE_MagicDataNode $node * @param integer $max The max index of storage objects to save. * Defaults to -1 meaning we store on all * mechanisms * @returns boolean true on success. */ public function store($node, $max = -1) { if ($node->type == I2CE_MagicDataNode::TYPE_NOT_POPULATED) { I2CE::raiseError("Trying to store magic data which is unpopulated at " . $node->getPath()); return FALSE; } if ($this->num_storage === 0) { return TRUE; } if ($max < 0 || $max > $this->num_storage) { $max = $this->num_storage - 1; } //there is a problem here if there in only one storage mechanism that we have just retrieved/populated from $fails = array(); for ($i = $max; $i >= 0; $i--) { if (!$this->storage[$i]->store($node)) { $fails[] = $i; } } if (count($fails) > 0) { $fail_max = max($fails); if ($fail_max == $this->num_storage - 1) { I2CE::raiseError("Unrecoverable data storage failure for " . $node->getPath()); return false; //we failed on the permanent data store } I2CE::raiseError("Attempting to recover from data storage failure for " . $node->getPath()); //we did not fail on the permanent data store //we try to clear all caches at and above the failure point. $cleared = true; for ($i = $fail_max; $i >= 0; $i--) { $cleared &= $this->storage[$i]->destroy($node); } if (!$cleared) { I2CE::raiseError("Could not clear cached data for " . $node->getPath()); return false; } } return true; }
/** *Renames a child node * @param I2CE_MagicDataNode $node *@param string $old *@param string $new *@returns boolean. True on success, false on failure */ public function renameChild($node, $old, $new) { if ($node instanceof I2CE_MagicData) { $parentPath = '/'; $offset = strlen('/' . $old) + 1; $fullOffset = strlen($node->getPath(true) . '/' . $old); // if $old ='old', results in calling SUBSTR(parent,5) //so if parent = '/old/path' then substr(parent,5) = '/path' //we want to result in /new/path } else { $parentPath = $node->getPath(false); //e.g. $offset = strlen($node->getPath(false) . '/' . $old) + 1; $fullOffset = strlen($node->getPath(true) . '/' . $old); //child: if $old = 'old' and $node='/some', then calling SUBSTR(parent, 10) //so if parent = /some/old/path then substr(parent,10) = /path //we want to result in /some/new/path } $newPath = mysql_real_escape_string($this->getChildPath($node, $new, false)); $newFullPath = mysql_real_escape_string($this->getChildPath($node, $new, true)); $oldPath = mysql_real_escape_string($this->getChildPath($node, $old, false)); $qry_node = "UPDATE config_alt SET name = '" . mysql_real_escape_string($new) . "' , path_hash = '" . mysql_real_escape_string($this->getHash($node, $new)) . "' " . "WHERE parent = '" . mysql_real_escape_string($parentPath) . "' AND name = '" . mysql_real_escape_string($old) . "'"; //change direct children $qry_child = "UPDATE config_alt SET " . " path_hash = MD5(CONCAT('{$newFullPath}', '/',name)) " . ", parent = '{$newPath}' " . "WHERE parent = '{$oldPath}'"; //change descendents $qry_desc = "UPDATE config_alt SET " . " path_hash = MD5( CONCAT('{$newFullPath}', SUBSTR(parent,{$offset}) , '/',name)) " . ", parent = CONCAT('{$newPath}', SUBSTR(parent,{$offset}) ) " . "WHERE parent LIKE '{$oldPath}/%'"; $this->db->exec($qry_node); $this->db->exec($qry_child); $this->db->exec($qry_desc); return true; }
/** * Return the md5 Hash of the path of this object. * @param I2CE_MagicDataNode $node * @param string $childPath * @param boolean $show_top defaults to true if we are to show the parent * @return string */ public function getChildPath($node, $childPath, $show_top = true) { if ($show_top) { if ($node instanceof I2CE_MagicData) { return $node->getPath(true) . $node->pathDivider() . $childPath; } else { return $node->getPath(true) . '/' . $childPath; } } else { if ($node instanceof I2CE_MagicData) { return '/' . $childPath; } else { return $node->getPath(false) . '/' . $childPath; } } }