Files
sprinkle-uf-tweaks/src/ServicesProvider/ServicesProvider.php

237 lines
9.2 KiB
PHP

<?php
/*
* AVSDev UF Tweaks (https://avsdev.uk)
*
* @link https://git.avsdev.uk/avsdev/sprinkle-uf-tweaks
* @license https://git.avsdev.uk/avsdev/sprinkle-uf-tweaks/blob/master/LICENSE.md (LGPL-3.0 License)
*/
namespace UserFrosting\Sprinkle\UFTweaks\ServicesProvider;
use Illuminate\Database\Capsule\Manager as Capsule;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use UserFrosting\Sprinkle\Core\Log\MixedFormatter;
use UserFrosting\Sprinkle\UFTweaks\Twig\HasRoleExtension;
use UserFrosting\Sprinkle\UFTweaks\Twig\LocaleOverrideExtension;
use UserFrosting\Sprinkle\UFTweaks\Twig\MobileDetectExtension;
use UserFrosting\Sprinkle\UFTweaks\Mail\RetryMailer;
/**
* Registers services for the UFTweaks sprinkle.
*
* @author Craig Williams (https://avsdev.uk)
*/
class ServicesProvider
{
/**
* Register UserFrosting's services.
*
* @param ContainerInterface $container A DI container implementing ArrayAccess and psr-container.
*/
public function register(ContainerInterface $container)
{
/*
* Extend the 'classMapper' service to register sprunje classes.
*
* Mappings added: 'activity_sprunje'
*
* @return \UserFrosting\Sprinkle\Core\Util\ClassMapper
*/
$container->extend('classMapper', function ($classMapper, $c) {
$classMapper->setClassMapping('activity_sprunje', 'UserFrosting\Sprinkle\UFTweaks\Sprunje\ActivitySprunje');
$classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\UFTweaks\Database\Models\User');
$classMapper->setClassMapping('user_sprunje', 'UserFrosting\Sprinkle\Organisations\Sprunje\UserSprunje');
return $classMapper;
});
/*
* Returns a callback that forwards to dashboard if user is already logged in.
*
* @return callable
*/
$container['redirect.onAlreadyLoggedIn'] = function ($c) {
/*
* This method is invoked when a user attempts to perform certain public actions when they are already logged in.
*
* @todo Forward to user's landing page or last visited page
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Message\ResponseInterface $response
* @param array $args
* @return \Psr\Http\Message\ResponseInterface
*/
return function (Request $request, Response $response, array $args) use ($c) {
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
$authorizer = $c->authorizer;
$currentUser = $c->authenticator->user();
if ($authorizer->checkAccess($currentUser, 'uri_dashboard')) {
return $response->withRedirect($c->router->pathFor('dashboard'));
} else {
return $response->withRedirect($c->router->pathFor('index'));
}
};
};
/*
* Returns a callback that handles setting the `UF-Redirect` header after a successful login.
*
* Overrides the service definition in the account Sprinkle.
*
* @return callable
*/
$container['redirect.onLogin'] = function ($c) {
/*
* This method is invoked when a user completes the login process.
*
* Returns a callback that handles setting the `UF-Redirect` header after a successful login.
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Message\ResponseInterface $response
* @param array $args
* @return \Psr\Http\Message\ResponseInterface
*/
return function (Request $request, Response $response, array $args) use ($c) {
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
$authorizer = $c->authorizer;
$currentUser = $c->authenticator->user();
if ($authorizer->checkAccess($currentUser, 'uri_dashboard')) {
return $response->withHeader('UF-Redirect', $c->router->pathFor('dashboard'));
} else {
return $response->withHeader('UF-Redirect', $c->router->pathFor('index'));
}
};
};
/*
* Extend the 'authorizer' service to fix some callbacks
*
* @return \UserFrosting\Sprinkle\Core\Util\ClassMapper
*/
$container->extend('authorizer', function ($authorizer, $c) {
/*
* Check if all values in the array $needle are present in the values of $haystack.
*
* @param array[mixed] $needle the array whose values we should look for in $haystack
* @param array[mixed] $haystack the array of values to search.
* @return bool true if every value in $needle is present in the values of $haystack, false otherwise.
*/
$authorizer->addCallback(
'subset',
function ($needle, $haystack) {
if (!is_countable($needle)) {
$needle = [ $needle ];
}
return count($needle) == count(array_intersect($needle, $haystack));
}
);
/*
* Check if all keys of the array $needle are present in the values of $haystack.
*
* This function is useful for whitelisting an array of key-value parameters.
* @param array[mixed] $needle the array whose keys we should look for in $haystack
* @param array[mixed] $haystack the array of values to search.
* @return bool true if every key in $needle is present in the values of $haystack, false otherwise.
*/
$authorizer->addCallback(
'subset_keys',
function ($needle, $haystack) {
if (!is_countable($needle)) {
$needle = [ $needle ];
}
return count($needle) == count(array_intersect(array_keys($needle), $haystack));
}
);
/*
* Check if the specified user (by user_id) has a particular permission.
*
* @param int $user_id the id of the user.
* @param int $permission_slug slug of the permission to check.
* @return bool true if the user has the permission, false otherwise.
*/
$authorizer->addCallback(
'has_permission',
function ($user_id, $permission_slug) {
return Capsule::table('role_users')
->join('permission_roles', 'role_users.role_id', '=', 'permission_roles.role_id')
->join('permissions', 'permission_roles.permission_id', '=', 'permissions.id')
->where('user_id', $user_id)
->where('slug', $permission_slug)
->count() > 0;
}
);
return $authorizer;
});
/*
* Extends the 'view' service with the HasRole extension for Twig.
*
* @return \Slim\Views\Twig
*/
$container->extend('view', function ($view, $c) {
$twig = $view->getEnvironment();
$twig->addExtension(new HasRoleExtension($c));
$twig->addExtension(new MobileDetectExtension($c));
$twig->addExtension(new LocaleOverrideExtension($c));
return $view;
});
/*
* Token logging with Monolog.
*
* Extend this service to push additional handlers onto the 'tokens' log stack.
*
* @return \Monolog\Logger
*/
$container['tokenLogger'] = function ($c) {
$logger = new Logger('tokens');
$logFile = $c->locator->findResource('log://userfrosting.log', true, true);
$handler = new StreamHandler($logFile);
$formatter = new MixedFormatter(null, null, true);
$handler->setFormatter($formatter);
$logger->pushHandler($handler);
return $logger;
};
/*
* Mail service.
*
* @return \UserFrosting\Sprinkle\Core\Mail\Mailer
* @return \UserFrosting\Sprinkle\UFTweaks\Mail\RetryMailer
*/
$container->extend('mailer', function ($mailer, $c) {
if (!$c->config['retry_mailer.enabled']) {
return $mailer;
}
$retryMailer = new RetryMailer($c->mailLogger, $c->config['mail']);
// Use UF debug settings to override any service-specific log settings.
if (!$c->config['debug.smtp']) {
$retryMailer->getPhpMailer()->SMTPDebug = 0;
}
return $retryMailer;
});
}
}