PageRenderTime 62ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/application/controllers/ServiceController.php

https://bitbucket.org/udfr/uc3-udfr-ontowiki
PHP | 1253 lines | 889 code | 167 blank | 197 comment | 180 complexity | 1ac34495dbd3605277276f182e08aa2a MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. <?php
  2. /*
  3. * This File is edited by UDFR for different requirement
  4. */
  5. /**
  6. * OntoWiki service controller.
  7. *
  8. * @package application
  9. * @subpackage mvc
  10. * @copyright Copyright (c) 2010, {@link http://aksw.org AKSW}
  11. * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
  12. */
  13. class ServiceController extends Zend_Controller_Action
  14. {
  15. /** @var OntoWiki */
  16. protected $_owApp = null;
  17. /** @var Zend_Config */
  18. protected $_config = null;
  19. /**
  20. * Attempts an authentication to the underlying Erfurt framework via
  21. * HTTP GET/POST parameters.
  22. */
  23. public function authAction()
  24. {
  25. if (!$this->_config->service->allowGetAuth) {
  26. // disallow get
  27. if (!$this->_request->isPost()) {
  28. $this->_response->setRawHeader('HTTP/1.0 405 Method Not Allowed');
  29. $this->_response->setRawHeader('Allow: POST');
  30. exit();
  31. }
  32. }
  33. // fetch params
  34. if (isset($this->_request->logout)) {
  35. $logout = $this->_request->logout == 'true' ? true : false;
  36. } elseif (isset($this->_request->u)) {
  37. $username = $this->_request->u;
  38. $password = $this->_request->getParam('p', '');
  39. } else {
  40. $this->_response->setRawHeader('HTTP/1.0 400 Bad Request');
  41. // $this->_response->setRawHeader('');
  42. exit();
  43. }
  44. if ($logout) {
  45. // logout
  46. Erfurt_Auth::getInstance()->clearIdentity();
  47. session_destroy();
  48. $this->_response->setRawHeader('HTTP/1.0 200 OK');
  49. exit();
  50. } else {
  51. // authenticate
  52. $result = $owApp->erfurt->authenticate($username, $password);
  53. }
  54. // return HTTP result
  55. if ($result->isValid()) {
  56. // return success (200)
  57. $this->_response->setRawHeader('HTTP/1.0 200 OK');
  58. exit();
  59. } else {
  60. // return fail (401)
  61. $this->_response->setRawHeader('HTTP/1.0 401 Unauthorized');
  62. exit();
  63. }
  64. }
  65. /**
  66. * Entity search
  67. */
  68. public function entitiesAction()
  69. {
  70. $type = (string)$this->_request->getParam('type', 's');
  71. $match = (string)$this->_request->getParam('match');
  72. $type = $type[0]; // use only first letter
  73. if ($this->_owApp->selectedModel && strlen($match) > 2) {
  74. $namespaces = $this->_owApp->selectedModel->getNamespaces();
  75. $namespacesFlipped = array_flip($namespaces);
  76. $nsFilter = array();
  77. foreach ($namespacesFlipped as $prefix => $uri) {
  78. if (stripos($prefix, $match) === 0) {
  79. $nsFilter[] = 'FILTER (regex(str(?' . $type . '), "' . $uri . '"))';
  80. }
  81. }
  82. $store = $this->_owApp->selectedModel->getStore();
  83. $query = Erfurt_Sparql_SimpleQuery::initWithString(
  84. 'SELECT DISTINCT ?' . $type . '
  85. FROM <' . $this->_owApp->selectedModel->getModelIri() . '>
  86. WHERE {
  87. ?s ?p ?o.
  88. ' . implode(PHP_EOL, $nsFilter) . '
  89. }'
  90. );
  91. }
  92. }
  93. public function hierarchyAction()
  94. {
  95. $options = array();
  96. if (isset($this->_request->entry)) {
  97. $options['entry'] = $this->_request->entry;
  98. }
  99. $model = new OntoWiki_Model_Hierarchy(Erfurt_App::getInstance()->getStore(),
  100. $this->_owApp->selectedModel,
  101. $options);
  102. $this->view->open = true;
  103. $this->view->classes = $model->getHierarchy();
  104. $this->_response->setBody($this->view->render('partials/hierarchy_list.phtml'));
  105. // $this->_response->setBody(json_encode($model->getHierarchy()));
  106. }
  107. /**
  108. * Constructor
  109. */
  110. public function init()
  111. {
  112. // init controller variables
  113. $this->_owApp = OntoWiki::getInstance();
  114. $this->_config = $this->_owApp->config;
  115. $this->_session = $this->_owApp->session;
  116. // prepare Ajax context
  117. $ajaxContext = $this->_helper->getHelper('AjaxContext');
  118. $ajaxContext->addActionContext('view', 'html')
  119. ->addActionContext('form', 'html')
  120. ->addActionContext('process', 'json')
  121. ->initContext();
  122. }
  123. /**
  124. * Menu Action to generate JSON serializations of OntoWiki_Menu for context-, module-, component-menus
  125. */
  126. public function menuAction()
  127. {
  128. $module = $this->_request->getParam('module');
  129. $resource = $this->_request->getParam('resource');
  130. $translate = $this->_owApp->translate;
  131. // create empty menu first
  132. $menuRegistry = OntoWiki_Menu_Registry::getInstance();
  133. $menu = $menuRegistry->getMenu(EF_RDFS_RESOURCE);
  134. if (!empty($module)) {
  135. $moduleRegistry = OntoWiki_Module_Registry::getInstance();
  136. $menu = $moduleRegistry->getModule($module)->getContextMenu();
  137. }
  138. if (!empty($resource)) {
  139. $models = array_keys($this->_owApp->erfurt->getStore()->getAvailableModels(true));
  140. $isModel = in_array($resource, $models);
  141. $menu->prependEntry(
  142. 'Go to Resource (external)',
  143. (string)$resource
  144. );
  145. if ($this->_owApp->erfurt->getAc()->isModelAllowed('edit', $this->_owApp->selectedModel) ) {
  146. // Delete resource option
  147. $url = new OntoWiki_Url(
  148. array('controller' => 'resource', 'action' => 'delete'),
  149. array()
  150. );
  151. if ($isModel) {
  152. $url->setParam('m',$resource,false);
  153. }
  154. $url->setParam('r',$resource,true);
  155. $menu->prependEntry( 'Delete Resource', (string) $url );
  156. // edit resource option
  157. $menu->prependEntry('Edit Resource', 'javascript:editResourceFromURI(\''.(string) $resource.'\')');
  158. }
  159. // add resource menu entries
  160. $url = new OntoWiki_Url(
  161. array( 'action' => 'view'),
  162. array()
  163. );
  164. if ($isModel) {
  165. $url->setParam('m',$resource,false);
  166. }
  167. $url->setParam('r',$resource,true);
  168. $menu->prependEntry(
  169. 'View Resource',
  170. (string)$url
  171. );
  172. if ($isModel) {
  173. // add a seperator
  174. $menu->prependEntry(OntoWiki_Menu::SEPARATOR);
  175. // can user delete models?
  176. if ( $this->_owApp->erfurt->getAc()->isModelAllowed('edit', $resource) &&
  177. $this->_owApp->erfurt->getAc()->isActionAllowed('ModelManagement')
  178. ) {
  179. $url = new OntoWiki_Url(
  180. array('controller' => 'model', 'action' => 'delete'),
  181. array()
  182. );
  183. $url->setParam('m',$resource,false);
  184. $menu->prependEntry(
  185. 'Delete Knowledge Base',
  186. (string)$url
  187. );
  188. }
  189. // add entries for supported export formats
  190. foreach (array_reverse(Erfurt_Syntax_RdfSerializer::getSupportedFormats()) as $key => $format) {
  191. $url = new OntoWiki_Url(
  192. array('controller' => 'model', 'action' => 'export'),
  193. array()
  194. );
  195. $url->setParam('m',$resource,false);
  196. $url->setParam('f',$key);
  197. $menu->prependEntry(
  198. 'Export Knowledge Base as ' . $format,
  199. (string)$url
  200. );
  201. }
  202. // check if model could be edited (prefixes and data)
  203. if ($this->_owApp->erfurt->getAc()->isModelAllowed('edit', $resource)) {
  204. $url = new OntoWiki_Url(
  205. array('controller' => 'model', 'action' => 'add'),
  206. array()
  207. );
  208. $url->setParam('m',$resource,false);
  209. $menu->prependEntry(
  210. 'Add Data to Knowledge Base',
  211. (string)$url
  212. );
  213. $url = new OntoWiki_Url(
  214. array('controller' => 'model', 'action' => 'config'),
  215. array()
  216. );
  217. $url->setParam('m',$resource,false);
  218. $menu->prependEntry(
  219. 'Configure Knowledge Base',
  220. (string)$url
  221. );
  222. }
  223. // Select Knowledge Base
  224. $url = new OntoWiki_Url(
  225. array('controller' => 'model', 'action' => 'select'),
  226. array()
  227. );
  228. $url->setParam('m',$resource,false);
  229. $menu->prependEntry(
  230. 'Select Knowledge Base',
  231. (string)$url
  232. );
  233. } else {
  234. $query = Erfurt_Sparql_SimpleQuery::initWithString(
  235. 'SELECT *
  236. FROM <' . (string)$this->_owApp->selectedModel . '>
  237. WHERE {
  238. <' . $resource . '> a ?type .
  239. }'
  240. );
  241. $results[] = $this->_owApp->erfurt->getStore()->sparqlQuery($query);
  242. $query = Erfurt_Sparql_SimpleQuery::initWithString(
  243. 'SELECT *
  244. FROM <' . (string)$this->_owApp->selectedModel . '>
  245. WHERE {
  246. ?inst a <' . $resource . '> .
  247. } LIMIT 2'
  248. );
  249. if ( sizeof($this->_owApp->erfurt->getStore()->sparqlQuery($query)) > 0 ) {
  250. $hasInstances = true;
  251. } else {
  252. $hasInstances = false;
  253. }
  254. //var_dump($results[0]);
  255. //var_dump($hasInstances);
  256. $typeArray = array();
  257. foreach ($results[0] as $row) {
  258. $typeArray[] = $row['type'];
  259. }
  260. //var_dump($typeArray); exit;
  261. if (in_array(EF_RDFS_CLASS, $typeArray) ||
  262. in_array(EF_OWL_CLASS, $typeArray) ||
  263. $hasInstances
  264. ) {
  265. // add a seperator
  266. $menu->prependEntry(OntoWiki_Menu::SEPARATOR);
  267. $url = new OntoWiki_Url(
  268. array('action' => 'list'),
  269. array()
  270. );
  271. $url->setParam('class',$resource,false);
  272. $url->setParam('init',"true",true);
  273. // UDFR - Abhi - Search for last '#' in resource string
  274. if (strrchr($resource, "#")){
  275. $search = strrchr($resource, "#");
  276. $trim = substr($search, 1, 8);
  277. }
  278. else {
  279. $search = strrchr($resource, "/");
  280. $trim = substr($search, 1, 8);
  281. }
  282. // add class menu entries
  283. if ($this->_owApp->erfurt->getAc()->isModelAllowed('edit', $this->_owApp->selectedModel) && $trim != 'Abstract') { // Don't allow create instance for Abstract classes
  284. $menu->prependEntry(
  285. 'Create Instance',
  286. "javascript:createInstanceFromClassURI('$resource');"
  287. );
  288. }
  289. $menu->prependEntry(
  290. 'List Instances',
  291. (string)$url
  292. );
  293. // ->prependEntry('Create Instance', $this->_config->urlBase . 'index/create/?r=')
  294. // ->prependEntry('Create Subclass', $this->_config->urlBase . 'index/create/?r=');
  295. }
  296. }
  297. }
  298. // Fire a event;
  299. $event = new Erfurt_Event('onCreateMenu');
  300. $event->menu = $menu;
  301. $event->resource = $resource;
  302. if (isset($isModel)) {
  303. $event->isModel = $isModel;
  304. }
  305. $event->model = $this->_owApp->selectedModel;
  306. $event->trigger();
  307. echo $menu->toJson();
  308. }
  309. public function preDispatch()
  310. {
  311. // disable auto-rendering
  312. $this->_helper->viewRenderer->setNoRender();
  313. // disable layout for Ajax requests
  314. $this->_helper->layout()->disableLayout();
  315. }
  316. public function sessionAction()
  317. {
  318. if (!isset($this->_request->name)) {
  319. throw new OntoWiki_Exception("Missing parameter 'name'.");
  320. exit;
  321. }
  322. if (isset($this->_request->namespace)) {
  323. $namespace = $this->_request->namespace;
  324. } else {
  325. $namespace = _OWSESSION;
  326. }
  327. $session = new Zend_Session_Namespace($namespace);
  328. $name = $this->_request->name;
  329. $method = 'set'; // default
  330. if (isset($this->_request->method)) {
  331. $method = $this->_request->method;
  332. }
  333. if (isset($this->_request->value)) {
  334. $value = $this->_request->value;
  335. } else if($method!='unsetArray' && $method!='unsetArrayKey' && !($method=='unset' && !is_array($session->$name))) {
  336. throw new OntoWiki_Exception('Missing parameter "value".');
  337. exit;
  338. }
  339. if (isset($this->_request->value) && isset($this->_request->valueIsSerialized) && $this->_request->valueIsSerialized == "true") {
  340. $value = json_decode(stripslashes($value), true);
  341. }
  342. if (isset($this->_request->key)) {
  343. $key = $this->_request->key;
  344. } else if ($method == 'setArrayValue' || $method == 'unsetArrayKey') {
  345. throw new OntoWiki_Exception('Missing parameter "key".');
  346. exit;
  347. }
  348. switch ($method) {
  349. case 'set':
  350. $session->$name = $value;
  351. break;
  352. case 'setArrayValue':
  353. if(!is_array($session->$name))$session->$name = array();
  354. $array = $session->$name;
  355. $array[$key] = $value;
  356. $session->$name = $array; //strange (because the __get and __set interceptors)
  357. break;
  358. case 'push':
  359. if (!is_array($session->$name)) {
  360. $session->$name = array();
  361. }
  362. array_push($session->$name, $value);
  363. break;
  364. case 'merge':
  365. if (!is_array($session->$name)) {
  366. $session->$name = array();
  367. }
  368. $session->$name = array_merge($session->$name, $value);
  369. break;
  370. case 'unset':
  371. // unset a value by inverting the array
  372. // and unsetting the specified key
  373. if (is_array($session->$name)) {
  374. $valuesAsKeys = array_flip($session->$name);
  375. unset($valuesAsKeys[$value]);
  376. $session->$name = array_flip($valuesAsKeys);
  377. } else {
  378. //unset a non-array
  379. unset($session->$name);
  380. }
  381. break;
  382. case 'unsetArrayKey':
  383. //done this way because of interceptor-methods...
  384. $new = array();
  385. if(is_array($session->$name)){
  386. foreach($session->$name as $comparekey => $comparevalue){
  387. if($comparekey != $key){
  388. $new[] = $comparevalue;
  389. }
  390. }
  391. }
  392. $session->$name = $new;
  393. break;
  394. case 'unsetArray':
  395. // unset the array
  396. // (the above unsets only values in arrays)
  397. unset($session->$name);
  398. break;
  399. }
  400. $msg = 'sessionStore: '
  401. . $name
  402. . ' = '
  403. . print_r($session->$name, true);
  404. $this->_owApp->logger->debug($msg);
  405. }
  406. /**
  407. * OntoWiki Sparql Endpoint
  408. *
  409. * Implements the SPARQL protocol according to {@link http://www.w3.org/TR/rdf-sparql-protocol/}.
  410. */
  411. public function sparqlAction()
  412. {
  413. // service controller needs no view renderer
  414. $this->_helper->viewRenderer->setNoRender();
  415. // disable layout for Ajax requests
  416. $this->_helper->layout()->disableLayout();
  417. $store = OntoWiki::getInstance()->erfurt->getStore();
  418. $response = $this->getResponse();
  419. // fetch params
  420. // TODO: support maxOccurs:unbound
  421. $queryString = $this->_request->getParam('query', '');
  422. if (get_magic_quotes_gpc()) {
  423. $queryString = stripslashes($queryString);
  424. }
  425. $defaultGraph = $this->_request->getParam('default-graph-uri', null);
  426. $namedGraph = $this->_request->getParam('named-graph-uri', null);
  427. if (!empty($queryString)) {
  428. $query = Erfurt_Sparql_SimpleQuery::initWithString($queryString);
  429. // overwrite query-specidfied dataset with protocoll-specified dataset
  430. if (null !== $defaultGraph) {
  431. $query->setFrom((array)$defaultGraph);
  432. }
  433. if (null !== $namedGraph) {
  434. $query->setFromNamed((array)$namedGraph);
  435. }
  436. // check graph availability
  437. $ac = Erfurt_App::getInstance()->getAc();
  438. foreach (array_merge($query->getFrom(), $query->getFromNamed()) as $graphUri) {
  439. if (!$ac->isModelAllowed('view', $graphUri)) {
  440. if (Erfurt_App::getInstance()->getAuth()->getIdentity()->isAnonymousUser()) {
  441. // In this case we allow the requesting party to authorize...
  442. $response->setRawHeader('HTTP/1.1 401 Unauthorized');
  443. $response->setHeader('WWW-Authenticate', 'Basic realm="OntoWiki"');
  444. $response->sendResponse();
  445. exit;
  446. } else {
  447. $response->setRawHeader('HTTP/1.1 500 Internal Server Error')
  448. ->setBody('QueryRequestRefused')
  449. ->sendResponse();
  450. exit;
  451. }
  452. }
  453. }
  454. $typeMapping = array(
  455. 'application/sparql-results+xml' => 'xml',
  456. 'application/json' => 'json',
  457. 'application/sparql-results+json' => 'json'
  458. );
  459. try {
  460. $type = OntoWiki_Utils::matchMimetypeFromRequest($this->_request, array_keys($typeMapping));
  461. } catch (Exeption $e) {
  462. //
  463. }
  464. if (empty($type) && isset($this->_request->callback)) {
  465. // JSONp
  466. $type = 'application/sparql-results+json';
  467. } else if (empty($type)) {
  468. // dafault: XML
  469. $type = 'application/sparql-results+xml';
  470. }
  471. try {
  472. // get result for mimetype
  473. $result = $store->sparqlQuery($query, array('result_format' => $typeMapping[$type]));
  474. } catch (Exception $e) {
  475. $response->setRawHeader('HTTP/1.1 400 Bad Request')
  476. ->setBody('MalformedQuery: ' . $e->getMessage())
  477. ->sendResponse();
  478. exit;
  479. }
  480. if (/* $typeMapping[$type] == 'json' && */isset($this->_request->callback)) {
  481. // return jsonp
  482. $response->setHeader('Content-Type', 'application/javascript');
  483. $padding = $this->_request->getParam('callback', '');
  484. $response->setBody($padding . '(' . $result . ')');
  485. } else {
  486. // set header
  487. $response->setHeader('Content-Type', $type);
  488. // return normally
  489. $response->setBody($result);
  490. }
  491. $response->sendResponse();
  492. exit;
  493. }
  494. }
  495. /**
  496. * OntoWiki Update Endpoint
  497. *
  498. * Only data inserts and deletes are implemented at the moment (e.g. no graph patterns).
  499. * @todo LOAD <> INTO <>, CLEAR GRAPH <>, CREATE[SILENT] GRAPH <>, DROP[ SILENT] GRAPH <>
  500. */
  501. public function updateAction()
  502. {
  503. // service controller needs no view renderer
  504. $this->_helper->viewRenderer->setNoRender();
  505. // disable layout for Ajax requests
  506. $this->_helper->layout()->disableLayout();
  507. $store = OntoWiki::getInstance()->erfurt->getStore();
  508. $response = $this->getResponse();
  509. $defaultGraph = $this->_request->getParam('default-graph-uri', null);
  510. $namedGraph = $this->_request->getParam('named-graph-uri', null);
  511. $insertGraph = null;
  512. $deleteGraph = null;
  513. $insertModel = null;
  514. $deleteModel = null;
  515. if (isset($this->_request->query)) {
  516. // we have a query, enter SPARQL/Update mode
  517. $query = $this->_request->getParam('query', '');
  518. OntoWiki::getInstance()->logger->info('SPARQL/Update query: ' . $query);
  519. $matches = array();
  520. // insert
  521. preg_match('/INSERT\s+DATA(\s+INTO\s*<(.+)>)?\s*{\s*([^}]*)/i', $query, $matches);
  522. $insertGraph = (isset($matches[2]) && ($matches[2] !== '')) ? $matches[2] : null;
  523. $insertTriples = isset($matches[3]) ? $matches[3] : '';
  524. if ((null === $insertGraph) && ($insertTriples !== '')) {
  525. if (null !== $defaultGraph) {
  526. $insertGraph = $defaultGraph;
  527. }
  528. if (null !== $namedGraph) {
  529. $insertGraph = $namedGraph;
  530. }
  531. }
  532. OntoWiki::getInstance()->logger->info('SPARQL/Update insertGraph: ' . $insertGraph);
  533. OntoWiki::getInstance()->logger->info('SPARQL/Update insertTriples: ' . $insertTriples);
  534. // delete
  535. preg_match('/DELETE\s+DATA(\s+FROM\s*<(.+)>)?\s*{\s*([^}]*)/i', $query, $matches);
  536. $deleteGraph = (isset($matches[2]) && ($matches[2] !== '')) ? $matches[2] : null;
  537. $deleteTriples = isset($matches[3]) ? $matches[3] : '';
  538. if ((null === $deleteGraph) && ($deleteTriples !== '')) {
  539. if (null !== $defaultGraph) {
  540. $deleteGraph = $defaultGraph;
  541. }
  542. if (null !== $namedGraph) {
  543. $deleteGraph = $namedGraph;
  544. }
  545. }
  546. // TODO: normalize literals
  547. $parser = Erfurt_Syntax_RdfParser::rdfParserWithFormat('nt');
  548. $insert = $parser->parse($insertTriples, Erfurt_Syntax_RdfParser::LOCATOR_DATASTRING);
  549. $parser->reset();
  550. $delete = $parser->parse($deleteTriples, Erfurt_Syntax_RdfParser::LOCATOR_DATASTRING);
  551. if (null !== $insertGraph) {
  552. try {
  553. $insertModel = $insertGraph ? $store->getModel($insertGraph) : $store->getModel($namedGraph);
  554. } catch (Erfurt_Store_Exception $e) {
  555. // TODO: error
  556. if (defined('_OWDEBUG')) {
  557. OntoWiki::getInstance()->logger->info('Could not instantiate models.');
  558. }
  559. exit;
  560. }
  561. }
  562. if (null !== $deleteGraph) {
  563. try {
  564. $deleteModel = $deleteGraph ? $store->getModel($deleteGraph) : $store->getModel($namedGraph);
  565. } catch (Erfurt_Store_Exception $e) {
  566. // TODO: error
  567. if (defined('_OWDEBUG')) {
  568. OntoWiki::getInstance()->logger->info('Could not instantiate models.');
  569. }
  570. exit;
  571. }
  572. }
  573. } else {
  574. // no query, inserts and delete triples by JSON via param
  575. $insert = json_decode($this->_request->getParam('insert', '{}'), true);
  576. $delete = json_decode($this->_request->getParam('delete', '{}'), true);
  577. if ($this->_request->has('delete_hashed')) {
  578. $hashedObjectStatements = $this->_findStatementsForObjectsWithHashes(
  579. $namedGraph,
  580. json_decode($this->_request->getParam('delete_hashed'), true));
  581. $delete = array_merge_recursive($delete, $hashedObjectStatements);
  582. }
  583. try {
  584. $namedModel = $store->getModel($namedGraph);
  585. $insertModel = $namedModel;
  586. $deleteModel = $namedModel;
  587. } catch (Erfurt_Store_Exception $e) {
  588. // TODO: error
  589. if (defined('_OWDEBUG')) {
  590. OntoWiki::getInstance()->logger->info('Could not instantiate models.');
  591. }
  592. exit;
  593. }
  594. }
  595. if (empty($insert) or empty($delete)) {
  596. // TODO: error
  597. }
  598. $flag = false;
  599. /**
  600. * @trigger onUpdateServiceAction is triggered when Service-Controller Update Action is executed.
  601. * Event contains following attributes:
  602. * deleteModel : model to delete statments from
  603. * deleteData : statements payload being deleted
  604. * insertModel : model to add statements to
  605. * insertDara : statements payload being added
  606. */
  607. $event = new Erfurt_Event('onUpdateServiceAction');
  608. $event->deleteModel = $deleteModel;
  609. $event->insertModel = $insertModel;
  610. $event->deleteData = $delete;
  611. $event->insertData = $insert;
  612. $event->trigger();
  613. // writeback
  614. $delete = $event->deleteData;
  615. $insert = $event->insertData;
  616. $changes = isset($event->changes) ? $event->changes : null;
  617. // delete
  618. if ($deleteModel && $deleteModel->isEditable()) {
  619. try {
  620. $count = $deleteModel->deleteMultipleStatements((array)$delete);
  621. } catch (Erfurt_Store_Exception $e) {
  622. if (defined('_OWDEBUG')) {
  623. OntoWiki::getInstance()->logger->info(
  624. 'Could not delete statements from graph: ' . $e->getMessage() . PHP_EOL .
  625. 'Statements: ' . print_r($delete, true)
  626. );
  627. }
  628. }
  629. $flag = true;
  630. if (defined('_OWDEBUG')) {
  631. OntoWiki::getInstance()->logger->info(
  632. sprintf('Deleted %i statements from graph <%s>', $count, $deleteModel->getModelUri())
  633. );
  634. }
  635. }
  636. // insert
  637. if ($insertModel && $insertModel->isEditable()) {
  638. $count = $insertModel->addMultipleStatements((array)$insert);
  639. $flag = true;
  640. if (defined('_OWDEBUG')) {
  641. OntoWiki::getInstance()->logger->info(
  642. sprintf('Inserted %i statements into graph <%s>', $count, $insertModel->getModelUri())
  643. );
  644. }
  645. }
  646. // nothing done?
  647. if (!$flag) {
  648. // When no user is given (Anoymous) give the requesting party a chance to authenticate.
  649. if (Erfurt_App::getInstance()->getAuth()->getIdentity()->isAnonymousUser()) {
  650. // In this case we allow the requesting party to authorize
  651. $response->setRawHeader('HTTP/1.1 401 Unauthorized');
  652. $response->setHeader('WWW-Authenticate', 'Basic realm="OntoWiki"');
  653. $response->sendResponse();
  654. exit;
  655. }
  656. }
  657. if ($changes) {
  658. /**
  659. * @see {http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2}
  660. */
  661. $response->setHttpResponseCode(201);
  662. $response->setHeader('Location', $changes['changed']);
  663. $response->setHeader('Content-Type', 'application/json');
  664. $response->setBody(json_encode($changes));
  665. }
  666. }
  667. /**
  668. * Renders a template and responds with the output.
  669. *
  670. * All GET and POST parameters are populated into the view object
  671. * and therefore available in the view script. You have to know
  672. * which parameters the script uses and objects obviously cannot
  673. * be passed via GET/POST.
  674. */
  675. public function templateAction()
  676. {
  677. // fetch folder parameter
  678. if (isset($this->_request->f)) {
  679. $folder = $this->_request->getParam('f');
  680. } else {
  681. throw new OntoWiki_Exception('Missing parameter f!');
  682. exit;
  683. }
  684. // fetch template parameter
  685. if (isset($this->_request->t)) {
  686. $template = $this->_request->getParam('t');
  687. } else {
  688. throw new OntoWiki_Exception('Missing parameter t!');
  689. exit;
  690. }
  691. if (!preg_match('/^[a-z_]+$/', $folder) || !preg_match('/^[a-z_]+$/', $template)) {
  692. throw new OntoWiki_Exception('Illegal characters in folder or template name!');
  693. exit;
  694. }
  695. $path = _OWROOT . $this->_config->themes->path . $this->_config->themes->default . 'templates/' . $folder . DIRECTORY_SEPARATOR;
  696. $file = $template . '.' . $this->_helper->viewRenderer->getViewSuffix();
  697. if (!is_readable($path . $file)) {
  698. // $this->log('Template file not readable: ' . $path . $file, Zend_Log::ERR);
  699. throw new OntoWiki_Exception('Template file not readable. ' . $path . $file);
  700. exit;
  701. }
  702. // set script path
  703. $this->view->setScriptPath($path);
  704. // assign get and post parameters to view
  705. $this->view->assign($this->_request->getParams());
  706. // set header
  707. $this->_response->setRawHeader('Content-type: text/html');
  708. // render script
  709. $this->_response->setBody($this->view->render($file));
  710. }
  711. /**
  712. * JSON outputs of the transitive closure of resources to a given start
  713. * resource and an transitive attribute
  714. */
  715. public function transitiveclosureAction()
  716. {
  717. // service controller needs no view renderer
  718. $this->_helper->viewRenderer->setNoRender();
  719. // disable layout for Ajax requests
  720. $this->_helper->layout()->disableLayout();
  721. $store = OntoWiki::getInstance()->erfurt->getStore();
  722. $response = $this->getResponse();
  723. // fetch start resource parameter
  724. if (isset($this->_request->sr)) {
  725. $resource = $this->_request->getParam('sr', null, true);
  726. } else {
  727. throw new OntoWiki_Exception('Missing parameter sr (start resource)!');
  728. exit;
  729. }
  730. // fetch property resource parameter
  731. if (isset($this->_request->p)) {
  732. $property = $this->_request->getParam('p', null, true);
  733. } else {
  734. throw new OntoWiki_Exception('Missing parameter p (property)!');
  735. exit;
  736. }
  737. // m is automatically used and selected
  738. if ((!isset($this->_request->m)) && (!$this->_owApp->selectedModel)) {
  739. throw new OntoWiki_Exception('No model pre-selected model and missing parameter m (model)!');
  740. exit;
  741. } else {
  742. $model = $this->_owApp->selectedModel;
  743. }
  744. // fetch inverse parameter
  745. $inverse = $this->_request->getParam('inverse', 'true');
  746. switch ($inverse) {
  747. case 'false': /* fallthrough */
  748. case 'no': /* fallthrough */
  749. case 'off': /* fallthrough */
  750. case '0':
  751. $inverse = false;
  752. break;
  753. default:
  754. $inverse = true;
  755. }
  756. $store = $model->getStore();
  757. // get the transitive closure
  758. $closure = $store->getTransitiveClosure((string)$model, $property, array($resource), $inverse);
  759. // send the response
  760. $response->setHeader('Content-Type', 'application/json');
  761. $response->setBody(json_encode($closure));
  762. $response->sendResponse();
  763. exit;
  764. }
  765. /**
  766. * JSON output of the RDFauthor selection Cache File of the current model or
  767. * of the model given in parameter m
  768. */
  769. public function rdfauthorcacheAction()
  770. {
  771. // service controller needs no view renderer
  772. $this->_helper->viewRenderer->setNoRender();
  773. // disable layout for Ajax requests
  774. $this->_helper->layout()->disableLayout();
  775. $store = OntoWiki::getInstance()->erfurt->getStore();
  776. $response = $this->getResponse();
  777. $model = $this->_owApp->selectedModel;
  778. if (isset($this->_request->m)) {
  779. $model = $store->getModel($this->_request->m);
  780. }
  781. if (empty($model)) {
  782. throw new OntoWiki_Exception('Missing parameter m (model) and no selected model in session!');
  783. exit;
  784. }
  785. $output = array();
  786. $properties = $model->sparqlQuery('SELECT DISTINCT ?uri {
  787. ?uri a ?propertyClass.
  788. FILTER(
  789. sameTerm(?propertyClass, <'.EF_OWL_OBJECT_PROPERTY.'>) ||
  790. sameTerm(?propertyClass, <'.EF_OWL_DATATYPE_PROPERTY.'>) ||
  791. sameTerm(?propertyClass, <'.EF_OWL_ONTOLOGY_PROPERTY.'>) ||
  792. sameTerm(?propertyClass, <'.EF_RDF_PROPERTY.'>)
  793. )} LIMIT 200 ');
  794. if (!empty($properties)) {
  795. // push all URIs to titleHelper
  796. $titleHelper = new OntoWiki_Model_TitleHelper($model);
  797. foreach($properties as $property) {
  798. $titleHelper->addResource($property['uri']);
  799. }
  800. $lastProperty = end($properties);
  801. foreach($properties as $property) {
  802. $newProperty = array();
  803. // return title from titleHelper
  804. $newProperty['label'] = $titleHelper->getTitle($property['uri']);
  805. $pdata = $model->sparqlQuery('SELECT DISTINCT ?key ?value
  806. WHERE {
  807. <'.$property['uri'].'> ?key ?value
  808. FILTER(
  809. sameTerm(?key, <'.EF_RDF_TYPE.'>) ||
  810. sameTerm(?key, <'.EF_RDFS_DOMAIN.'>) ||
  811. sameTerm(?key, <'.EF_RDFS_RANGE.'>)
  812. )
  813. FILTER(isUri(?value))
  814. }
  815. LIMIT 20');
  816. if (!empty($pdata)) {
  817. $types = array();
  818. $ranges = array();
  819. $domains = array();
  820. // prepare the data in arrays
  821. foreach($pdata as $data) {
  822. if ( ($data['key'] == EF_RDF_TYPE) && ($data['value'] != EF_RDF_PROPERTY) ) {
  823. $types[] = $data['value'];
  824. } elseif ($data['key'] == EF_RDFS_RANGE) {
  825. $ranges[] = $data['value'];
  826. } elseif ($data['key'] == EF_RDFS_DOMAIN) {
  827. $domains[] = $data['value'];
  828. }
  829. }
  830. if (!empty($types)) {
  831. $newProperty['type'] = array_unique($types);
  832. }
  833. if (!empty($ranges)) {
  834. $newProperty['range'] = array_unique($ranges);
  835. }
  836. if (!empty($domains)) {
  837. $newProperty['domain'] = array_unique($domains);
  838. }
  839. }
  840. $output[ $property['uri'] ] = $newProperty;
  841. }
  842. }
  843. // send the response
  844. $response->setHeader('Content-Type', 'application/json');
  845. $response->setBody(json_encode($output));
  846. $response->sendResponse();
  847. exit;
  848. }
  849. /**
  850. * JSON output of the RDFauthor init config, which is a RDF/JSON Model
  851. * without objects where the user should be able to add data
  852. *
  853. * get/post parameters:
  854. * mode - class, resource or clone
  855. * class: prop list based on one class' resources
  856. * resource: prop list based on one resource
  857. * clone: prop list and values based on one resource (with new uri)
  858. * edit: prop list and values based on one resource
  859. * uri - parameter for mode (class uri, resource uri)
  860. */
  861. public function rdfauthorinitAction()
  862. {
  863. // service controller needs no view renderer
  864. $this->_helper->viewRenderer->setNoRender();
  865. // disable layout for Ajax requests
  866. $this->_helper->layout()->disableLayout();
  867. $store = OntoWiki::getInstance()->erfurt->getStore();
  868. $response = $this->getResponse();
  869. $model = $this->_owApp->selectedModel;
  870. $modelIri = $model->getModelIri();
  871. if (isset($this->_request->m)) {
  872. $model = $store->getModel($this->_request->m);
  873. }
  874. if (empty($model)) {
  875. throw new OntoWiki_Exception('Missing parameter m (model) and no selected model in session!');
  876. exit;
  877. }
  878. if ( (isset($this->_request->uri)) && (Zend_Uri::check($this->_request->uri)) ) {
  879. $parameter = $this->_request->uri;
  880. } else {
  881. throw new OntoWiki_Exception('Missing or invalid parameter uri (clone uri) !');
  882. exit;
  883. }
  884. if (isset($this->_request->mode)) {
  885. $workingMode = $this->_request->mode;
  886. } else {
  887. $workingMode = 'resource';
  888. }
  889. if ($workingMode != 'edit') {
  890. $resourceUri = $model->getBaseUri(). 'newResource/' .md5(date('F j, Y, g:i:s:u a'));
  891. } else {
  892. $resourceUri = $parameter;
  893. }
  894. if ($workingMode == 'class') {
  895. //UDFR - Abhi
  896. if ($modelIri != "http://localhost/OntoWiki/Config/") {
  897. $properties = $model->sparqlQuery('
  898. SELECT distinct ?uri ?propType ?super
  899. WHERE {
  900. <'.$parameter.'> <'.EF_RDFS_SUBCLASSOF.'>?super.
  901. {?uri <'.EF_RDFS_DOMAIN.'>?super.}
  902. UNION {?uri <'.EF_RDFS_DOMAIN.'> <'.$parameter.'> }
  903. ?uri <'.EF_RDFS_RANGE.'> ?rangeclass.
  904. ?uri <'.EF_RDF_TYPE.'> ?propType.
  905. }
  906. Limit 200' , array('result_format' => 'extended'));
  907. //OPTIONAL { ?value <'.EF_RDF_TYPE.'> ?rangeclass.}
  908. }
  909. else {
  910. $properties = $model->sparqlQuery('SELECT DISTINCT ?uri ?value {
  911. ?s ?uri ?value.
  912. ?s a <'.$parameter.'>.
  913. } LIMIT 20 ', array('result_format' => 'extended'));
  914. }
  915. } elseif ($workingMode == 'clone') {
  916. # BUG: more than one values of a property are not supported right now
  917. # BUG: Literals are not supported right now
  918. $properties = $model->sparqlQuery('SELECT ?uri ?value {
  919. <'.$parameter.'> ?uri ?value.
  920. #FILTER (isUri(?value))
  921. } LIMIT 200 ', array('result_format' => 'extended'));
  922. } elseif ($workingMode == 'edit') {
  923. $properties = $model->sparqlQuery('SELECT ?uri ?value {
  924. <'.$parameter.'> ?uri ?value.
  925. } LIMIT 200 ', array('result_format' => 'extended'));
  926. } else { // resource
  927. $properties = $model->sparqlQuery('SELECT DISTINCT ?uri ?value {
  928. <'.$parameter.'> ?uri ?value.
  929. } LIMIT 200 ', array('result_format' => 'extended'));
  930. }
  931. // empty object to hold data
  932. $output = new stdClass();
  933. $newProperties = new stdClass();
  934. $properties = $properties['results']['bindings'];
  935. /*echo "abhishek-----<pre>";
  936. var_dump($properties); echo '<br>';
  937. echo "</pre>";
  938. exit;*/
  939. // feed title helper w/ URIs
  940. $titleHelper = new OntoWiki_Model_TitleHelper($model);
  941. $titleHelper->addResources($properties, 'uri');
  942. if (!empty($properties)) {
  943. // Abhi - UDFR -- Adding properties by default (rdf:ype and rdfs:label)
  944. if ($modelIri != "http://localhost/OntoWiki/Config/" && $workingMode == 'class') {
  945. $value = new stdClass();
  946. $value->value = $parameter;
  947. $value->type = 'uri';
  948. $value->hidden = true;
  949. $uri = EF_RDF_TYPE;
  950. $newProperties->$uri = array($value);
  951. $value = new stdClass();
  952. $value->type = 'literal';
  953. $value->title = 'label';
  954. $uri = EF_RDFS_LABEL;
  955. $newProperties->$uri = array($value);
  956. }
  957. // Abhi end
  958. foreach ($properties as $property) {
  959. $value = new stdClass();
  960. $currentUri = $property['uri']['value'];
  961. if(array_key_exists('value', $property)) {
  962. $currentValue = $property['value']['value'];
  963. $currentType = $property['value']['type'];
  964. //echo "I am in key==value "; var_dump($currentValue); echo"\n<br/>";
  965. if ($currentType == 'literal' || $currentType == 'typed-literal') {
  966. if (isset($property['value']['datatype'])) {
  967. $value->datatype = $property['value']['datatype'];
  968. } else if (isset($property['value']['xml:lang'])) {
  969. $value->lang = $property['value']['xml:lang'];
  970. }
  971. /* not in RDFauthor 0.8
  972. else {
  973. // plain literal --> rdfQuery needs extra quotes
  974. $currentValue = '"' . $currentValue . '"';
  975. }
  976. */
  977. }
  978. }
  979. // return title from titleHelper
  980. $value->title = $titleHelper->getTitle($currentUri);
  981. if ($currentUri == EF_RDF_TYPE) {
  982. //echo "I am in currentUri == EF_RDF_TYPE <br/>\n";
  983. switch ($workingMode) {
  984. case 'resource':
  985. /* fallthrough */
  986. case 'clone':
  987. $value->value = $currentValue;
  988. $value->type = $currentType;
  989. break;
  990. case 'edit':
  991. $value->value = $currentValue;
  992. $value->type = $currentType;
  993. break;
  994. case 'class':
  995. $value->value = $parameter;
  996. break;
  997. }
  998. //$value->type = $currentType;
  999. #$value->hidden = true;
  1000. } else { // $currentUri != EF_RDF_TYPE
  1001. if ( ($workingMode == 'clone') || ($workingMode == 'edit') ) {
  1002. //if(array_key_exists('value', $property )&& $modelIri == "http://www.udfr.org/udfr#") {
  1003. $value->value = $currentValue;
  1004. $value->type = $currentType;
  1005. }
  1006. }
  1007. // deal with multiple values of a property
  1008. if (isset($newProperties->$currentUri)) {
  1009. $tempProperty = $newProperties->$currentUri;
  1010. $tempProperty[] = $value;
  1011. $newProperties->$currentUri = $tempProperty;
  1012. } else {
  1013. $newProperties->$currentUri = array($value);
  1014. }
  1015. } // foreach
  1016. $output->$resourceUri = $newProperties;
  1017. } else {
  1018. // empty sparql results -> start with a plain resource
  1019. if ($workingMode == 'class') {
  1020. // for classes, add the rdf:type property
  1021. $value = new stdClass();
  1022. $value->value = $parameter;
  1023. $value->type = 'uri';
  1024. $value->hidden = true;
  1025. $uri = EF_RDF_TYPE;
  1026. $newProperties->$uri = array($value);
  1027. }
  1028. $value = new stdClass();
  1029. $value->type = 'literal';
  1030. $value->title = 'label';
  1031. $uri = EF_RDFS_LABEL;
  1032. $newProperties->$uri = array($value);
  1033. $output->$resourceUri = $newProperties;
  1034. }
  1035. // send the response
  1036. $response->setHeader('Content-Type', 'application/json');
  1037. $response->setBody(json_encode($output));
  1038. $response->sendResponse();
  1039. exit;
  1040. }
  1041. protected function _findStatementsForObjectsWithHashes($graphUri, $indexWithHashedObjects, $hashFunc = 'md5')
  1042. {
  1043. $queryOptions = array(
  1044. 'result_format' => 'extended'
  1045. );
  1046. $result = array();
  1047. foreach ($indexWithHashedObjects as $subject => $predicates) {
  1048. foreach ($predicates as $predicate => $hashedObjects) {
  1049. $query = "SELECT ?o FROM <$graphUri> WHERE {<$subject> <$predicate> ?o .}";
  1050. $queryObj = Erfurt_Sparql_SimpleQuery::initWithString($query);
  1051. if ($queryResult = $this->_owApp->erfurt->getStore()->sparqlQuery($queryObj, $queryOptions)) {
  1052. $bindings = $queryResult['results']['bindings'];
  1053. for ($i = 0, $max = count($bindings); $i < $max; $i++) {
  1054. $currentObject = $bindings[$i]['o'];
  1055. $objectString = Erfurt_Utils::buildLiteralString(
  1056. $currentObject['value'],
  1057. isset($currentObject['datatype']) ? $currentObject['datatype'] : null,
  1058. isset($currentObject['xml:lang']) ? $currentObject['xml:lang'] : null);
  1059. $hash = $hashFunc($objectString);
  1060. if (in_array($hash, $hashedObjects)) {
  1061. // add current statement to result
  1062. if (!isset($result[$subject])) {
  1063. $result[$subject] = array();
  1064. }
  1065. if (!isset($result[$subject][$predicate])) {
  1066. $result[$subject][$predicate] = array();
  1067. }
  1068. $objectSpec = array(
  1069. 'value' => $currentObject['value'],
  1070. 'type' => str_replace('typed-', '', $currentObject['type'])
  1071. );
  1072. if (isset($currentObject['datatype'])) {
  1073. $objectSpec['datatype'] = $currentObject['datatype'];
  1074. } else if (isset($currentObject['xml:lang'])) {
  1075. $objectSpec['lang'] = $currentObject['xml:lang'];
  1076. }
  1077. array_push($result[$subject][$predicate], $objectSpec);
  1078. }
  1079. }
  1080. }
  1081. }
  1082. }
  1083. return $result;
  1084. }
  1085. }