private function makeRequest(array $accept_header, $semantic = false) { $data = \Mockery::mock('Tdt\\Core\\Datasets\\Data'); if ($semantic) { $data->data = new Graph(); } else { $data->data = array(); } $data->is_semantic = $semantic; $this->updateRequest('GET', $accept_header); return ContentNegotiator::getResponse($data, null); }
public function get($uri) { // Ask permission Auth::requirePermissions('info.view'); // Default format is ttl for dcat if (empty($extension)) { $extension = 'ttl'; } $dcat = $this->createDcat(); // Allow content nego. for dcat return ContentNegotiator::getResponse($dcat, $extension); }
/** * Get all of the configured semantic sources * * @return \Response */ public function get($id = null) { Auth::requirePermissions('definitions.view'); // If the id isn't empty if (!empty($id)) { $data = $this->semantic_source->getSourceConfiguration($id); } else { $data = $this->semantic_source->getAllConfigurations(); } $result = new Data(); $result->data = $data; return ContentNegotiator::getResponse($result, 'json'); }
/** * Check if the link template header is filled in correctly */ public function testLinkTemplate() { $data = \Mockery::mock('Tdt\\Core\\Datasets\\Data'); \Mockery::mock('Eloquent'); $data->data = array(); $data->optional_parameters = array('param1', 'param2'); $response = ContentNegotiator::getResponse($data, 'json'); $this->assertNotNull($response); $header_bag = $response->headers; $this->assertNotEmpty($header_bag->get('Link-Template')); $this->assertEquals('http://localhost.json{?param1, param2}', $header_bag->get('Link-Template')); $data->optional_parameters = array(); $response = ContentNegotiator::getResponse($data, 'json'); $header_bag = $response->headers; $this->assertNotNull($response); $this->assertEmpty($header_bag->get('Link-Template')); }
private function getKeywords($uri = null) { $definitions = $this->definitions->getAll(); $keywords = []; foreach ($definitions as $definition) { $keyword_str = $definition['keywords']; $keywords_set = explode(',', $keyword_str); foreach ($keywords_set as $keyword) { $keyword = trim($keyword); if (!in_array($keyword, $keywords) && !empty($keyword)) { $keywords[] = $keyword; } } } $result = new Data(); $result->data = $keywords; return ContentNegotiator::getResponse($result, 'json'); }
private function getInfo($uri = null) { if (!empty($uri)) { if (!$this->definition->exists($uri)) { \App::abort(404, "No resource was found identified with " . $uri); } $description = $this->definition->getDescriptionInfo($uri); $result = new Data(); $result->data = $description; return ContentNegotiator::getResponse($result, 'json'); } list($limit, $offset) = Pager::calculateLimitAndOffset(); $definitions_info = $this->definition->getAllDefinitionInfo($limit, $offset); $definition_count = $this->definition->countPublished(); $result = new Data(); $result->paging = Pager::calculatePagingHeaders($limit, $offset, $definition_count); $result->data = $definitions_info; return ContentNegotiator::getResponse($result, 'json'); }
/** * Retrieve a Data object identified by $uri * * @param string $uri The identifier that identifies a resource * * @return \Response */ public function get($uri) { // Check permissions Auth::requirePermissions('dataset.view'); // Split for an (optional) extension list($uri, $extension) = $this->processURI($uri); // Check for caching // Based on: URI / Rest parameters / Query parameters / Paging headers $cache_string = $uri; list($limit, $offset) = Pager::calculateLimitAndOffset(); $cache_string .= '/limit=' . $limit . 'offset=' . $offset; $cache_string .= http_build_query(\Input::except('limit', 'offset', 'page', 'page_size')); $cache_string = sha1($cache_string); if (Cache::has($cache_string)) { return ContentNegotiator::getResponse(Cache::get($cache_string), $extension); } else { // Get definition $definition = $this->definition->getByIdentifier($uri); if ($definition) { // Get source definition $source_definition = $this->definition->getDefinitionSource($definition['source_id'], $definition['source_type']); if ($source_definition) { $source_type = $source_definition['type']; // Create the right datacontroller $controller_class = 'Tdt\\Core\\DataControllers\\' . $source_type . 'Controller'; $data_controller = \App::make($controller_class); // Get REST parameters $rest_parameters = str_replace($definition['collection_uri'] . '/' . $definition['resource_name'], '', $uri); $rest_parameters = ltrim($rest_parameters, '/'); $rest_parameters = explode('/', $rest_parameters); if (empty($rest_parameters[0]) && !is_numeric($rest_parameters[0])) { $rest_parameters = array(); } // Retrieve dataobject from datacontroller $data = $data_controller->readData($source_definition, $rest_parameters); $data->rest_parameters = $rest_parameters; // REST filtering if ($source_type != 'INSTALLED' && count($data->rest_parameters) > 0) { $data->data = self::applyRestFilter($data->data, $data->rest_parameters); } // Add definition to the object $data->definition = $definition; // Add source definition to the object $data->source_definition = $source_definition; // Add the available, supported formats to the object $format_helper = new FormatHelper(); $data->formats = $format_helper->getAvailableFormats($data); // Store in cache Cache::put($cache_string, $data, $source_definition['cache']); // Return the formatted response with content negotiation return ContentNegotiator::getResponse($data, $extension); } else { \App::abort(404, "Source for the definition could not be found."); } } else { // Coulnd't find a definition, but it might be a collection $resources = $this->definition->getByCollection($uri); if (count($resources) > 0) { $data = new Data(); $data->data = new \stdClass(); $data->data->datasets = array(); $data->data->collections = array(); foreach ($resources as $res) { // Check if it's a subcollection or a dataset $collection_uri = rtrim($res['collection_uri'], '/'); if ($collection_uri == $uri) { array_push($data->data->datasets, \URL::to($collection_uri . '/' . $res['resource_name'])); } else { // Push the subcollection if it's not already in the array if (!in_array(\URL::to($collection_uri), $data->data->collections)) { array_push($data->data->collections, \URL::to($collection_uri)); } } } // Fake a definition $data->definition = new \Definition(); $uri_array = explode('/', $uri); $last_chunk = array_pop($uri_array); $data->definition->collection_uri = join('/', $uri_array); $data->definition->resource_name = $last_chunk; // Return the formatted response with content negotiation return ContentNegotiator::getResponse($data, $extension); } else { \App::abort(404, "The dataset or collection you were looking for could not be found (URI: {$uri})."); } } } }
/** * Retrieve a Data object identified by $uri * * @param string $uri The identifier that identifies a resource * * @return \Response */ public function get($uri) { // Check permissions Auth::requirePermissions('dataset.view'); // Split for an (optional) extension list($uri, $extension) = $this->processURI($uri); // Check for caching // Based on: URI / Rest parameters / Query parameters / Paging headers $cache_string = $uri; list($limit, $offset) = Pager::calculateLimitAndOffset(); $cache_string .= '/limit=' . $limit . 'offset=' . $offset; $omit = ['limit', 'offset', 'page', 'page_size']; $query_string_params = \Input::get(); foreach ($query_string_params as $key => $val) { if (in_array($key, $omit)) { unset($query_string_params[$key]); } } $cache_string .= http_build_query($query_string_params); $cache_string = sha1($cache_string); if (Cache::has($cache_string)) { return ContentNegotiator::getResponse(Cache::get($cache_string), $extension); } else { // Get definition $definition = $this->definition->getByIdentifier($uri); if ($definition) { // Get source definition $source_definition = $this->definition->getDefinitionSource($definition['source_id'], $definition['source_type']); if ($source_definition) { $source_type = $source_definition['type']; // Create the right datacontroller $controller_class = 'Tdt\\Core\\DataControllers\\' . $source_type . 'Controller'; $data_controller = \App::make($controller_class); // Get REST parameters $uri_segments = explode('/', $uri); $rest_parameters = array_diff($uri_segments, array($definition['collection_uri'], $definition['resource_name'])); $rest_parameters = array_values($rest_parameters); $throttle_response = $this->applyThrottle($definition); if (!empty($throttle_response)) { return $throttle_response; } // Retrieve dataobject from datacontroller $data = $data_controller->readData($source_definition, $rest_parameters); // If the source type is XML, just return the XML contents, don't transform if (strtolower($source_type) == 'xml' && $extension == 'xml') { return $this->createXMLResponse($data->data); } $data->rest_parameters = $rest_parameters; // REST filtering if ($source_type != 'INSTALLED' && count($data->rest_parameters) > 0) { $data->data = self::applyRestFilter($data->data, $data->rest_parameters); } // Semantic paging with the hydra voc if ($data->is_semantic && !empty($data->paging)) { \EasyRdf_Namespace::set('hydra', 'http://www.w3.org/ns/hydra/core#'); $graph = $data->data; $url = \URL::to($definition['collection_uri'] . '/' . $definition['resource_name']); $request_url = \Request::url(); $graph->addResource($request_url, 'void:subset', $url); foreach ($data->paging as $key => $val) { $paged_url = $request_url . '?offset=' . $val[0] . '&limit=' . $val[1] . Pager::buildQuerystring(); switch ($key) { case 'next': $graph->addResource($request_url, 'hydra:nextPage', $paged_url); break; case 'previous': $graph->addResource($request_url, 'hydra:previousPage', $paged_url); break; case 'last': $graph->addResource($request_url, 'hydra:lastPage', $paged_url); break; case 'first': $graph->addResource($request_url, 'hydra:firstPage', $paged_url); break; } } $graph->addResource($url, 'a', 'dcat:Dataset'); $title = null; if (!empty($definition['title'])) { $title = $definition['title']; } else { $title = $definition['collection_uri'] . '/' . $definition['resource_name']; } $graph->addLiteral($url, 'dc:title', $title); $graph->addLiteral($url, 'dc:description', $source_definition['description']); $graph->addResource($url, 'dcat:distribution', $url . '.json'); $data->data = $graph; } // Add definition to the object $data->definition = $definition; // Add source definition to the object $data->source_definition = $source_definition; // Add the available, supported formats to the object $format_helper = new FormatHelper(); $data->formats = $format_helper->getAvailableFormats($data); // Store in cache Cache::put($cache_string, $data, $source_definition['cache']); // Return the formatted response with content negotiation return ContentNegotiator::getResponse($data, $extension); } else { \App::abort(404, "Source for the definition could not be found."); } } else { // Coulnd't find a definition, but it might be a collection $resources = $this->definition->getByCollection($uri); if (count($resources) > 0) { $data = new Data(); $data->data = new \stdClass(); $data->data->datasets = array(); $data->data->collections = array(); foreach ($resources as $res) { // Check if it's a subcollection or a dataset $collection_uri = rtrim($res['collection_uri'], '/'); if ($collection_uri == $uri) { array_push($data->data->datasets, \URL::to($collection_uri . '/' . $res['resource_name'])); } else { // Push the subcollection if it's not already in the array if (!in_array(\URL::to($collection_uri), $data->data->collections)) { array_push($data->data->collections, \URL::to($collection_uri)); } } } // Fake a definition $data->definition = new \Definition(); $uri_array = explode('/', $uri); $last_chunk = array_pop($uri_array); $data->definition->collection_uri = join('/', $uri_array); $data->definition->resource_name = $last_chunk; // Return the formatted response with content negotiation return ContentNegotiator::getResponse($data, $extension); } else { \App::abort(404, "The dataset or collection you were looking for could not be found (URI: {$uri})."); } } } }
/** * Resolve a graph pattern query (/all route) * * @param string $format The format of the request * * @return \Response */ public function solveQuery($format = null) { $data; if (!empty($format)) { $format = ltrim($format, '.'); } // Ignore the rest of the uri after /all and work with the request parameters as they were given $cache_string = sha1($this->getRawRequestURI(\Request::root())); // Check if the response to the query has been cached already if (Cache::has($cache_string)) { $data = Cache::get($cache_string); } else { // Get the graph pattern query string parameters from the request list($s, $p, $o) = $this->getTemplateParameters(); // Pass them to our sparql query builder SparqlQueryBuilder::setParameters(array($s, $p, $o)); $base_uri = null; // If no parameter has been filled in, the URI we have to match triples with is the root of our application if ($s == '?s' && $p == '?p' && $o == '?o') { $base_uri = \Request::root(); } // Fetch matching triples $result = $this->triples->getTriples($base_uri, \Request::get('limit', 100), \Request::get('offset', 0)); // If the graph contains no triples, then the graph pattern couldn't resolve to anything, 404 it is if ($result->countTriples() == 0) { \App::abort(404, "The resource couldn't be found, nor dereferenced."); } $definition = array('resource_name' => "all", 'collection_uri' => ""); $source_definition = array('description' => 'Semantic data collected out the configured semantic data sources.', 'type' => 'Semantic'); $data = new Data(); $data->definition = $definition; $data->source_definition = $source_definition; $data->data = $result; $data->is_semantic = true; // Add the available, supported formats to the object $format_helper = new FormatHelper(); $data->formats = $format_helper->getAvailableFormats($data); // Store in cache for a default of 5 minutes Cache::put($cache_string, $data, 5); } // Add the hydra namespace, it's not present in the easy rdf namespaces by default \EasyRdf_Namespace::set('hydra', 'http://www.w3.org/ns/hydra/core#'); // Return the formatted response with content negotiation $response = ContentNegotiator::getResponse($data, $format); // Pass a Vary header so that browsers know they have to take the accept header // into consideration when they apply caching client side $response->header('Vary', 'Accept'); // Allow CORS $response->header('Access-Control-Allow-Origin', '*'); return $response; }
public function get($uri) { // Set permission Auth::requirePermissions('definition.view'); if (!empty($uri)) { if (!$this->definition->exists($uri)) { \App::abort(404, "No resource was found identified with " . $uri); } $description = $this->definition->getFullDescription($uri); $result = new Data(); $result->data = $description; return ContentNegotiator::getResponse($result, 'json'); } list($limit, $offset) = Pager::calculateLimitAndOffset(); $definitions = $this->definition->getAllFullDescriptions($limit, $offset); $definition_count = $this->definition->count(); $result = new Data(); $result->paging = Pager::calculatePagingHeaders($limit, $offset, $definition_count); $result->data = $definitions; return ContentNegotiator::getResponse($result, 'json'); }
private function getInfo($uri = null) { $dataset = \Request::get('dataset', null); if (!empty($dataset)) { if (!$this->definition->exists($dataset)) { \App::abort(404, "No resource was found identified with " . $uri); } $description = $this->definition->getDescriptionInfo($dataset); $result = new Data(); $result->data = $description; return ContentNegotiator::getResponse($result, 'json'); } $filters = ['keywords', 'rights', 'theme', 'language', 'publisher_name', 'query']; $filter_map = []; foreach ($filters as $filter) { $filter_values = $this->parseFilterValues(\Input::get($filter)); if (!empty($filter_values)) { $filter_map[$filter] = $filter_values; } } list($limit, $offset) = Pager::calculateLimitAndOffset(50); $definitions = $this->definition->getFiltered($filter_map, $limit, $offset); $definition_count = $this->definition->countFiltered($filter_map, $limit, $offset); $facet_count = $this->definition->countFacets($filter_map); $facet_map = []; $definitions_info = []; foreach ($definitions as $definition) { $definitions_info[] = $this->definition->getDescriptionInfo($definition['identifier']); } foreach ($facet_count as $facet) { if (empty($facet_map[$facet->facet_name])) { $facet_map[$facet->facet_name] = []; } $facet_map[$facet->facet_name][$facet->value] = $facet->count; } $result = new Data(); $result->paging = Pager::calculatePagingHeaders($limit, $offset, $definition_count); $result->data = ['filter' => [['filterProperty' => 'theme', 'displayName' => Lang::get('datasets.theme'), 'options' => @$facet_map['theme'], 'count' => count(@$facet_map['theme'])], ['filterProperty' => 'keywords', 'displayName' => Lang::get('datasets.keywords'), 'options' => @$facet_map['keyword'], 'count' => count(@$facet_map['keyword'])], ['filterProperty' => 'language', 'displayName' => Lang::get('datasets.language'), 'options' => @$facet_map['language'], 'count' => count(@$facet_map['language'])], ['filterProperty' => 'rights', 'displayName' => Lang::get('datasets.license'), 'options' => @$facet_map['rights'], 'count' => count(@$facet_map['rights'])], ['filterProperty' => 'publisher_name', 'displayName' => Lang::get('datasets.publisher'), 'options' => @$facet_map['publisher_name'], 'count' => count(@$facet_map['publisher_name'])]], 'paging' => $this->calculatePagingInfo($limit, $offset, $definition_count), 'datasets' => $definitions_info]; return ContentNegotiator::getResponse($result, 'json'); }
/** * Perform the SPECTQL query. */ private function performQuery($uri) { SPECTQLController::$TMP_DIR = __DIR__ . "/../tmp/"; // Fetch the original uri, which is a hassle since our spectql format allows for a ? - character // identify the start of a filter, the Request class sees this is the start of query string parameters // and fails to parse them as they only contain keys, but never values ( our spectql filter syntax is nowhere near // the same as a query string parameter sequence). Therefore, we need to build our spectql uri manually. // Furthermore, after the ? - character dots are replaced with underscores by PHP itself. http://ca.php.net/variables.external // This is another reason why we build the query string to be passed to the parser ourselves. // The Request class also seems to have an issue with evaluating a semi-colon in the query string // It puts the semi-colon and what follows next to the first query string parameter, IF there are multiple // query string parameters (lon>5&lon<10), since this isn't really supported by PHP, Request from Symfony tries // apparently a best effort at fixing this. $filter = ""; $original_uri = \Request::fullUrl(); $root = \Request::root(); if (preg_match("%{$root}\\/spectql\\/(.*)%", $original_uri, $matches)) { $query_uri = urldecode($matches[1]); } $format = ""; // Fetch the format of the query if (preg_match("/.*(:[a-zA-Z]+)&?(.*?)/", $query_uri, $matches)) { $format = ltrim($matches[1], ":"); } // Remove the format and any following query string parameters if (!empty($format)) { $query_uri = preg_replace("/:" . $format . "\\??.*/", '', $query_uri); } // Initialize the parser with our query string $parser = new SPECTQLParser($query_uri); $context = array(); // array of context variables $universalquery = $parser->interpret($context); // Display the query tree, uncomment in case of debugging /*$treePrinter = new TreePrinter(); $tree = $treePrinter->treeToString($universalquery); echo "<pre>"; echo $tree; echo "</pre>";*/ $interpreter = new UniversalInterpreter(new UniversalFilterTableManager()); $result = $interpreter->interpret($universalquery); // Convert the resulting table object to a php object $converter = new TableToPhpObjectConverter(); $object = $converter->getPhpObjectForTable($result); // Perform a clean-up, every property that is empty can be thrown away foreach ($object as $index => $property) { if ($this->isArrayNull($property)) { unset($object[$index]); } } $rootname = "spectqlquery"; // Get the required properties for the Data object $definition_uri = preg_match('/(.*?)\\{.*/', $uri, $matches); // If no selection statement is given, abort the processing of the query if (empty($matches)) { \App::abort(400, "Please provide a select statement with the SPECTQL query (e.g. { column_1, column_2 })."); } $definition_uri = $matches[1]; $definition_repo = \App::make('Tdt\\Core\\Repositories\\Interfaces\\DefinitionRepositoryInterface'); $definition = $definition_repo->getByIdentifier($definition_uri); if (!empty($definition)) { $source_definition = $definition_repo->getDefinitionSource($definition['source_id'], $definition['source_type']); } $rest_parameters = str_replace($definition['collection_uri'] . '/' . $definition['resource_name'], '', $uri); $rest_parameters = ltrim($rest_parameters, '/'); $rest_parameters = explode('/', $rest_parameters); if (empty($rest_parameters[0]) && !is_numeric($rest_parameters[0])) { $rest_parameters = array(); } $data = new Data(); $data->data = $object; // Specify it's a SPECTQL result $data->is_spectql = true; $data->rest_parameters = $rest_parameters; // Add definition to the object $data->definition = $definition; // Add source definition to the object $data->source_definition = $source_definition; // Return the formatted response with content negotiation return ContentNegotiator::getResponse($data, $format); }