<?php namespace Opf; use DI\ContainerBuilder; use Exception; use Opf\Handlers\HttpErrorHandler; use Opf\Util\Util; use Slim\App; use Slim\Factory\AppFactory; class ScimServer { /** * @var string $scimServerPhpRoot The root of the project using * OPF as a dependency. This is needed for autoloading purposes, * such that all classes of the project using OPF can be made * visible to OPF. */ private string $scimServerPhpRoot; /** * A container builder which is used to configure and create a * DI container, used by the Slim application */ private ContainerBuilder $containerBuilder; /** * The Slim application to configure and run as a server, exposing * the SCIM API */ private App $app; /** * @var array $dependencies An array holding dependency definitions, * passed to the DI ContainerBuilder for configuring the DI container */ private array $dependencies; /** * @var array $middleware Any custom middleware that needs to be added * to the Slim application (e.g., custom auth middleware) */ private array $middleware; /** * ScimServer class constructor * * @param string $scimServerPhpRoot The root of the project using * the OPF library. Needed for autoloading. See more in description * of the dedicated class property of the same name */ public function __construct(string $scimServerPhpRoot) { $this->scimServerPhpRoot = $scimServerPhpRoot; /** * Once we have the root directory of the project that's using * OPF, we include its autoload file, so that we don't run into * autoloading issues. */ require $this->scimServerPhpRoot . '/vendor/autoload.php'; } public function setConfig(string $configFilePath) { if (!isset($configFilePath) || empty($configFilePath)) { throw new Exception("Config file path must be supplied"); } Util::setConfigFile($configFilePath); } public function setDependencies(array $dependencies = array()) { $baseDependencies = require __DIR__ . '/Dependencies/dependencies.php'; $this->dependencies = array_merge($baseDependencies, $dependencies); } public function setMiddleware(array $middleware = array()) { $this->middleware = $middleware; } public function run() { session_start(); // Instantiate the PHP-DI ContainerBuilder $containerBuilder = new ContainerBuilder(); $config = Util::getConfigFile(); if ($config['isInProduction']) { $containerBuilder->enableCompilation(__DIR__ . '/../var/cache'); } // Set up a few Slim-related settings $settings = [ 'settings' => [ 'determineRouteBeforeAppMiddleware' => false, 'displayErrorDetails' => true, // set to false in production 'addContentLengthHeader' => false, // Allow the web server to send the content-length header ] ]; $containerBuilder->addDefinitions($settings); // Set all necessary dependencies which are provided in this class' // $dependencies attribute $containerBuilder->addDefinitions($this->dependencies); // Build PHP-DI Container instance $container = $containerBuilder->build(); // Instantiate the app AppFactory::setContainer($container); $this->app = AppFactory::create(); // Set our app's base path if it's configured if (isset($config['basePath']) && !empty($config['basePath'])) { $this->app->setBasePath($config['basePath']); } // Register routes $routes = require __DIR__ . '/routes.php'; $routes($this->app); // Iterate through the custom middleware (if any) and set it if (isset($this->middleware) && !empty($this->middleware)) { foreach ($this->middleware as $middleware) { $this->app->addMiddleware($this->app->getContainer()->get($middleware)); } } // Add Routing Middleware $this->app->addRoutingMiddleware(); $this->app->addBodyParsingMiddleware(); $callableResolver = $this->app->getCallableResolver(); $responseFactory = $this->app->getResponseFactory(); // Instantiate our custom Http error handler that we need further down below $errorHandler = new HttpErrorHandler($callableResolver, $responseFactory); // Add error middleware $errorMiddleware = $this->app->addErrorMiddleware( $config['isInProduction'] ? false : true, true, true ); $errorMiddleware->setDefaultErrorHandler($errorHandler); // Run app $this->app->run(); } }