/** * Short description of method referenceInstanceTypes * * @access public * @author Joel Bout, <*****@*****.**> * @param Class class * @return boolean */ public function referenceInstanceTypes(\core_kernel_classes_Class $class) { $returnValue = (bool) false; $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); $query = "SELECT DISTINCT object FROM statements \n \t\t\tWHERE predicate = ? \n \t\t\tAND object != ?\n \t\t\tAND subject IN (SELECT subject FROM statements \n \t\t\t\t\t\tWHERE predicate = ? \n \t\t\t\t\t\tAND object = ?)"; $result = $dbWrapper->query($query, array(RDF_TYPE, $class->getUri(), RDF_TYPE, $class->getUri())); $types = array(); while ($row = $result->fetch()) { $types[] = $row['object']; } $tableName = '_' . Utils::getShortName($class); foreach ($types as $type) { $this->referenceClass(new \core_kernel_classes_Class($type), array("table" => $tableName)); } return (bool) $returnValue; }
public function propertyDescriptor(\core_kernel_classes_Property $property, $hardRangeClassOnly = false) { $returnValue = array('name' => Utils::getShortName($property), 'isMultiple' => $property->isMultiple(), 'isLgDependent' => $property->isLgDependent(), 'range' => array()); $range = $property->getRange(); $rangeClassName = Utils::getShortName($range); if ($hardRangeClassOnly) { if (ResourceReferencer::singleton()->isClassReferenced($range)) { $returnValue[] = $rangeClassName; } } else { $returnValue[] = $rangeClassName; } return (array) $returnValue; }
/** * Short description of method getPropertiesValues * * @access public * @author Joel Bout, <*****@*****.**> * @param Resource resource * @param array properties * @return array */ public function getPropertiesValues(\core_kernel_classes_Resource $resource, $properties) { $returnValue = array(); $referencer = ResourceReferencer::singleton(); $table = ResourceReferencer::singleton()->resourceLocation($resource); if (empty($table)) { return $returnValue; } $tableProps = $table . 'props'; $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); $propertiesMain = ''; $propertiesProps = ''; $propertyIndexes = array(); $propertyIndex = 0; foreach ($properties as $propertyMixed) { $property = is_object($propertyMixed) ? $propertyMixed : new \core_kernel_classes_Property($propertyMixed); $propertyLocation = $referencer->propertyLocation($property); if (in_array($tableProps, $propertyLocation) || !$referencer->isPropertyReferenced($property)) { if (!empty($propertiesProps)) { $propertiesProps .= ", "; } $propertiesProps .= "'" . $property->getUri() . "'"; } else { try { $propertyAlias = HardapiUtils::getShortName($property); if (!empty($propertiesMain)) { $propertiesMain .= ', '; } $propertiesMain .= '"' . $propertyAlias . '" as "propertyValue' . $propertyIndex . '"'; $propertyIndexes[$propertyIndex] = $property; $propertyIndex++; } catch (\common_exception_UnknownNamespace $e) { // unknown property } } } if (!empty($propertiesProps)) { // Define language if required $lang = ''; $defaultLg = ''; $options = array(); //@TODO: option to be implemented if (isset($options['lg'])) { $lang = $options['lg']; } else { $lang = \common_session_SessionManager::getSession()->getDataLanguage(); $defaultLg = ' OR "l_language" = \'' . DEFAULT_LANG . '\' '; } $query = 'SELECT "property_uri", "property_value", "property_foreign_uri" FROM "' . $table . '" INNER JOIN "' . $tableProps . '" on "' . $table . '"."id" = "' . $tableProps . '"."instance_id" WHERE "' . $table . '"."uri" = ? AND "' . $tableProps . '"."property_uri" IN (' . $propertiesProps . ') AND ( "l_language" = ? OR "l_language" = \'\' ' . $defaultLg . ') ORDER BY "property_uri"'; try { $result = $dbWrapper->query($query, array($resource->getUri(), $lang)); } catch (\PDOException $e) { throw new Exception("Unable to get property (multiple) values for {$resource->getUri()} in {$table} : " . $e->getMessage()); } $currentPredicate = null; while ($row = $result->fetch()) { if ($currentPredicate != $row['property_uri']) { $currentPredicate = $row['property_uri']; $returnValue[$currentPredicate] = array(); } $value = $row['property_value'] != null ? $row['property_value'] : $row['property_foreign_uri']; $returnValue[$currentPredicate][] = \common_Utils::isUri($value) ? new \core_kernel_classes_Resource($value) : new \core_kernel_classes_Literal($value); } } if (!empty($propertiesMain)) { try { $query = 'SELECT ' . $propertiesMain . ' FROM "' . $table . '" WHERE "uri" = ?'; $result = $dbWrapper->query($query, array($resource->getUri())); while ($row = $result->fetch()) { foreach ($propertyIndexes as $propertyIndex => $property) { $returnValue[$property->getUri()] = array(); if ($row['propertyValue' . $propertyIndex] != null) { $value = $row['propertyValue' . $propertyIndex]; $returnValue[$property->getUri()][] = \common_Utils::isUri($value) ? new \core_kernel_classes_Resource($value) : new \core_kernel_classes_Literal($value); } } } } catch (\PDOException $e) { if ($e->getCode() == $dbWrapper->getColumnNotFoundErrorCode()) { // Column doesn't exists is not an error. Try to get a property which does not exist is allowed } else { if ($e->getCode() !== '00000') { throw new Exception("Unable to get property (single) values for {$resource->getUri()} in {$table} : " . $e->getMessage()); } } } } return (array) $returnValue; }
/** * Will create an Index (in the RDBMS) for all the promperties passed as * a parameter. This may increase the performance of the system. * * @static * @access public * @param array $indexProperties * @throws Exception * @return boolean If it succeeds, false otherwise. */ public static function createIndex($indexProperties = array()) { $referencer = ResourceReferencer::singleton(); $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); foreach ($indexProperties as $indexProperty) { $property = new \core_kernel_classes_Property($indexProperty); $propertyAlias = Utils::getShortName($property); foreach ($referencer->propertyLocation($property) as $table) { if (!preg_match("/props\$/", $table) && preg_match("/^_[0-9]{2,}/", $table)) { try { $indexName = 'idx_' . $table . '_' . $propertyAlias; if (strlen($indexName) > 64) { $md5 = md5($indexName); $indexName = substr($indexName, 0, 30) . $md5; } $dbWrapper->createIndex($indexName, $dbWrapper->quoteIdentifier($table), array($dbWrapper->quoteIdentifier($propertyAlias) => 255)); } catch (\Exception $e) { if ($e->getCode() != $dbWrapper->getIndexAlreadyExistsErrorCode() && $e->getCode() != '00000') { throw new Exception("Unable to create index 'idx_{$propertyAlias}' for property alias '{$propertyAlias}' on table '{$table}': {$e->getMessage()}"); } else { \common_Logger::e('something go wrong when creating index idx_' . $propertyAlias . ' on table ' . $table . ' : ' . $e->getMessage()); } } } } } return true; }
/** * (non-PHPdoc) * @see core_kernel_persistence_ClassInterface::createInstanceWithProperties() */ public function createInstanceWithProperties(\core_kernel_classes_Class $type, $properties) { $returnValue = null; if (isset($properties[RDF_TYPE])) { throw new \core_kernel_persistence_Exception('Additional types in createInstanceWithProperties not permited'); } $uri = \common_Utils::getNewUri(); $table = '_' . HardapiUtils::getShortName($type); // prepare properties $hardPropertyNames = array("uri" => $uri); $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); if (is_array($properties)) { if (count($properties) > 0) { // Get the table name $referencer = ResourceReferencer::singleton(); $queryProps = array(); foreach ($properties as $propertyUri => $value) { $property = new \core_kernel_classes_Property($propertyUri); $propertyLocation = $referencer->propertyLocation($property); if (in_array("{$table}props", $propertyLocation) || !$referencer->isPropertyReferenced($property)) { $propertyRange = $property->getRange(); $lang = $property->isLgDependent() ? \common_session_SessionManager::getSession()->getDataLanguage() : ''; $formatedValues = array(); if ($value instanceof \core_kernel_classes_Resource) { $formatedValues[] = $dbWrapper->quote($value->getUri()); } else { if (is_array($value)) { foreach ($value as $val) { if ($val instanceof \core_kernel_classes_Resource) { $formatedValues[] = $dbWrapper->quote($val->getUri()); } else { $formatedValues[] = $dbWrapper->quote($val); } } } else { $formatedValues[] = $dbWrapper->quote($value); } } if (is_null($propertyRange) || $propertyRange->getUri() == RDFS_LITERAL) { foreach ($formatedValues as $formatedValue) { $queryProps[] = "'{$property->getUri()}', {$formatedValue}, null, '{$lang}'"; } } else { foreach ($formatedValues as $formatedValue) { $queryProps[] = "'{$property->getUri()}', null, {$formatedValue}, '{$lang}'"; } } } else { $propertyName = HardapiUtils::getShortName($property); if (is_array($value)) { if (count($value) > 1) { throw new Exception("try setting multivalue for the non multiple property {$property->getLabel()} ({$property->getUri()})"); } else { $value = count($value) == 0 ? null : reset($value); // take the only element } } if ($value instanceof \core_kernel_classes_Resource) { $value = $value->getUri(); } $hardPropertyNames[$propertyName] = $value; } } } } // spawn $returnValue = new \core_kernel_classes_Resource($uri, __METHOD__); $varnames = '"' . implode('","', array_keys($hardPropertyNames)) . '"'; try { $query = 'INSERT INTO "' . $table . '" (' . $varnames . ') VALUES (' . implode(',', array_fill(0, count($hardPropertyNames), '?')) . ')'; $result = $dbWrapper->exec($query, array_values($hardPropertyNames)); // reference the newly created instance ResourceReferencer::singleton()->referenceResource($returnValue, $table, array($type), true); // @todo this shoould be retrievable without an aditional query $instanceId = Utils::getInstanceId($returnValue); // @todo Merge into a single query if (!empty($queryProps)) { $prefixed = array(); foreach ($queryProps as $row) { $prefixed[] = ' (' . $instanceId . ', ' . $row . ')'; } try { $query = 'INSERT INTO "' . $table . 'props" ("instance_id", "property_uri", "property_value", "property_foreign_uri", "l_language") VALUES ' . implode(',', $prefixed); $result = $dbWrapper->exec($query); } catch (\PDOException $e) { throw new Exception("Unable to set properties (multiple) Value for the instance {$returnValue->getUri()} in {$tableName} : " . $e->getMessage()); } } } catch (\PDOException $e) { throw new Exception("Unable to create instance for the class {$type->getUri()} in the table {$table} : " . $e->getMessage()); } return $returnValue; }
/** * Test the referencer on properties, using the file caching mode * (it's the default caching mode for the properties) * @see oat\generisHard\models\hardapi\ResourceReferencer */ public function testPropertyReferencer() { $referencer = ResourceReferencer::singleton(); $this->assertIsA($referencer, 'oat\\generisHard\\models\\hardapi\\ResourceReferencer'); $referencer->setPropertyCache(ResourceReferencer::CACHE_FILE); $referencer->clearCaches(); $class = new core_kernel_classes_Class(CLASS_GENERIS_USER); $table = '_' . Utils::getShortName($class); // this part simulates a hardifying of the Userclass $myUserTblMgr = new TableManager($table); $this->assertFalse($myUserTblMgr->exists()); $this->assertTrue($myUserTblMgr->create(array(array('name' => '05label'), array('name' => '05comment'), array('name' => '07login'), array('name' => '07password'), array('name' => '07userMail'), array('name' => '07userFirstName'), array('name' => '07userLastName')))); $this->assertTrue($myUserTblMgr->exists()); $referencer->referenceClass($class); $this->assertTrue($referencer->isClassReferenced($class)); // test start on the cache containing the simulated data // in case of a fallback to the real sata (class_to_table) the tests fail $labelProperty = new core_kernel_classes_Property(RDFS_LABEL); $this->assertTrue($referencer->isPropertyReferenced($labelProperty)); $commentProperty = new core_kernel_classes_Property(RDFS_COMMENT); $this->assertTrue($referencer->isPropertyReferenced($commentProperty)); $loginProperty = new core_kernel_classes_Property(PROPERTY_USER_LOGIN); $this->assertTrue($referencer->isPropertyReferenced($loginProperty)); $passwordProperty = new core_kernel_classes_Property(PROPERTY_USER_PASSWORD); $this->assertTrue($referencer->isPropertyReferenced($passwordProperty)); $firstNameProperty = new core_kernel_classes_Property(PROPERTY_USER_FIRSTNAME); foreach ($referencer->propertyLocation($firstNameProperty) as $foundTable) { $this->assertEquals($foundTable, $table); } $this->assertTrue($myUserTblMgr->exists()); $referencer->unReferenceClass($class); $this->assertFalse($referencer->isClassReferenced($class)); $this->assertFalse($myUserTblMgr->exists()); // Testing the cache... $cache = common_cache_FileCache::singleton(); $serial = 'hard-api-property'; $this->assertTrue($cache->has($serial)); try { $cacheContent = $cache->get($serial); $this->assertTrue(is_array($cacheContent)); $this->assertTrue(count($cacheContent) > 0); $this->assertTrue(array_key_exists(RDFS_LABEL, $cacheContent)); $this->assertTrue(array_key_exists(PROPERTY_USER_LOGIN, $cacheContent)); } catch (common_cache_Exception $e) { $this->fail('Cannot access hard-api-property cache.'); } //clear the cache $cache->remove($serial); $this->assertFalse($cache->has($serial)); }
public function testHardPropertyModifications() { $this->hardify(); $this->createData(); $dbWrapper = core_kernel_classes_DbWrapper::singleton(); $movieClass = $this->targetMovieClass; $workClass = $this->targetWorkClass; $authorProperty = $this->targetAuthorProperty; $producerProperty = $this->targetProducerProperty; $actorsProperty = $this->targetActorsProperty; $labelProperty = new core_kernel_classes_Property(RDFS_LABEL); $referencer = ResourceReferencer::singleton(); $propertyProxy = PropertyProxy::singleton(); // Retrieve interesting resources. $instances = $workClass->searchInstances(array($authorProperty->getUri() => 'Leonardo da Vinci'), array('like' => false, 'recursive' => false)); $monaLisa = current($instances); $instances = $movieClass->searchInstances(array($labelProperty->getUri() => 'The Lord of the Rings'), array('like' => false, 'recursive' => false)); $lordOfTheRings = current($instances); $instances = $movieClass->searchInstances(array($labelProperty->getUri() => 'The Hobbit'), array('like' => true, 'recursive' => false)); $theHobbit = current($instances); if (empty($monaLisa) || empty($lordOfTheRings) || empty($theHobbit)) { $this->fail("Unable to retrieve instances that will be used in the following tests."); } else { // Try to create a new scalar property after hardification. $testProperty = $movieClass->createProperty('after hardify property'); $testPropertyShortName = Utils::getShortName($testProperty); $testPropertyLocations = $referencer->propertyLocation($testProperty); $movieClassLocations = $referencer->classLocations($movieClass); $movieClassTable = $movieClassLocations[0]['table']; $movieClassTableColumns = array(); foreach ($dbWrapper->getColumnNames($movieClassTable) as $col) { $movieClassTableColumns[] = $col->getName(); } $workClassLocations = $referencer->classLocations($workClass); $workClassTable = $movieClassLocations[0]['table']; $workClassTableColumns = $dbWrapper->getColumnNames($workClassTable); $testPropertyShortName = Utils::getShortName($testProperty); $authorPropertyShortName = Utils::getShortName($authorProperty); // test delegation and presence of the column. $this->assertFalse($testProperty->isMultiple()); $this->assertTrue(in_array($testPropertyShortName, $movieClassTableColumns)); $this->assertIsA($propertyProxy->getImpToDelegateTo($testProperty), 'oat\\generisHard\\models\\hardsql\\Property'); // set language dependency of the test property to true. $testProperty->setLgDependent(true); $this->assertTrue($testProperty->isLgDependent()); $movieClassTableColumns = array(); foreach ($dbWrapper->getColumnNames($movieClassTable) as $col) { $movieClassTableColumns[] = $col->getName(); } $this->assertFalse(in_array($testPropertyShortName, $movieClassTableColumns)); // create some property values for the test property. $testMovie = $movieClass->createInstance('A Test Movie'); $testMovie->setPropertyValue($testProperty, 'EN-TestPropertyValue-1'); $testMovie->setPropertyValueByLg($testProperty, 'EN-TestPropertyValue-2', DEFAULT_LANG); $testMovie->setPropertyValueByLg($testProperty, 'FR-TestPropertyValue-1', 'FR'); $testPropertyValues = $testMovie->getPropertyValues($testProperty); $this->assertEquals(count($testPropertyValues), 2); // Only EN values will come back. $testPropertyValues = $testMovie->getPropertyValuesByLg($testProperty, DEFAULT_LANG); $this->assertEquals(count($testPropertyValues->sequence), 2); $testPropertyValues = $testMovie->getPropertyValuesByLg($testProperty, 'FR'); $this->assertEquals(count($testPropertyValues->sequence), 1); // set back the language dependency of the test property to false. $testProperty->setLgDependent(false); $this->assertFalse($testProperty->isLgDependent()); $movieClassTableColumns = array(); foreach ($dbWrapper->getColumnNames($movieClassTable) as $col) { $movieClassTableColumns[] = $col->getName(); } $this->assertTrue(in_array($testPropertyShortName, $movieClassTableColumns)); $testPropertyValues = $testMovie->getPropertyValues($testProperty); $this->assertEquals(count($testPropertyValues), 1); // set the author property to multiple. $this->assertTrue(in_array($authorPropertyShortName, $movieClassTableColumns)); $this->assertFalse($authorProperty->isMultiple()); $authorProperty->setMultiple(true); $this->assertTrue($authorProperty->isMultiple()); $movieClassTableColumns = array(); foreach ($dbWrapper->getColumnNames($movieClassTable) as $col) { $movieClassTableColumns[] = $col->getName(); } $this->assertFalse(in_array($authorPropertyShortName, $movieClassTableColumns)); // Add a fake value to make it multi valued $theHobbit->setPropertyValue($authorProperty, 'The Clone of Peter Jackson'); $authors = $theHobbit->getPropertyValues($authorProperty); $this->assertEquals(count($authors), 2); $this->assertEquals(current($authors), 'Peter Jackson'); next($authors); $this->assertEquals(current($authors), 'The Clone of Peter Jackson'); $authors = $monaLisa->getPropertyValues($authorProperty); $this->assertEquals(count($authors), 1); $this->assertEquals(current($authors), 'Leonardo da Vinci'); // reset the author property to scalar. $authorProperty->setMultiple(false); $this->assertFalse($authorProperty->isMultiple()); $movieClassTableColumns = array(); foreach ($dbWrapper->getColumnNames($movieClassTable) as $col) { $movieClassTableColumns[] = $col->getName(); } $this->assertTrue(in_array($authorPropertyShortName, $movieClassTableColumns)); $authors = $theHobbit->getPropertyValues($authorProperty); $this->assertEquals(count($authors), 1); $this->assertEquals(current($authors), 'Peter Jackson'); } }
/** * Short description of method setLgDependent * * @access public * @author Jerome Bogaerts, <*****@*****.**> * @param Resource resource * @param boolean isLgDependent * @return void */ public function setLgDependent(\core_kernel_classes_Resource $resource, $isLgDependent) { // First, do the same as in smooth mode. \core_kernel_persistence_smoothsql_Property::singleton()->setLgDependent($resource, $isLgDependent); // Second, we alter the relevant table(s) if needed. // For all the classes that have the resource as domain, // we have to alter the correspondent tables. $referencer = ResourceReferencer::singleton(); $dbWrapper = \core_kernel_classes_DbWrapper::singleton(); $propertyDescription = HardapiUtils::propertyDescriptor($resource); $wasMulti = $propertyDescription['isMultiple']; $wasLgDependent = $propertyDescription['isLgDependent']; // @TODO $batchSize's value is arbitrary. $batchSize = 100; // Transfer data $batchSize by $batchSize. if ($wasLgDependent != $isLgDependent) { try { // The multiplicity is then changing. // However, if the property was not 'language dependent' but 'multiple' // it is already stored as it should. if ($isLgDependent == true && $wasMulti == false && $wasLgDependent == false) { // We go from single to multiple. HardapiUtils::scalarToMultiple($resource, $batchSize); } else { if ($isLgDependent == false && ($wasMulti == true || $wasLgDependent == true)) { // We go from multiple to single. HardapiUtils::multipleToScalar($resource, $batchSize); } } } catch (HardapiException $e) { throw new Exception($e->getMessage()); } } }