protected static function storeModuleMagicData($shortname, $old_vers, $new_vers, $mod_configurator, $imported) { $mod_storage = $mod_configurator->getStorage(); if (!$mod_storage instanceof I2CE_MagicDataNode) { I2CE::raiseError("Expecting magic data"); return false; } //processconfig data $storage = I2CE::getConfig(); $merges = $mod_configurator->getMerges(); foreach ($merges as $path => $merge) { if ($storage->is_scalar($path)) { I2CE::raiseError("Trying to merge arrays into {$path} where target is scalar valued. Skipping"); continue; } if ($mod_storage->is_scalar($path)) { I2CE::raiseError("Trying to merge arrays into {$path} where source is scalar valued. Skipping"); continue; } $old_arr = $storage->getAsArray($path); $new_arr = $mod_storage->getAsArray($path); $mod_storage->__unset($path); if (!is_array($old_arr)) { //in case the target did not exist $old_arr = array(); } if (!is_array($new_arr)) { //in case no values were set for the source $new_arr = array(); } switch ($merge) { case 'uniquemerge': $new_arr = I2CE_Util::array_unique(array_merge($old_arr, $new_arr)); break; case 'merge': $new_arr = array_merge($old_arr, $new_arr); break; case 'mergerecursive': I2CE_Util::merge_recursive($old_arr, $new_arr); $new_arr = $old_arr; break; } $storage->__unset($path); $storage->{$path} = $new_arr; } //we took care of all array merges. anything that is left is an overwrite. foreach ($mod_storage as $k => $v) { if ($k == 'config') { //don't update config info that might be here. It's handled below. continue; } if (is_scalar($v) && $mod_storage->is_translatable($k) && !$storage->is_parent($k)) { $storage->setTranslatable($k); $translations = $mod_storage->traverse($k, true, false)->getTranslations(); foreach ($translations as $locale => $trans) { if (strlen($trans) == 0) { continue; } $storage->setTranslation($locale, $trans, $k); } } else { $storage->{$k}->setValue($v, null, false); } if ($storage->{$k} instanceof I2CE_MagicDataNode) { //free up some memory. $storage->{$k}->unpopulate(true); } } $storage->config->status->config_processed->{$shortname} = $new_vers; //set the config data as processed if (isset($storage->config->status->initialized->{$shortname})) { $storage->config->status->initialized->{$shortname} = 1; //set the config data as processed } foreach ($imported as $locale => &$data) { unset($data['old_vers']); } $storage->config->status->localized->{$shortname} = $imported; return true; }
protected function loadMDTemplate($doc, $transform = false, $erase = false) { //doc is either a file name or a DOMDocument if ($transform) { //transform if (is_string($doc)) { $file = $doc; $doc = new DOMDocument(); if (!($contents = file_get_contents($file))) { $this->userMessage("Could not load source file"); return false; } if (!$doc->loadXML($contents)) { $this->userMessage("Could not load file source contents"); return false; } } if (!$doc instanceof DOMDocument) { $this->userMessage("Could not load xml into document"); return false; } $proc = new XSLTProcessor(); $xslt_doc = new DOMDocument(); if (!$xslt_doc->loadXML($transform)) { $this->userMessage("Could not load transform: " . $_FILES['xsl']['name']); return false; } if (!$proc->importStylesheet($xslt_doc)) { $this->userMessage("Could not import style sheet"); return false; } $trans_doc = new DOMDocument('1.0', 'UTF-8'); $trans_doc->appendChild($trans_doc->importNode($doc->documentElement, true)); if (($trans_out = $proc->transformToXML($trans_doc)) === false) { $this->userMessage("Could not transform accoring to xsl"); return false; } } else { $trans_doc = $doc; } if ($trans_doc instanceof DOMDocument) { $temp_file = tempnam(sys_get_temp_dir(), 'MDN_UPLOAD'); if (!file_put_contents($temp_file, $trans_out)) { $this->userMessage("Could not save transformed files"); return false; } } else { $temp_file = $trans_doc; } $template = new I2CE_MagicDataTemplate(); $template->setVerboseErrors(true); if (!$template->loadRootFile($temp_file)) { I2CE::raiseError("Unable to load transformed file as Magic Data"); $this->userMessage("Unable to load transformed file as Magic Data"); return false; } if (!$template->validate()) { I2CE::raiseError("Unable to validate transformed file as Magic Data"); $this->userMessage("Unable to validate transformed file as Magic Data"); return false; } $store = new I2CE_MagicDataStorageMem(); $mem_config = I2CE_MagicData::instance("mdn_load"); $mem_config->addStorage($store); $nodeList = $template->query("/configurationGroup"); if (!$nodeList instanceof DOMNodeList || $nodeList->length == 0) { $nodeList = $template->query("/I2CEConfiguration/configurationGroup"); //perhaps we really need to do something more if this is a module } foreach ($nodeList as $configNode) { $locale = false; $status = $template->getDefaultStatus(); if ($configNode->hasAttribute('locale')) { $locale = $configNode->getAttribute('locale'); } $vers = '0'; if ($template->setConfigValues($configNode, $mem_config, $status, $vers) === false) { I2CE::raiseError("Could not load configuration values"); $this->userMessage("Could not load configuration values"); return false; } } //I2CE::raiseError(print_r($mem_config->getAsArray(),true)); if ($erase) { $this->config->eraseChildren(); } $merges = $template->getMerges(); foreach ($merges as $path => $merge) { if ($this->config->is_scalar($path)) { I2CE::raiseError("Trying to merge arrays into {$path} where target is scalar valued. Skipping"); continue; } if ($mem_config->is_scalar($path)) { I2CE::raiseError("Trying to merge arrays into {$path} where source is scalar valued. Skipping"); continue; } $old_arr = $this->config->getAsArray($path); $new_arr = $mem_config->getAsArray($path); $mem_config->__unset($path); if (!is_array($old_arr)) { //in case the target did not exist $old_arr = array(); } if (!is_array($new_arr)) { //in case no values were set for the source $new_arr = array(); } switch ($merge) { case 'uniquemerge': $new_arr = I2CE_Util::array_unique(array_merge($old_arr, $new_arr)); break; case 'merge': $new_arr = array_merge($old_arr, $new_arr); break; case 'mergerecursive': I2CE_Util::merge_recursive($old_arr, $new_arr); $new_arr = $old_arr; break; } $this->config->__unset($path); $this->config->{$path} = $new_arr; } //we took care of all array merges. anything that is left is an overwrite. foreach ($mem_config as $k => $v) { if (is_scalar($v) && $mem_config->is_translatable($k) && !$this->config->is_parent($k)) { $this->config->setTranslatable($k); $translations = $mem_config->traverse($k, true, false)->getTranslations(); foreach ($translations as $locale => $trans) { if (strlen($trans) == 0) { continue; } $this->config->setTranslation($locale, $trans, $k); } } else { $this->config->{$k}->setValue($v, null, false); } if ($this->config->{$k} instanceof I2CE_MagicDataNode) { //free up some memory. $this->config->{$k}->unpopulate(true); } } return true; }
/** * Process values for a config node * @param DOMNode $configNode * @param I2CE_MagicDataNode $data * @param array $status. If null, it defaults to the array set by getDefaultStatus(). The current status (of parent node) * @param string $version . Defaults to '0' . The version of the currently loaded data in $storage responsible for this XML * @param array of string $paths -- the current path into the $storage that we are using. Defaults to the empty array(). * @returns boolean. true on sucess */ public function processValues($configNode, $storage, $status = null, $vers, $paths) { if (!$configNode instanceof DOMNode) { $this->raiseError("Did not receive configuration node"); return false; } //deal with any erase Information if (!$this->updatePaths($configNode, $paths)) { return false; } $this->processErasers($configNode, $paths); if ($status === null) { $status = $this->getDefaultStatus(); } if ($configNode->hasAttribute('path')) { //check to see if there is an explicit path set $path = $configNode->getAttribute('path'); $hasPath = true; } else { $path = $configNode->getAttribute('name'); $hasPath = false; } if (strlen($path) === 0) { $this->raiseError("configuration has empty path at " . $storage->getPath()); return false; } if ($configNode->hasAttribute('type')) { $valueType = strtolower(trim($configNode->getAttribute("type"))); } else { $valueType = 'string'; } if ($valueType == 'delimited') { // Delimited types really only make sense as many values $valueValues = 'many'; } elseif ($configNode->hasAttribute('values')) { $valueValues = strtolower(trim($configNode->getAttribute("values"))); } else { $valueValues = 'single'; } $uniquemerge = null; if (array_key_exists('uniquemerge', $status)) { $uniquemerge = $status['uniquemerge']; unset($status['uniquemerge']); } $valStatus = $this->processStatus($configNode, $status, $vers); if (array_key_exists('uniquemerge', $valStatus)) { //the uniquemerge status has been set on explicitly this node. //do nothing } else { //the unique merge status has not been set on this node. //if this node is a values='many' values='string' make it a default merge if ($valueValues == 'many' && $valueType == 'string') { $valStatus['uniquemerge'] = true; } else { if ($uniquemerge !== null) { $valStatus['uniquemerge'] = $uniquemerge; } } } if (!$valStatus['overwrite']) { return true; } $valueList = $this->query("./value", $configNode); if ($valueList->length == 0) { if ($valStatus['required'] === true) { $this->raiseError("Required value is not set at " . $this->getConfigPath($configNode)); return false; } else { //not required so let's return return true; } } $processor = 'processValues_' . $valueType . '_' . $valueValues; $vals = null; $encoding = null; if ($valueValues == 'single') { if ($valueList->item(0) instanceof DOMElement) { //item 0 should exist by the check/return above $vals = $this->{$processor}(trim($valueList->item(0)->textContent), $valStatus); } } else { $vals = array(); for ($k = 0; $k < $valueList->length; $k++) { if ($valueList->item($k) instanceof DOMElement) { $vals[$k] = trim($valueList->item($k)->textContent); } } $vals = $this->{$processor}($vals, $valStatus); if (!is_array($vals)) { $this->raiseError("Expected array to be returned from {$processor}() while evaluating " . $this->getConfigPath($configNode)); return false; } } if ($valStatus['required'] === true && ($valueValues == 'single' && $vals === null || $valueValues == 'many' && count($vals) == 0)) { $this->raiseError("Required value is not set at " . $this->getConfigPath($configNode) . ' in the module ' . $this->query("/I2CEConfiguration")->item(0)->getAttribute('name')); return false; } $validator = 'validateValues_' . $valueType . '_' . $valueValues; if ($this->_hasMethod($validator)) { $validate = $this->{$validator}($vals, $valStatus); if ($validate !== null) { $this->raiseError("Invalid data at " . $this->getConfigPath($configNode) . " + " . $validate); return false; } } $locale = null; if (array_key_exists('locale', $valStatus) && $valStatus['locale']) { //this node is translatable. $locale = $valStatus['locale']; } if ($valStatus['uniquemerge'] && $valueValues == 'many') { if ($storage->is_scalar($path)) { $this->raiseError("Trying to set non-scalar value at scalar valued (uniquemerge):\n" . $storage->getPath() . '/' . $path); return false; } $valStorage = $this->traversePaths($storage, $paths); if (!$valStorage instanceof I2CE_MagicDataNode) { return false; } $old_vals = $valStorage->getAsArray(null, $locale); $valStorage->eraseChildren($locale); $vals = I2CE_Util::array_unique(array_merge($old_vals, $vals)); } else { if ($valStatus['mergerecursive'] && $valueValues == 'many') { if ($storage->is_scalar($path)) { $this->raiseError("Trying to set non-scalar value at scalar valued (mergerecursive):\n" . $storage->getPath() . '/' . $path); return false; } $valStorage = $this->traversePaths($storage, $paths); if (!$valStorage instanceof I2CE_MagicDataNode) { return false; } $old_vals = $valStorage->getAsArray(null, $locale); $valStorage->eraseChildren($locale); I2CE_Util::merge_recursive($old_vals, $vals); $vals = $old_vals; } else { if ($valStatus['merge'] && $valueValues == 'many') { if ($storage->is_scalar($path)) { $this->raiseError("Trying to set non-scalar value at scalar valued (merge):\n" . $storage->getPath() . '/' . $path); return false; } $valStorage = $this->traversePaths($storage, $paths); if (!$valStorage instanceof I2CE_MagicDataNode) { return false; } $old_vals = $valStorage->getAsArray(null, $locale); $valStorage->eraseChildren($locale); $vals = array_merge($old_vals, $vals); } else { if (is_array($vals) && $storage->is_scalar($path)) { $this->raiseError("Trying to set non-scalar value at scalar valued:\n" . $storage->getPath() . '/' . $path); return false; } $valStorage = $this->traversePaths($storage, $paths); if (!$valStorage instanceof I2CE_MagicDataNode) { return false; } } } } $merges = array('merge', 'mergerecursive', 'uniquemerge'); foreach ($merges as $merge) { if (!array_key_exists($merge, $valStatus) || !$valStatus[$merge]) { continue; } $this->merges[$valStorage->getPath(false)] = $merge; } //only one merge status can be set, notice above that unqiuemerge takes presedence over mergerecursive which takes presidents over mergere $valStorage->setValue($vals, $locale, false); if (array_key_exists('binary', $valStatus)) { $this->setAttributeOnChildren('binary', $valStatus['binary'], $valStorage, $vals); } if (array_key_exists('encoding', $valStatus)) { $this->setAttributeOnChildren('encoding', $valStatus['encoding'], $valStorage, $vals); } return true; }