/** * Test the HarApi utils class * @see Utils */ public function testUtils() { $class = new core_kernel_classes_Class(CLASS_ROLE); $shortName = Utils::getShortName($class); $this->assertEquals($shortName, "06ClassRole"); $longName = Utils::getLongName($shortName); $this->assertEquals($longName, $class->getUri()); }
/** * Short description of method loadProperties * * @access private * @author Joel Bout, <*****@*****.**> * @param boolean force * @param array additionalProperties * @return mixed */ private function loadProperties($force = false, $additionalProperties = array()) { if (is_null(self::$_properties) || $force) { if (!$force && $this->cacheModes['property'] == self::CACHE_FILE) { $serial = 'hard-api-property'; try { $cache = \common_cache_FileCache::singleton(); $properties = $cache->get($serial); self::$_properties = $properties; } catch (\common_cache_NotFoundException $e) { // The cache cannot be accessed, build the property cache. // get all the compiled tables $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); $tables = array(); $query = 'SELECT DISTINCT "id","table" FROM "class_to_table"'; $result = $dbWrapper->query($query); while ($row = $result->fetch()) { $tables[$row['id']] = $row['table']; } $additionalPropertiesTable = array(); $query = 'SELECT DISTINCT "class_id","property_uri" FROM "class_additional_properties"'; $result = $dbWrapper->query($query); while ($row = $result->fetch()) { $additionalPropertiesTable[$row['class_id']][] = new \core_kernel_classes_Property($row['property_uri']); } //retrieve each property by table $this->loadClasses(); self::$_properties = array(); foreach ($tables as $classId => $table) { //check in $additionalPropertiesTable if current table is concerned by additionnal properties if (isset($additionalPropertiesTable[$classId])) { $additionalProperties = $additionalPropertiesTable[$classId]; } else { $additionalProperties = array(); } $classUri = Utils::getLongName($table); $class = new \core_kernel_classes_Class($classUri); $topclassUri = self::$_classes[$classUri]['topclass']; $topclass = new \core_kernel_classes_Class($topclassUri); $ps = new PropertySwitcher($class, $topclass); $properties = $ps->getProperties($additionalProperties); foreach ($properties as $property) { $propertyUri = $property->getUri(); if ($property->isMultiple() || $property->isLgDependent()) { if (isset(self::$_properties[$propertyUri])) { if (!in_array("{$table}props", self::$_properties[$propertyUri])) { self::$_properties[$propertyUri][] = "{$table}props"; } } else { self::$_properties[$propertyUri] = array("{$table}props"); } } else { if (isset(self::$_properties[$propertyUri])) { if (!in_array("{$table}", self::$_properties[$propertyUri])) { self::$_properties[$propertyUri][] = "{$table}"; } } else { self::$_properties[$propertyUri] = array("{$table}"); } } } } //saving the properties in the cache file try { $cache = \common_cache_FileCache::singleton(); $cache->put(self::$_properties, $serial); } catch (\common_cache_Exception $e) { throw new Exception("cannot write the required property cache file for serial '{$serial}'."); } } } } }
/** * Short description of method duplicate * * @access public * @author Joel Bout, <*****@*****.**> * @param Resource resource * @param array excludedProperties * @return \core_kernel_classes_Resource */ public function duplicate(\core_kernel_classes_Resource $resource, $excludedProperties = array()) { $returnValue = null; $referencer = ResourceReferencer::singleton(); $tableName = $referencer->resourceLocation($resource); if (empty($tableName)) { return $returnValue; } //the new Uri $newUri = \common_Utils::getNewUri(); $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); //duplicate the row in the main table $query = 'SELECT * FROM "' . $tableName . '" WHERE "uri" = ?'; $result = $dbWrapper->query($query, array($resource->getUri())); $rows = $result->fetchAll(); if (count($rows) > 0) { //get the columns to duplicate $columnProps = array(); for ($i = 0; $i < $result->columnCount(); $i++) { $column = $result->getColumnMeta($i); if (preg_match("/^[0-9]{2,}/", $column['name'])) { $propertyUri = HardapiUtils::getLongName($column['name']); if (!in_array($propertyUri, $excludedProperties)) { //check if the property is excluded $columnProps[$propertyUri] = $column['name']; } } } // Fetch the first result. $instanceId = $rows[0]['id']; //build the insert query $insertQuery = 'INSERT INTO "' . $tableName . '" ("uri"'; foreach ($columnProps as $column) { if (!is_string($column)) { throw new Exception('columns should be a string'); } $insertQuery .= ', "' . $column . '"'; } $insertQuery .= ') VALUES ('; $insertQuery .= "'{$newUri}'"; foreach ($columnProps as $column) { $insertQuery .= ", '" . $rows[0][$column] . "'"; } $insertQuery .= ')'; $insertResult = $dbWrapper->exec($insertQuery); if ($insertResult !== false && $instanceId > -1) { //duplicated data $duplicatedResource = new \core_kernel_classes_Resource($newUri); $referencer->referenceResource($duplicatedResource, $tableName, $resource->getTypes(), true); $duplicateInstanceId = Utils::getInstanceId($duplicatedResource); //now we duplciate the rows of the Props table //linearize the excluded properties $excludedPropertyList = ''; foreach ($excludedProperties as $excludedProperty) { $excludedPropertyList .= "'{$excludedProperty}',"; } $excludedPropertyList = substr($excludedPropertyList, 0, strlen($excludedPropertyList) - 1); //query templates of the 3 ways to insert the props rows $insertPropValueQuery = 'INSERT INTO "' . $tableName . 'props" ("property_uri", "property_value", "l_language", "instance_id") VALUES (?,?,?,?)'; $insertPropForeignQuery = 'INSERT INTO "' . $tableName . 'props" ("property_uri", "property_foreign_uri", "l_language", "instance_id") VALUES (?,?,?,?)'; $insertPropEmptyQuery = 'INSERT INTO "' . $tableName . 'props" ("property_uri", "l_language", "instance_id") VALUES (?,?,?)'; //get the rows to duplicate try { $propsQuery = 'SELECT * FROM "' . $tableName . 'props" WHERE "instance_id" = ? '; $propsQuery .= empty($excludedPropertyList) ? '' : ' AND "property_uri" NOT IN (' . $excludedPropertyList . ') '; $propsResult = $dbWrapper->query($propsQuery, array($instanceId)); } catch (\PDOException $e) { throw new Exception("Unable to duplicate the resource {$resource->getUri()} : " . $e->getMessage()); } while ($row = $propsResult->fetch()) { $propUri = $row['property_uri']; $propValue = $row['property_value']; $propForeign = $row['property_foreign_uri']; $proplang = $row['l_language']; //insert them regarding the populated columns if (!is_null($propValue) && !empty($propValue)) { $dbWrapper->exec($insertPropValueQuery, array($propUri, $propValue, $proplang, $duplicateInstanceId)); } else { if (!is_null($propForeign) && !empty($propForeign)) { $dbWrapper->exec($insertPropForeignQuery, array($propUri, $propForeign, $proplang, $duplicateInstanceId)); } else { $dbWrapper->exec($insertPropEmptyQuery, array($propUri, $proplang, $duplicateInstanceId)); //costly to insert NULL values } } } //return the duplciated resource $returnValue = $duplicatedResource; } } return $returnValue; }
/** * Unhardify a specific class. Unhardifying a class implies that the instances of this * class will be transfered from specific optimized tables to the statement table, as RDF * triples. * * The $options array is an associative array where values are all booleans. The keys that * can be used to pass specific unhardify options are the following: * * - recursive: Unhardify the target class and its subclasses (default: false). * * @access public * @author Cédric Alfonsi, <*****@*****.**> * @param \core_kernel_classes_Class class * @param array options * @return boolean true if the resource was correctly unhardified, false otherwise. */ public function unhardify(\core_kernel_classes_Class $class, $options = array()) { $returnValue = (bool) false; $classLabel = $class->getLabel(); \common_Logger::i("Unhardifying class {$classLabel}", 'GENERIS'); if (defined("DEBUG_PERSISTENCE") && DEBUG_PERSISTENCE) { var_dump('unhardify ' . $class->getUri()); } // Check if the class has been hardened if (!ResourceReferencer::singleton()->isClassReferenced($class)) { \common_Logger::w("Class {$classLabel} could not be unhardened because it is not hardified."); return false; } //if defined, we take all the properties of the class and it's parents till the topclass $classLocations = ResourceReferencer::singleton()->classLocations($class); $topclass = null; if (count($classLocations) > 1) { throw new Exception("Try to unhardify the class {$class->getUri()} which has multiple locations"); } else { $topclass = new \core_kernel_classes_Class($classLocations[0]['topclass']); } //recursive will unhardify the class and it's subclasses in the same table! isset($options['recursive']) ? $recursive = $options['recursive'] : ($recursive = false); //removeForeigns will unhardify the class that are range of the properties isset($options['removeForeigns']) ? $removeForeigns = $options['removeForeigns'] : ($removeForeigns = false); //rmSources will remove the related data from the hard data after //transfer to the smooth data. $rmSources = true; // Get class' properties $propertySwitcher = new PropertySwitcher($class); $additionalProperties = array(); $properties = $propertySwitcher->getProperties($additionalProperties); $columns = $propertySwitcher->getTableColumns($additionalProperties, self::$blackList); // Get all instances of this class $startIndex = 0; $instancePackSize = 100; $instances = $class->getInstances(false, array('offset' => $startIndex, 'limit' => $instancePackSize)); $count = count($instances); $existingInstances = array(); do { //reset timeout: \helpers_TimeOutHelper::setTimeOutLimit(\helpers_TimeOutHelper::MEDIUM); // lionel did that :d le salop PersistenceProxy::forceMode(PERSISTENCE_SMOOTH); foreach ($instances as $uri => $instance) { if ($instance->exists()) { PersistenceProxy::forceMode(PERSISTENCE_HARD); $instance->delete(); PersistenceProxy::restoreImplementation(); unset($instances[$uri]); $existingInstances[] = $uri; } } PersistenceProxy::restoreImplementation(); foreach ($instances as $instance) { // Get table name where the resource is located $tableName = ResourceReferencer::singleton()->resourceLocation($instance); // Get Instance type $types = $instance->getTypes(); // Create instance in the smooth implementation PersistenceProxy::forceMode(PERSISTENCE_SMOOTH); $class->createInstance('', '', $instance->getUri()); // set types to the newly created instance foreach ($types as $type) { if (!$type->equals($class)) { $instance->setType($type); } } PersistenceProxy::restoreImplementation(); // Export properties of the instance foreach ($columns as $column) { $property = new \core_kernel_classes_Property(Utils::getLongName($column['name'])); // Multiple property if (isset($column['multi']) && $column['multi']) { $sqlQuery = 'SELECT "' . $tableName . 'props"."property_value", "' . $tableName . 'props"."property_foreign_uri", "' . $tableName . 'props"."l_language" FROM "' . $tableName . 'props" LEFT JOIN "' . $tableName . '" ON "' . $tableName . '"."id" = "' . $tableName . 'props"."instance_id" WHERE "' . $tableName . '"."uri" = ? AND "' . $tableName . 'props"."property_uri" = ?'; $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); $sqlResult = $dbWrapper->query($sqlQuery, array($instance->getUri(), $property->getUri())); if ($sqlResult->errorCode() !== '00000') { throw new Exception("unable to unhardify : " . $dbWrapper->errorMessage()); } // ENTER IN SMOOTH SQL MODE PersistenceProxy::forceMode(PERSISTENCE_SMOOTH); while ($row = $sqlResult->fetch()) { $value = null; if (!empty($row['property_value'])) { $value = $row['property_value']; } else { $value = $row['property_foreign_uri']; } $lg = $row['l_language']; if (!empty($lg)) { $instance->setPropertyValueByLg($property, $value, $lg); } else { $instance->setPropertyValue($property, $value); } } /// EXIT HARD SQL MODE PersistenceProxy::restoreImplementation(); } else { $value = $instance->getOnePropertyValue($property); if ($value != null) { PersistenceProxy::forceMode(PERSISTENCE_SMOOTH); $instance->setPropertyValue($property, $value); PersistenceProxy::restoreImplementation(); } } } // delete instance in the hard implementation $instance->delete(); } //record decompiled instances number if (isset($this->decompiledClasses[$class->getUri()])) { $this->decompiledClasses[$class->getUri()] += $count; } else { $this->decompiledClasses[$class->getUri()] = $count; } //update instance array and count value $instances = $class->getInstances(false, array('offset' => $startIndex, 'limit' => $instancePackSize)); foreach ($existingInstances as $uri) { unset($instances[$uri]); } $count = count($instances); \helpers_TimeOutHelper::reset(); } while ($count > 0); // Unreference the class $returnValue = ResourceReferencer::singleton()->unReferenceClass($class); // If recursive, treat the subclasses if ($recursive) { foreach ($class->getSubClasses(true) as $subClass) { if (ResourceReferencer::singleton()->isClassReferenced($subClass)) { $returnValue = $this->unhardify($subClass, $options); } } } return (bool) $returnValue; }