/** * Calling this method will transfer all instances of $class from the statements table * to specific optimized relational tables. * * During optimization, the current user has all privileges on the persistent memory. At * the end of the process, the old privileges will be set back. * * The $options array can contain the following key => values (all booleans): * * - recursive: compile the target class and its subclasses (default: false). * - append: append data to the existing optimized table if it already exists (default: false). * - rmSources: remove the triples in the statement table after transfer (default: true). * * @access public * @author Bertrand Chevrier, <*****@*****.**> * @param \core_kernel_classes_Class class * @param array options * @return boolean Will return true if it succeeds, false otherwise. */ public function hardify(\core_kernel_classes_Class $class, $options = array()) { $returnValue = (bool) false; $oldUpdatableModels = core_kernel_persistence_smoothsql_SmoothModel::getUpdatableModelIds(); try { // Give access to all models during hardification. core_kernel_persistence_smoothsql_SmoothModel::forceUpdatableModelIds(self::getAllModelIds()); $classLabel = $class->getLabel(); \common_Logger::i("Hardifying class {$classLabel}", array("GENERIS")); if (defined("DEBUG_PERSISTENCE") && DEBUG_PERSISTENCE) { if (in_array($class->getUri(), self::$debug_tables)) { return; } \common_Logger::d('hardify ' . $class->getUri()); self::$debug_tables[] = $class->getUri(); $countStatement = $this->countStatements(); } if (in_array($class->getUri(), self::$blackList)) { return $returnValue; } // ENTER IN SMOOTH SQL MODE PersistenceProxy::forceMode(PERSISTENCE_SMOOTH); //recursive will hardify the class and it's subclasses in the same table! isset($options['recursive']) ? $recursive = $options['recursive'] : ($recursive = false); //createForeigns will hardify the class that are range of the properties isset($options['createForeigns']) ? $createForeigns = $options['createForeigns'] : ($createForeigns = false); //check if we append the data in case the hard table exists or truncate the table and add the new rows isset($options['append']) ? $append = $options['append'] : ($append = false); //if true, the instances of the class will be removed from the statements table! isset($options['rmSources']) ? $rmSources = (bool) $options['rmSources'] : ($rmSources = false); //if defined, we took all the properties of the class and it's parents till the topclass isset($options['topclass']) ? $topclass = $options['topclass'] : ($topclass = new \core_kernel_classes_Class(RDFS_RESOURCE)); //if defined, compile the additional properties isset($options['additionalProperties']) ? $additionalProperties = $options['additionalProperties'] : ($additionalProperties = array()); //if defined, reference the additional class to the table isset($options['referencesAllTypes']) ? $referencesAllTypes = $options['referencesAllTypes'] : ($referencesAllTypes = false); $tableName = '_' . Utils::getShortName($class); $myTableMgr = new TableManager($tableName); $referencer = ResourceReferencer::singleton(); //get the table columns from the class properties $columns = array(); $ps = new PropertySwitcher($class); $properties = $ps->getProperties($additionalProperties); $columns = $ps->getTableColumns($additionalProperties, self::$blackList); //init the count value in hardened classes: if (isset($this->hardenedClasses[$class->getUri()])) { PersistenceProxy::restoreImplementation(); return true; //already being compiled } else { $this->hardenedClasses[$class->getUri()] = 0; } if (!$append || $append && !$myTableMgr->exists()) { //create the table if ($myTableMgr->exists()) { $myTableMgr->remove(); } $myTableMgr->create($columns); //reference the class $referencer->referenceClass($class, array("topclass" => $topclass, "additionalProperties" => $additionalProperties)); if ($referencesAllTypes) { $referencer->referenceInstanceTypes($class); } } //insert the resources $startIndex = 0; $instancePackSize = 100; $instances = $class->getInstances(false, array('offset' => $startIndex, 'limit' => $instancePackSize)); $count = count($instances); $notDeletedInstances = array(); do { //reset timeout: //set_time_limit(30); \helpers_TimeOutHelper::setTimeOutLimit(\helpers_TimeOutHelper::MEDIUM); $rows = array(); foreach ($instances as $index => $resource) { if ($referencer->isResourceReferenced($resource)) { PersistenceProxy::forceMode(PERSISTENCE_HARD); $resource->delete(); PersistenceProxy::restoreImplementation(); } $row = array('uri' => $resource->getUri()); foreach ($properties as $property) { $propValue = $resource->getOnePropertyValue($property); $row[Utils::getShortName($property)] = $propValue; } $rows[] = $row; } $rowMgr = new RowManager($tableName, $columns); $rowMgr->insertRows($rows); foreach ($instances as $resource) { $referencer->referenceResource($resource, $tableName, null, true); if ($rmSources) { //remove exported resources in smooth sql, if required: // Be carefull, the resource can still exist even if // delete returns true. Indeed, modelIds can be mixed between // multiple models and only a part of the triples that consitute // the resource might have been deleted. if (!$resource->delete() || $resource->exists()) { //@TODO : modified resource::delete() because resource not in local modelId cannot be deleted $notDeletedInstances[] = $resource->getUri(); $startIndex++; } } } if (!$rmSources) { //increment start index only if not removed $startIndex += $instancePackSize; } //record hardened instances number if (isset($this->hardenedClasses[$class->getUri()])) { $this->hardenedClasses[$class->getUri()] += $count; } else { $this->hardenedClasses[$class->getUri()] = $count; } //update instance array and count value $instances = $class->getInstances(false, array('offset' => $startIndex, 'limit' => $instancePackSize)); foreach ($notDeletedInstances as $uri) { unset($instances[$uri]); } $count = count($instances); \helpers_TimeOutHelper::reset(); } while ($count > 0); $returnValue = true; // Treat subclasses of the current class if ($recursive) { foreach ($class->getSubClasses(true) as $subClass) { $returnValue = $this->hardify($subClass, array_merge($options, array('recursive' => false, 'append' => true))); } } //reset cache: $referencer->clearCaches(); // EXIT SMOOTH SQL MODE PersistenceProxy::restoreImplementation(); if (defined("DEBUG_PERSISTENCE") && DEBUG_PERSISTENCE) { $this->unhardify($class, array_merge($options, array('recursive' => false, 'removeForeigns' => false))); \common_Logger::d('unhardened result statements ' . $this->countStatements() . ' / ' . $countStatement); } // Give the normal rights on models to the session. core_kernel_persistence_smoothsql_SmoothModel::forceUpdatableModelIds($oldUpdatableModels); } catch (Exception $e) { \common_Logger::e('An error occured during hardification: ' . $e->getMessage()); core_kernel_persistence_smoothsql_SmoothModel::forceUpdatableModelIds($oldUpdatableModels); } return (bool) $returnValue; }
public function testForceMode() { $this->hardify(); // Check if the returner implementation are correct PersistenceProxy::forceMode(PERSISTENCE_SMOOTH); $classProxy = ClassProxy::singleton(); $impl = $classProxy->getImpToDelegateTo($this->targetSubjectClass); $this->assertTrue($impl instanceof core_kernel_persistence_smoothsql_Class); $this->assertEquals(count($this->targetSubjectClass->getInstances()), 1); $this->assertEquals(count($this->targetSubjectSubClass->getInstances()), 1); PersistenceProxy::restoreImplementation(); $this->assertTrue(ClassProxy::singleton()->getImpToDelegateTo($this->targetSubjectClass) instanceof Clazz); $this->assertTrue(ResourceProxy::singleton()->getImpToDelegateTo($this->subject1) instanceof Resource); }
/** * Retrieve the inplementation to delegate * * @access public * @author Joel Bout, <*****@*****.**> * @param Resource resource * @param array params * @return \core_kernel_persistence_ResourceInterface */ public function getImpToDelegateTo(core_kernel_classes_Resource $resource, $params = array()) { $returnValue = null; if (!isset(self::$ressourcesDelegatedTo[$resource->getUri()]) || PersistenceProxy::isForcedMode()) { $impls = $this->getAvailableImpl($params); foreach ($impls as $implName => $enable) { // If the implementation is enabled && the resource exists in this context if ($enable && $this->isValidContext($implName, $resource)) { $implClass = self::$implClasses[$implName]; $reflectionMethod = new \ReflectionMethod($implClass, 'singleton'); $delegate = $reflectionMethod->invoke(null); if (PersistenceProxy::isForcedMode()) { return $delegate; } self::$ressourcesDelegatedTo[$resource->getUri()] = $delegate; break; } } } if (isset(self::$ressourcesDelegatedTo[$resource->getUri()])) { $returnValue = self::$ressourcesDelegatedTo[$resource->getUri()]; } else { $errorMessage = "The resource with uri {$resource->getUri()} does not exist in the available implementation(s): "; $i = 0; foreach ($this->getAvailableImpl() as $name => $valid) { if ($valid) { if ($i > 0) { $errorMessage .= ", "; } $errorMessage .= $name; } $i++; } throw new \core_kernel_persistence_Exception($errorMessage); } return $returnValue; }
/** * Short description of method getImpToDelegateTo * * @access public * @author Jerome Bogaerts, <*****@*****.**> * @param Resource resource * @param array params * @return \core_kernel_persistence_ResourceInterface */ public function getImpToDelegateTo(\core_kernel_classes_Resource $resource, $params = array()) { if (!isset(self::$ressourcesDelegatedTo[$resource->getUri()]) || PersistenceProxy::isForcedMode()) { $impls = $this->getAvailableImpl($params); foreach ($impls as $implName => $enable) { // If the implementation is enabled && the resource exists in this context if ($enable && $this->isValidContext($implName, $resource)) { $implClass = self::$implClasses[$implName]; $reflectionMethod = new \ReflectionMethod($implClass, 'singleton'); $delegate = $reflectionMethod->invoke(null); if (PersistenceProxy::isForcedMode()) { return $delegate; } self::$ressourcesDelegatedTo[$resource->getUri()] = $delegate; break; } } } return self::$ressourcesDelegatedTo[$resource->getUri()]; }
public function testSearchInstancesHard($hard = true) { if (!$hard) { return; } PersistenceProxy::forceMode(PERSISTENCE_HARD); $class = new core_kernel_classes_Class('http://www.tao.lu/Ontologies/TAO.rdf#Languages'); if (ResourceReferencer::singleton()->isClassReferenced($class)) { $propertyFilter = array(RDFS_LABEL => 'English'); $options = array('like' => false, 'recursive' => 0); $languagesDependantProp = $class->searchInstances($propertyFilter, $options); $found = count($languagesDependantProp); $this->assertTrue($found > 0); $propertyFilter = array(RDF_VALUE => 'EN', RDF_TYPE => 'http://www.tao.lu/Ontologies/TAO.rdf#Languages'); $languagesDependantProp = $class->searchInstances($propertyFilter, $options); $nfound = count($languagesDependantProp); $this->assertTrue($nfound > 0); $this->assertEquals($found, $nfound); } PersistenceProxy::restoreImplementation(); }