Skip to content
Snippets Groups Projects
ServiceModule.php 12.9 KiB
Newer Older
<?php declare(strict_types=1);

namespace uib\ub\loadspeakr\modules;
alvaro's avatar
alvaro committed

use ARC2;
use uib\ub\loadspeakr\Configuration;
use uib\ub\loadspeakr\Convert;
use uib\ub\loadspeakr\HTTPStatus;
use uib\ub\loadspeakr\Logging;
use uib\ub\loadspeakr\Utils;

final class ServiceModule implements ModuleInterface
    private Configuration $configuration;
    private Utils $utils;
    private string $basedir;

    public function __construct(Configuration $configuration, Utils $utils)
    {
        $this->configuration = $configuration;
        $this->utils = $utils;
        $this->basedir = $configuration->getConfigValue('conf', 'basedir');
        $this->endpoints = $configuration->getConfigValue('bootstrap', 'endpoints');
    /**
     * Checking default components.
     *
     * @param $serviceName
     * @param $arguments
     * @param $extension
     * @param $conf
     * @param $lodspk
     */
    private function checkComponents($serviceName, $arguments, $extension, $conf, $lodspk)
    {

        if (file_exists(
          $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/scaffold.ttl'
        )) {
            $subDir = $this->readScaffold(
              $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/scaffold.ttl',
              join("/", $arguments)
            );
            $subDir .= '/';
            $lodspk['model'] = $conf['home'] . $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/' . $subDir;
            $lodspk['view'] = $conf['view']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/' . $subDir . $extension . '.template';
        } elseif (file_exists(
          $conf['home'] . $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName
        )) {
            $lodspk['model'] = $conf['home'] . $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/';
            $lodspk['view'] = $conf['home'] . $conf['view']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/' . $extension . '.template';
        } else {
            if (is_null($lodspk['model']) && is_null($lodspk['view'])) {
                //checking other components
                if (!empty($conf['components']['services']) && count($conf['components']['services']) > 0) {
                    foreach ($conf['components']['services'] as $service) {
                        $serviceArray = explode("/", $service);
                        if ($serviceName == end($serviceArray)) {
                            array_pop($serviceArray);
                            $conf['service']['prefix'] = array_pop($serviceArray);
                            $conf['model']['directory'] = join("/", $serviceArray);
                            $conf['view']['directory'] = $conf['model']['directory'];
                            if (file_exists(
                              $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/scaffold.ttl'
                            )) {
                                $subDir = $this->readScaffold(
                                  $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/scaffold.ttl',
                                  join("/", $arguments)
                                );
                                $subDir .= '/';
                                $lodspk['model'] = $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/' . $subDir;
                                $lodspk['view'] = $conf['view']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/' . $subDir . $extension . '.template';
                            } elseif (file_exists(
                              $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName
                            )) {
                                $lodspk['model'] = $conf['model']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/';
                                $lodspk['view'] = $conf['view']['directory'] . '/' . $conf['service']['prefix'] . '/' . $serviceName . '/' . $extension . '.template';
                            }
                        }
                    }
                }
            }
        }

        return ['conf' => $conf, 'lodspk' => $lodspk];
    }

    public function match($uri)
    {
        $conf = $this->configuration->getConfigValues('conf');
        $acceptContentType = $this->configuration->getConfigValue('bootstrap', 'acceptContentType');
        $localUri = $this->configuration->getConfigValue('bootstrap', 'localUri');
        $lodspk = $this->configuration->getConfigValue('bootstrap', 'lodspk');

        $q = preg_replace('|^' . $conf['basedir'] . '|', '', $localUri);
        $qArr = explode('/', $q);
        $extension = Utils::getExtension($acceptContentType, $conf['http_accept']);
        $viewFile = null;
        $tokens = $qArr;
        $arguments = array();
        while (sizeof($tokens) > 0) {
            $serviceName = join("%2F", $tokens);
            //Use .extension at the end of the service to force a particular content type
            $lastSegment = end($tokens);
            if (strpos($lastSegment, '.') > 0) {
                $aux = explode(".", $lastSegment);
                if (sizeof($aux) > 1) {
                    $requestExtension = array_pop($aux);
                    $contentTypes = $conf['http_accept'][$requestExtension];
                    if ($contentTypes != null) {
                        $acceptContentType = $contentTypes[0];
                        $extension = $requestExtension;
                    }
                }
                $serviceName = join(".", $aux);
            }

            $foundComponents = $this->checkComponents(
              $serviceName,
              $arguments,
              $extension,
              $conf,
              $this->configuration->getConfigValue('bootstrap', 'lodspk')
            );
            $lodspk = $foundComponents["lodspk"];
            $lodspk['serviceName'] = implode("/", $tokens);
            $lodspk['componentName'] = $lodspk['serviceName'];
            $modelFile = $foundComponents['lodspk']['model'] . $extension . '.queries';
            if (file_exists($lodspk['model'] . $extension . '.queries')) {
                if (!file_exists($lodspk['view'])) {
                    $viewFile = null;
                } else {
                    $viewFile = $lodspk['view'];
                }
                return array($modelFile, $viewFile);
            }

            if (file_exists($lodspk['model'] . 'queries')) {
                $modelFile = $lodspk['model'] . 'queries';
                if (!file_exists($lodspk['view'])) {
                    $lodspk['resultRdf'] = true;
                    $viewFile = null;
                } else {
                    $viewFile = $lodspk['view'];
                }
                return array($modelFile, $viewFile);
            }

            if (file_exists($lodspk['model'])) {
            array_unshift($arguments, array_pop($tokens));
        }
    private function altUri(array $parameter, int $index)
    {
        $nsLocal = $this->configuration->getConfigValue('conf', 'ns')['local'];
        $altUri = Utils::curie2uri($parameter[$index]);
        return preg_replace("|^" . $this->basedir . "|", $nsLocal, $altUri);
    }

    public function execute($service)
    {
        $conf = $this->configuration->getConfigValues('conf');
        $localUri = $this->configuration->getConfigValue('bootstrap', 'localUri');
        $uri = $this->configuration->getConfigValue('bootstrap', 'uri');
        $acceptContentType = $this->configuration->getConfigValue('bootstrap', 'acceptContentType');
        $lodspk = $this->configuration->getConfigValue('bootstrap', 'lodspk');
        $firstResults = $this->configuration->getConfigValue('bootstrap', 'firstResults');
        $results = $this->configuration->getConfigValue('bootstrap', 'results');
        $context = array();
        $context['contentType'] = $acceptContentType;
        $params = $this->getParams($localUri);
        $extension = Utils::getExtension($acceptContentType, $conf['http_accept']);
        [$modelFile, $viewFile] = $service;
        try {
            $prefixHeader = array();

            for ($i = 0; $i < sizeof($params); $i++) {
                if ($params[$i] && Utils::mirror_external_uris($conf)) {
                    $params[$i] = Utils::uri2curie($this->altUri($params, $i));
                }
            }

            $segmentConnector = "";
            for ($i = 0; $i < sizeof($params); $i++) {
                if ($params[$i]) {
                    Utils::curie2uri($params[$i]);
                    $auxPrefix = Utils::getPrefix($params[$i], $conf['ns']);

                    if ($auxPrefix['ns'] != null) {
                        $prefixHeader[] = $auxPrefix;
                    }

                    $args["arg" . $i] = $params[$i];
                    $args["all"] .= $segmentConnector . $params[$i];

                    if ($segmentConnector == "") {
                        $segmentConnector = "/";
                    }
            $lodspk['home'] = $conf['basedir'];
            $lodspk['baseUrl'] = $conf['basedir'];
            $lodspk['module'] = 'service';
            $lodspk['root'] = $conf['root'];
            $lodspk['contentType'] = $acceptContentType;
            $lodspk['ns'] = $conf['ns'];
            $lodspk['this']['value'] = $uri;
            $lodspk['this']['curie'] = Utils::uri2curie($uri);
            $lodspk['local']['value'] = $localUri;
            $lodspk['local']['curie'] = Utils::uri2curie($localUri);
            $lodspk['contentType'] = $acceptContentType;
            $lodspk['endpoint'] = $conf['endpoint'];
            $lodspk['type'] = $modelFile;
            $lodspk['header'] = $prefixHeader;
            $lodspk['args'] = $args;
            $lodspk['add_mirrored_uris'] = false;
            $lodspk['baseUrl'] = $conf['basedir'];
            $lodspk['this']['value'] = $uri;
            if ($viewFile == null) {
                $lodspk['transform_select_query'] = true;
            }

            Utils::queryFile($modelFile, $this->endpoints, $results, $firstResults);

            if (!$lodspk['resultRdf']) {
                $results = Utils::internalize($results);
                $firstAux = Utils::getfirstResults($results);

                if (is_array($results)) {
                    $resultsObj = Convert::array_to_object($results);
                    $results = $resultsObj;
                } else {
                    $resultsObj = $results;
                }
                $lodspk['firstResults'] = Convert::array_to_object($firstAux);
            } else {
                $resultsObj = $results;
            }
            Utils::processDocument($viewFile, $lodspk, $results);
        } catch (Exception $ex) {
            echo $ex->getMessage();
            if ($conf['debug']) {
                Logging::log($ex->getMessage(), E_ERROR);
            }
            HTTPStatus::send500($uri);
        }
    }

    protected function getParams($uri)
    {
        $count = 1;
        $functionAndParams = explode('/', str_replace($this->basedir . $this->lodspk['serviceName'], '', $uri, $count));
        if (sizeof($functionAndParams) > 1) {
            array_shift($functionAndParams);
            return $functionAndParams;
        }
alvaro's avatar
alvaro committed
    }

    protected function readScaffold($scaffold, $serviceArgs)
    {
        $parser = ARC2::getTurtleParser();
        $parser->parse($scaffold);
        $triples = $parser->getTriples();
        $aux = Utils::filterTriples(
          $triples,
          array(null, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://lodspeakr.org/vocab/ScaffoldedService")
        );
        $scaffoldUri = $aux[0][0];
        $aux = Utils::filterTriples($triples, array($scaffoldUri, "http://lodspeakr.org/vocab/scaffold", null));
        foreach ($aux as $r) {
            $patterns = Utils::filterTriples($triples, array($r[2], "http://lodspeakr.org/vocab/uriPattern", null));
            $pattern = stripcslashes($patterns[0][2]);
            if (preg_match("|$pattern|", $serviceArgs) > 0) {
                $patternDir = Utils::filterTriples(
                  $triples,
                  array($r[2], "http://lodspeakr.org/vocab/subComponent", null)
                );
alangrafu's avatar
alangrafu committed
}