shieldfy/shieldfy-php-client

View on GitHub
src/Guard.php

Summary

Maintainability
A
55 mins
Test Coverage
<?php
namespace Shieldfy;

use PDO;
use Shieldfy\Config;
use Shieldfy\Events;
use Shieldfy\Session;
use Shieldfy\Http\ApiClient;
use Shieldfy\Http\Dispatcher;
use Shieldfy\Install\Verifier;
use Shieldfy\Install\Installer;
use Shieldfy\Monitors\MonitorsBag;
use Shieldfy\Callbacks\CallbackHandler;
use Shieldfy\Collectors\CodeCollector;
use Shieldfy\Collectors\UserCollector;
use Shieldfy\Collectors\RequestCollector;
use Shieldfy\Collectors\PDO\TraceablePDO;
use Shieldfy\Collectors\ExceptionsCollector;
use Shieldfy\Exceptions\InstallationException;

class Guard
{
    /**
     * @var Singleton Reference to singleton class instance
     */
    private static $instance = null;

    /**
     * @var Api Endpoint
     * @var Version
     * @var Config
     * @var Dispatcher
     * @var Collectors
     * @var Session
     * @var Events
     */
    public $endpoint = 'https://api.shieldfy.com/v1';
    public $version = '3.0.0';
    public $config = null;
    public $dispatcher = null;
    public $collectors = [];
    public $session = null;
    public $events = null;

    /**
     * Initialize Shieldfy guard.
     *
     * @param array $config
     * @return object
     */
    public static function init(array $config = [])
    {
        if (self::$instance !== null) {
            return self::$instance;
        }

        return self::$instance = new self($config);
    }

    /**
     * Create a new Guard Instance
     * @param array $userConfig
     * return initialized guard
     */
    private function __construct(array $userConfig)
    {

        // Set config container.
        $userConfig['version'] = $this->version;
        $this->config = new Config($userConfig);

        // Overwrite the endpoint.
        if (isset($this->config['endpoint'])) {
            $this->endpoint = $this->config['endpoint'];
        }


        // Set Dispatcher.
        $apiClient = new ApiClient($this->endpoint, $this->config);
        $this->dispatcher = new Dispatcher($this->config, $apiClient);


        // Starting collectors.
        $this->collectors = $this->startCollecting();


        // Starting events.
        $this->events = new Events;


        // Catch callbacks.
        $this->catchCallbacks($this->collectors['request'], $this->config);


        $verifier = (new Verifier($this->config, $this->collectors['request']))->whoIsCalling();

        // Check the installation.
        if (!$this->isInstalled()) {
            try {
                (new Installer($this->collectors['request'], $this->dispatcher, $this->config))->run();
                $verifier->success();
            } catch (InstallationException $e) {
                $verifier->error($e->getMessage());
                return;
            }
        }

        // Verify installation.
        $verifier->check();

        // Start shieldfy guard.
        $this->startGuard();
    }

    /**
     * Starting Guard
     */
    private function startGuard()
    {

        // Starting session.
        $this->session = new Session(
                                $this->collectors['user'],
                                $this->collectors['request'],
                                $this->dispatcher,
                                $this->events
                        );


        register_shutdown_function([$this, 'flush']);

        // Expose essential headers.
        $this->exposeHeaders();

        // Starting monitors.
        $monitors = new MonitorsBag($this->config, $this->session, $this->dispatcher, $this->collectors, $this->events);
        $monitors->run();
    }


    /**
     * Start Collecting needed data.
     * @return Array CollectorsBag
     */
    private function startCollecting()
    {
        $exceptionsCollector = new ExceptionsCollector($this->config, $this->dispatcher);
        $requestCollector = new RequestCollector($_GET, $_POST, $_SERVER, $_COOKIE, $_FILES);
        $userCollector = new UserCollector($requestCollector);
        $codeCollector = new CodeCollector($this->config);

        return [
            'exceptions' => $exceptionsCollector,
            'request'    => $requestCollector,
            'user'       => $userCollector,
            'code'       => $codeCollector
        ];
    }

    /**
     * Catch callbacks from Shieldfy API
     * @param  RequestCollector $request
     * @param  Config           $config
     * @return void
     */
    public function catchCallbacks(RequestCollector $request, Config $config)
    {
        (new CallbackHandler($request, $config, $this->dispatcher))->catchCallback();
    }

    /**
     * Check whether guard is installed.
     * @return boolean
     */
    public function isInstalled()
    {
        if (file_exists($this->config['paths']['data'].'/installed')) {
            return true;
        }
        return false;
    }

    /**
     * flush data to the API
     */
    public function flush()
    {
        $this->session->flush();
    }

    /* attach pdo database */
    public function attachPDO(PDO &$pdo)
    {
        return $pdo = new TraceablePDO($pdo, $this->events);
    }


    /**
     * Expose useful headers
     * @return void
     */
    private function exposeHeaders()
    {
        if (function_exists('header_remove')) {
            header_remove('x-powered-by');
        } else {
            header('x-powered-by: unknown');
        }
        if ($this->config['headers']) {
            foreach ($this->config['headers'] as $header => $value) {
                if ($value === false) {
                    continue;
                }
                header($header.': '.$value);
            }
        }

        $signature = hash_hmac('sha256', $this->config['app_key'], $this->config['app_secret']);
        header('X-Web-Shield: ShieldfyWebShield');
        header('X-Shieldfy-Signature: '.$signature);
    }

    /* Singleton protection. */
    protected function __clone()
    {
    }

    protected function __wakeup()
    {
    }
}