Core code restructure (#697)

* Initial renaming to a single global App\ namespace.
* Move CSRF/Flash under Session, move Session under Request
* Use new Request Station helper
* Unify App/Acl and App/Acl/StationAcl
* Alphabetize composer.json
This commit is contained in:
Buster "Silver Eagle" Neece 2018-08-04 17:05:14 -05:00 committed by GitHub
parent cf8642f7bd
commit 98ff8f69cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
407 changed files with 1647 additions and 1971 deletions

View File

@ -1,113 +0,0 @@
<?php
namespace App;
use Entity;
class Acl
{
/** @var Entity\Repository\RolePermissionRepository */
protected $permission_repo;
/** @var array|null An array of actions enabled by each role. */
protected $_actions = null;
public function __construct(Entity\Repository\RolePermissionRepository $permission_repo)
{
$this->permission_repo = $permission_repo;
$this->reload();
}
/**
* Force a reload of the internal ACL cache (used in the event of a user status change.
*/
public function reload(): void
{
$this->_actions = $this->permission_repo->getActionsForAllRoles();
$this->_roles = null;
$this->_cache = null;
}
/**
* Check if a specified User entity is allowed to perform an action (or array of actions).
*
* @param Entity\User|null $user
* @param $action
* @return bool
*/
public function userAllowed(?Entity\User $user = null, $action): bool
{
if (!($user instanceof Entity\User)) {
return false;
}
$roles = [];
if ($user->getRoles()->count() > 0) {
foreach ($user->getRoles() as $role) {
$roles[] = $role->getId();
}
}
return $this->roleAllowed($roles, $action);
}
/**
* Check if a role (or array of roles) is allowed to perform an action (or array of actions).
*
* @param int|array $role_id
* @param string|array $action
* @return bool
*/
public function roleAllowed($role_id, $action)
{
// Iterate through an array of roles and return with the first "true" response, or "false" otherwise.
if (\is_array($role_id)) {
foreach ($role_id as $r) {
if ($this->roleAllowed($r, $action)) {
return true;
}
}
return false;
}
// If multiple actions are supplied, treat the list as "x OR y OR z", returning if any action is allowed.
if (\is_array($action)) {
foreach ($action as $a) {
if ($this->roleAllowed($role_id, $a)) {
return true;
}
}
return false;
}
if (\in_array('administer all', (array)$this->_actions[$role_id], true)) {
return true;
}
if (isset($this->_actions[$role_id]) && \in_array($action, $this->_actions[$role_id], true)) {
return true;
}
return false;
}
/**
* Wrapper around the 'userAllowed' function that throws a UI-friendly exception upon failure.
*
* @param Entity\User|null $user
* @param $action
* @throws Exception\NotLoggedIn
* @throws Exception\PermissionDenied
*/
public function checkPermission(?Entity\User $user = null, $action)
{
if (!($user instanceof Entity\User)) {
throw new \App\Exception\NotLoggedIn;
}
if (!$this->userAllowed($user, $action)) {
throw new \App\Exception\PermissionDenied;
}
}
}

View File

@ -1,47 +0,0 @@
<?php
namespace App\Console;
use Slim\Container;
/**
* Class Application
* Wraps the default Symfony console application with a DI-aware wrapper.
*
* @package App\Console
*/
class Application extends \Symfony\Component\Console\Application
{
/** @var Container */
protected $di;
/**
* @param Container $di
*/
public function setContainer(Container $di)
{
$this->di = $di;
}
/**
* @return Container
*/
public function getContainer(): Container
{
return $this->di;
}
/**
* @param $service_name
* @return mixed
* @throws \App\Exception
* @throws \Interop\Container\Exception\ContainerException
*/
public function getService($service_name)
{
if ($this->di->has($service_name)) {
return $this->di->get($service_name);
} else {
throw new \App\Exception(sprintf('Service "%s" not found.', $service_name));
}
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace App\Http;
class Request extends \Slim\Http\Request
{
/**
* Detect if a parameter exists in the request.
*
* Note: This method is not part of the PSR-7 standard.
*
* @param string $key The parameter key.
* @return bool Whether the key exists.
*/
public function hasParam($key): bool
{
return ($this->getParam($key, null) !== null);
}
}

View File

@ -1,15 +0,0 @@
<?php
namespace App\Middleware;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
class MiddlewareProvider implements ServiceProviderInterface
{
public function register(Container $di)
{
$di[DebugEcho::class] = function($di) {
return new DebugEcho($di[\Monolog\Logger::class]);
};
}
}

View File

@ -1,93 +0,0 @@
<?php
namespace AzuraCast\Console;
use App\Console\Command as AppCommand;
use Doctrine\ORM\EntityManager;
use Slim\Container;
class Application extends \App\Console\Application
{
/**
* Register all CLI commands and return a ready-to-execute CLI runner.
*
* @param Container $di
* @param $settings
* @return Application
*/
public static function create(Container $di, $settings): self
{
/** @var EntityManager $em */
$em = $di[EntityManager::class];
$helperSet = \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($em);
$helperSet->set(new \Symfony\Component\Console\Helper\QuestionHelper, 'dialog');
$cli = new self($settings['name'].' Command Line Tools ('.APP_APPLICATION_ENV.')', \AzuraCast\Version::getVersion());
$cli->setContainer($di);
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
// Doctrine ORM/DBAL
\Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli);
// Doctrine Migrations
$migrate_config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($em->getConnection());
$migrate_config->setMigrationsTableName('app_migrations');
$migrate_config->setMigrationsDirectory(APP_INCLUDE_BASE.'/src/Entity/Migration');
$migrate_config->setMigrationsNamespace('Entity\Migration');
$output = new \Symfony\Component\Console\Output\ConsoleOutput;
$migrate_config->setOutputWriter(new \Doctrine\DBAL\Migrations\OutputWriter(function($message) use ($output) {
$output->writeln($message);
}));
$migration_commands = [
new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand
];
foreach($migration_commands as $cmd) {
$cmd->setMigrationConfiguration($migrate_config);
$cli->add($cmd);
}
// Liquidsoap Internal CLI Commands
$cli->addCommands([
new Command\NextSong,
new Command\DjAuth,
new Command\DjOn,
new Command\DjOff,
]);
// Other App-specific Commands
$cli->addCommands([
// Locales
new AppCommand\LocaleGenerate,
new AppCommand\LocaleImport,
// Setup
new Command\MigrateConfig,
new Command\SetupInflux,
new Command\SetupFixtures,
new Command\Setup,
// Maintenance
new Command\ClearCache,
new Command\RestartRadio,
new Command\Sync,
new Command\ReprocessMedia,
new Command\GenerateApiDocs,
new Command\UptimeWait,
// User-side tools
new Command\ResetPassword,
]);
return $cli;
}
}

View File

@ -1,9 +0,0 @@
<?php
namespace AzuraCast\Exception\Supervisor;
use Monolog\Logger;
class AlreadyRunning extends \AzuraCast\Exception\Supervisor
{
protected $logger_level = Logger::INFO;
}

View File

@ -1,9 +0,0 @@
<?php
namespace AzuraCast\Exception\Supervisor;
use Monolog\Logger;
class NotRunning extends \AzuraCast\Exception\Supervisor
{
protected $logger_level = Logger::INFO;
}

View File

@ -29,7 +29,7 @@ define('APP_INCLUDE_CACHE', APP_INCLUDE_TEMP . '/cache');
if (APP_INSIDE_DOCKER) {
$_ENV = getenv();
} else if (file_exists(APP_INCLUDE_BASE.'/env.ini')) {
$_ENV = array_merge($_ENV, parse_ini_file(APP_INCLUDE_BASE.'/env.ini'));
$_ENV = array_merge($_ENV, parse_ini_file(APP_INCLUDE_ROOT.'/app/env.ini'));
}
// Application environment.
@ -67,7 +67,7 @@ $di = new \Slim\Container([
]);
// Define services.
$settings = require(__DIR__.'/bootstrap/settings.php');
call_user_func(include(__DIR__.'/bootstrap/services.php'), $di, $settings);
$settings = require(dirname(__DIR__).'/config/settings.php');
call_user_func(include(dirname(__DIR__).'/config/services.php'), $di, $settings);
return $di;
return $di;

55
bootstrap/cli.php Normal file
View File

@ -0,0 +1,55 @@
<?php
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT);
ini_set('display_errors', 1);
$di = require __DIR__.'/app.php';
// Load app, to generate routes, etc.
$di->get('app');
// Placeholder locale functions
$translator = new \Gettext\Translator();
$translator->register();
/** @var \Doctrine\ORM\EntityManager $em */
$em = $di[\Doctrine\ORM\EntityManager::class];
$helperSet = \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($em);
$helperSet->set(new \Symfony\Component\Console\Helper\QuestionHelper, 'dialog');
$cli = new \App\Console\Application($settings['name'].' Command Line Tools ('.APP_APPLICATION_ENV.')', \App\Version::getVersion());
$cli->setContainer($di);
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
// Doctrine ORM/DBAL
\Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli);
// Doctrine Migrations
$migrate_config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($em->getConnection());
$migrate_config->setMigrationsTableName('app_migrations');
$migrate_config->setMigrationsDirectory(dirname(__DIR__).'/src/Entity/Migration');
$migrate_config->setMigrationsNamespace('App\Entity\Migration');
$output = new \Symfony\Component\Console\Output\ConsoleOutput;
$migrate_config->setOutputWriter(new \Doctrine\DBAL\Migrations\OutputWriter(function($message) use ($output) {
$output->writeln($message);
}));
$migration_commands = [
new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand,
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand
];
foreach($migration_commands as $cmd) {
$cmd->setMigrationConfiguration($migrate_config);
$cli->add($cmd);
}
$cli->registerAppCommands();
return $cli;

View File

@ -17,41 +17,26 @@ modules:
coverage:
enabled: true
include:
- app/*
- src/*
exclude:
# Loaded before tests
- app/bootstrap.php
- app/bootstrap/**.php
- app/src/App/Tests/Module.php
- app/src/App/Doctrine/EntityManagerFactory.php
- src/Tests/Module.php
- src/Doctrine/EntityManagerFactory.php
# Not used in entire application
- app/**/*.conf.sample.php
- app/src/App/Crypto.php
- app/src/App/Messenger.php
- app/src/App/Forms/Element/Recaptcha.php
- app/src/App/Paginator/Doctrine.php
- app/src/App/Doctrine/Platform/*.php
- app/src/App/Doctrine/Paginate/*.php
- src/Doctrine/Platform/*.php
- src/Doctrine/Paginate/*.php
# Used in application, but not used in tests
- app/src/AzuraCast/Radio/Frontend/ShoutCast2.php
- app/src/AzuraCast/Console/Command/*.php
- app/src/App/Doctrine/Logger/EchoSQL.php
- app/src/App/Session/Temporary.php
- app/src/App/Console/Command/*.php
- app/src/Entity/Fixture/*
- app/src/Entity/Migration/*
- app/locale/**/*
- app/locale/*
- app/templates/system/error_general.phtml
- src/Radio/Frontend/ShoutCast2.php
- src/Console/Command/*.php
- src/Doctrine/Logger/EchoSQL.php
- src/Session/Temporary.php
- src/Console/Command/*.php
- src/Entity/Fixture/*
- src/Entity/Migration/*
# Exceptions
- app/src/App/Exception.php
- app/src/App/Exception/*.php
- app/src/App/Mvc/ErrorHandler.php
# Used in application, but not detected properly by the coverage tool :(
- app/config/*.conf.php
- app/config/**/*.conf.php
- app/**/routes.php
- src/Exception.php
- src/Exception/*.php
- src/Mvc/ErrorHandler.php

View File

@ -4,42 +4,42 @@
"license": "Apache-2.0",
"require": {
"php": ">=7.2",
"roave/security-advisories": "dev-master",
"slim/slim": "^3.0",
"league/plates": "^3.1",
"filp/whoops": "2.*",
"azuracast/azuraforms": "dev-master",
"zendframework/zend-paginator": "^2.7",
"zendframework/zend-config": "^3.1.0",
"doctrine/orm": "~2.6",
"cakephp/chronos": "^1.1",
"doctrine/data-fixtures": "^1.3",
"doctrine/dbal": "^2.8",
"doctrine/migrations": "^1.5",
"jdorn/sql-formatter": "^1.2",
"packaged/helpers": "^1.5",
"guzzlehttp/guzzle": ">6.0",
"doctrine/orm": "~2.6",
"electrolinux/phpquery": "0.9.6",
"james-heinrich/getid3": "dev-master",
"filp/whoops": "2.*",
"gettext/gettext": "^4.4",
"guzzlehttp/guzzle": ">6.0",
"guzzlehttp/oauth-subscriber": "^0.3.0",
"influxdb/influxdb-php": "^1.14.3",
"supervisorphp/supervisor": "^3.0",
"james-heinrich/getid3": "dev-master",
"jdorn/sql-formatter": "^1.2",
"league/plates": "^3.1",
"lstrojny/fxmlrpc": "^0.14.0",
"maxmind-db/reader": "~1.0",
"mobiledetect/mobiledetectlib": "^2.8",
"monolog/monolog": "^1.23",
"packaged/helpers": "^1.5",
"php-http/socket-client": "^1.2",
"php-http/message": "^1.4",
"php-http/guzzle6-adapter": "^1.1",
"mobiledetect/mobiledetectlib": "^2.8",
"guzzlehttp/oauth-subscriber": "^0.3.0",
"monolog/monolog": "^1.23",
"gettext/gettext": "^4.4",
"cakephp/chronos": "^1.1",
"doctrine/data-fixtures": "^1.3",
"maxmind-db/reader": "~1.0",
"symfony/finder": "^4.1"
"roave/security-advisories": "dev-master",
"slim/slim": "^3.0",
"supervisorphp/supervisor": "^3.0",
"symfony/finder": "^4.1",
"zendframework/zend-config": "^3.1.0",
"zendframework/zend-paginator": "^2.7"
},
"require-dev": {
"codeception/codeception": "^2.2",
"flow/jsonpath": "^0.3.4",
"zircote/swagger-php": "^2.0",
"mockery/mockery": "^1.0",
"squizlabs/php_codesniffer": "3.*"
"squizlabs/php_codesniffer": "3.*",
"zircote/swagger-php": "^2.0"
},
"authors": [
{
@ -49,10 +49,7 @@
],
"autoload": {
"psr-4": {
"App\\": "app/src/App",
"AzuraCast\\": "app/src/AzuraCast",
"Entity\\": "app/src/Entity",
"Controller\\": "app/src/Controller"
"App\\": "src"
}
},
"config": {

View File

@ -23,7 +23,7 @@ return [
'label' => __('Days Between Automated Assignments'),
'description' => __('Based on this setting, the system will automatically reassign songs every (this) days using data from the previous (this) days.'),
'class' => 'inline',
'default' => \AzuraCast\Sync\Task\RadioAutomation::DEFAULT_THRESHOLD_DAYS,
'default' => \App\Sync\Task\RadioAutomation::DEFAULT_THRESHOLD_DAYS,
'choices' => [
7 => sprintf(__('%d days'), 7),
14 => sprintf(__('%d days'), 14),
@ -43,4 +43,4 @@ return [
],
],
];
];

View File

@ -1,7 +1,7 @@
<?php
use \Entity\StationPlaylist;
use \App\Entity\StationPlaylist;
/** @var \AzuraCast\Customization $customization */
/** @var \App\Customization $customization */
$local_time_offset = \App\Timezone::getOffsetMinutes(null);
$local_time_hours = floor($local_time_offset / 60);
@ -342,4 +342,4 @@ return [
],
],
],
];
];

View File

@ -80,11 +80,11 @@ return [
'description' => __('Aggregate listener statistics are used to show station reports across the system. IP-based listener statistics are used to view live listener tracking and may be required for royalty reports.'),
'choices' => [
\Entity\Analytics::LEVEL_ALL => __('<b>Full:</b> Collect aggregate listener statistics and IP-based listener statistics'),
\Entity\Analytics::LEVEL_NO_IP => __('<b>Limited:</b> Only collect aggregate listener statistics'),
\Entity\Analytics::LEVEL_NONE => __('<b>None:</b> Do not collect any listener analytics'),
\App\Entity\Analytics::LEVEL_ALL => __('<b>Full:</b> Collect aggregate listener statistics and IP-based listener statistics'),
\App\Entity\Analytics::LEVEL_NO_IP => __('<b>Limited:</b> Only collect aggregate listener statistics'),
\App\Entity\Analytics::LEVEL_NONE => __('<b>None:</b> Do not collect any listener analytics'),
],
'default' => \Entity\Analytics::LEVEL_ALL,
'default' => \App\Entity\Analytics::LEVEL_ALL,
]
]
@ -122,4 +122,4 @@ return [
],
],
],
];
];

View File

@ -1,12 +1,12 @@
<?php
$frontends = \AzuraCast\Radio\Adapters::getFrontendAdapters();
$frontends = \App\Radio\Adapters::getFrontendAdapters();
$frontend_types = [];
foreach ($frontends['adapters'] as $adapter_nickname => $adapter_info) {
$frontend_types[$adapter_nickname] = $adapter_info['name'];
}
$frontend_default = $frontends['default'];
$backends = \AzuraCast\Radio\Adapters::getBackendAdapters();
$backends = \App\Radio\Adapters::getBackendAdapters();
$backend_types = [];
foreach ($backends['adapters'] as $adapter_nickname => $adapter_info) {
$backend_types[$adapter_nickname] = $adapter_info['name'];
@ -313,7 +313,7 @@ return [
'radio',
[
'label' => __('Advanced: Manual AutoDJ Mode'),
'description' => __('This mode disables AzuraCast\'s AutoDJ management, using Liquidsoap itself to manage song playback. "Next Song" and some other features will not be available.'),
'description' => __('This mode disables App\'s AutoDJ management, using Liquidsoap itself to manage song playback. "Next Song" and some other features will not be available.'),
'default' => '0',
'choices' => [0 => __('No'), 1 => __('Yes')],
'belongsTo' => 'backend_config',
@ -374,4 +374,4 @@ return [
],
],
],
];
];

View File

@ -34,7 +34,7 @@ return [
'multiCheckbox',
[
'label' => __('Web Hook Triggers'),
'options' => array_diff_key(\AzuraCast\Webhook\Dispatcher::getTriggers(), ['listener_lost' => 1, 'listener_gained' => 1]),
'options' => array_diff_key(\App\Webhook\Dispatcher::getTriggers(), ['listener_lost' => 1, 'listener_gained' => 1]),
'required' => true,
]
],
@ -129,4 +129,4 @@ return [
]
]
],
];
];

View File

@ -40,7 +40,7 @@ return [
'multiCheckbox',
[
'label' => __('Web Hook Triggers'),
'options' => \AzuraCast\Webhook\Dispatcher::getTriggers(),
'options' => \App\Webhook\Dispatcher::getTriggers(),
'required' => true,
]
],
@ -63,4 +63,4 @@ return [
]
]
],
];
];

View File

@ -76,7 +76,7 @@ return [
'multiCheckbox',
[
'label' => __('Web Hook Triggers'),
'options' => \AzuraCast\Webhook\Dispatcher::getTriggers(),
'options' => \App\Webhook\Dispatcher::getTriggers(),
'required' => true,
]
],
@ -109,4 +109,4 @@ return [
]
]
],
];
];

View File

@ -1,4 +1,7 @@
<?php
use App\Controller;
use App\Middleware;
return function(\Slim\App $app) {
$app->group('/admin', function () {
@ -8,8 +11,8 @@ return function(\Slim\App $app) {
$this->get('/sync/{type}', Controller\Admin\IndexController::class.':syncAction')
->setName('admin:index:sync')
->add([AzuraCast\Middleware\Permissions::class, 'administer all'])
->add(App\Middleware\DebugEcho::class);
->add([Middleware\Permissions::class, 'administer all'])
->add(Middleware\DebugEcho::class);
$this->group('/api', function () {
@ -22,11 +25,11 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Admin\ApiController::class.':deleteAction')
->setName('admin:api:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'administer api keys']);
})->add([Middleware\Permissions::class, 'administer api keys']);
$this->map(['GET', 'POST'], '/branding', Controller\Admin\BrandingController::class.':indexAction')
->setName('admin:branding:index')
->add([AzuraCast\Middleware\Permissions::class, 'administer settings']);
->add([Middleware\Permissions::class, 'administer settings']);
$this->group('/custom_fields', function() {
@ -42,7 +45,7 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Admin\CustomFieldsController::class.':deleteAction')
->setName('admin:custom_fields:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'administer custom fields']);
})->add([Middleware\Permissions::class, 'administer custom fields']);
$this->group('/permissions', function () {
@ -58,11 +61,11 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Admin\PermissionsController::class.':deleteAction')
->setName('admin:permissions:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'administer permissions']);
})->add([Middleware\Permissions::class, 'administer permissions']);
$this->map(['GET', 'POST'], '/settings', Controller\Admin\SettingsController::class.':indexAction')
->setName('admin:settings:index')
->add([AzuraCast\Middleware\Permissions::class, 'administer settings']);
->add([Middleware\Permissions::class, 'administer settings']);
$this->group('/stations', function () {
@ -81,7 +84,7 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Admin\StationsController::class.':deleteAction')
->setName('admin:stations:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'administer stations']);
})->add([Middleware\Permissions::class, 'administer stations']);
$this->group('/users', function () {
@ -100,15 +103,15 @@ return function(\Slim\App $app) {
$this->get('/login-as/{id}/{csrf}', Controller\Admin\UsersController::class.':impersonateAction')
->setName('admin:users:impersonate');
})->add([AzuraCast\Middleware\Permissions::class, 'administer users']);
})->add([Middleware\Permissions::class, 'administer users']);
// END /admin GROUP
})
->add(AzuraCast\Middleware\Module\Admin::class)
->add(AzuraCast\Middleware\EnableView::class)
->add([AzuraCast\Middleware\Permissions::class, 'view administration'])
->add(AzuraCast\Middleware\RequireLogin::class);
->add(Middleware\Module\Admin::class)
->add(Middleware\EnableView::class)
->add([Middleware\Permissions::class, 'view administration'])
->add(Middleware\RequireLogin::class);
$app->group('/api', function () {
@ -142,7 +145,7 @@ return function(\Slim\App $app) {
$this->map(['GET', 'POST'], '/notify', Controller\Api\InternalController::class.':notifyAction')
->setName('api:internal:notify');
})->add(AzuraCast\Middleware\GetStation::class);
})->add(Middleware\GetStation::class);
});
@ -151,13 +154,13 @@ return function(\Slim\App $app) {
$this->get('/stations', Controller\Api\Stations\IndexController::class.':listAction')
->setName('api:stations:list')
->add([AzuraCast\Middleware\RateLimit::class, 'api', 5, 2]);
->add([Middleware\RateLimit::class, 'api', 5, 2]);
$this->group('/station/{station}', function () {
$this->get('', Controller\Api\Stations\IndexController::class.':indexAction')
->setName('api:stations:index')
->add([AzuraCast\Middleware\RateLimit::class, 'api', 5, 2]);
->add([Middleware\RateLimit::class, 'api', 5, 2]);
$this->get('/nowplaying', Controller\Api\NowplayingController::class.':indexAction');
@ -167,33 +170,33 @@ return function(\Slim\App $app) {
$this->map(['GET', 'POST'], '/request/{media_id}', Controller\Api\RequestsController::class.':submitAction')
->setName('api:requests:submit')
->add([AzuraCast\Middleware\RateLimit::class, 'api', 5, 2]);
->add([Middleware\RateLimit::class, 'api', 5, 2]);
$this->get('/listeners', Controller\Api\ListenersController::class.':indexAction')
->setName('api:listeners:index')
->add([AzuraCast\Middleware\Permissions::class, 'view station reports', true]);
->add([Middleware\Permissions::class, 'view station reports', true]);
$this->get('/art/{media_id}', Controller\Api\Stations\MediaController::class.':artAction')
->setName('api:stations:media:art');
$this->post('/backend/{do}', Controller\Api\Stations\ServicesController::class.':backendAction')
->setName('api:stations:backend')
->add([AzuraCast\Middleware\Permissions::class, 'manage station broadcasting', true]);
->add([Middleware\Permissions::class, 'manage station broadcasting', true]);
$this->post('/frontend/{do}', Controller\Api\Stations\ServicesController::class.':frontendAction')
->setName('api:stations:frontend')
->add([AzuraCast\Middleware\Permissions::class, 'manage station broadcasting', true]);
->add([Middleware\Permissions::class, 'manage station broadcasting', true]);
$this->post('/restart', Controller\Api\Stations\ServicesController::class.':restartAction')
->setName('api:stations:restart')
->add([AzuraCast\Middleware\Permissions::class, 'manage station broadcasting', true]);
->add([Middleware\Permissions::class, 'manage station broadcasting', true]);
})->add(AzuraCast\Middleware\GetStation::class);
})->add(Middleware\GetStation::class);
// END /api GROUP
})
->add(AzuraCast\Middleware\Module\Api::class);
->add(Middleware\Module\Api::class);
$app->get('/', Controller\Frontend\IndexController::class.':indexAction')
->setName('home');
@ -231,16 +234,16 @@ return function(\Slim\App $app) {
if (!APP_IN_PRODUCTION) {
$this->any('/test', Controller\Frontend\UtilController::class.':testAction')
->setName('util:test')
->add(App\Middleware\DebugEcho::class);
->add(Middleware\DebugEcho::class);
}
})
->add(AzuraCast\Middleware\EnableView::class)
->add(AzuraCast\Middleware\RequireLogin::class);
->add(Middleware\EnableView::class)
->add(Middleware\RequireLogin::class);
$app->map(['GET', 'POST'], '/login', Controller\Frontend\AccountController::class.':loginAction')
->setName('account:login')
->add(AzuraCast\Middleware\EnableView::class);
->add(Middleware\EnableView::class);
$app->group('/setup', function () {
@ -260,7 +263,7 @@ return function(\Slim\App $app) {
->setName('setup:settings');
})
->add(AzuraCast\Middleware\EnableView::class);
->add(Middleware\EnableView::class);
$app->group('/public/{station}', function () {
@ -277,8 +280,8 @@ return function(\Slim\App $app) {
->setName('public:playlist');
})
->add(AzuraCast\Middleware\GetStation::class)
->add(AzuraCast\Middleware\EnableView::class);
->add(Middleware\GetStation::class)
->add(Middleware\EnableView::class);
$app->group('/station/{station}', function () {
@ -293,7 +296,7 @@ return function(\Slim\App $app) {
$this->get('/run', Controller\Stations\AutomationController::class.':runAction')
->setName('stations:automation:run');
})->add([AzuraCast\Middleware\Permissions::class, 'manage station automation', true]);
})->add([Middleware\Permissions::class, 'manage station automation', true]);
$this->group('/files', function () {
@ -322,8 +325,8 @@ return function(\Slim\App $app) {
->setName('stations:files:download');
})
->add(AzuraCast\Middleware\Module\StationFiles::class)
->add([AzuraCast\Middleware\Permissions::class, 'manage station media', true]);
->add(Middleware\Module\StationFiles::class)
->add([Middleware\Permissions::class, 'manage station media', true]);
$this->group('/playlists', function () {
@ -348,7 +351,7 @@ return function(\Slim\App $app) {
$this->get('/export/{id}[/{format}]', Controller\Stations\PlaylistsController::class.':exportAction')
->setName('stations:playlists:export');
})->add([AzuraCast\Middleware\Permissions::class, 'manage station media', true]);
})->add([Middleware\Permissions::class, 'manage station media', true]);
$this->group('/mounts', function () {
@ -367,7 +370,7 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Stations\MountsController::class.':deleteAction')
->setName('stations:mounts:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'manage station mounts', true]);
})->add([Middleware\Permissions::class, 'manage station mounts', true]);
$this->group('/profile', function () {
@ -376,7 +379,7 @@ return function(\Slim\App $app) {
$this->map(['GET', 'POST'], '/edit', Controller\Stations\ProfileController::class.':editAction')
->setName('stations:profile:edit')
->add([AzuraCast\Middleware\Permissions::class, 'manage station profile', true]);
->add([Middleware\Permissions::class, 'manage station profile', true]);
});
@ -388,7 +391,7 @@ return function(\Slim\App $app) {
$this->get('/delete/{request_id}/{csrf}', Controller\Stations\RequestsController::class.':deleteAction')
->setName('stations:requests:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'view station reports', true]);
})->add([Middleware\Permissions::class, 'view station reports', true]);
$this->group('/reports', function () {
@ -407,7 +410,7 @@ return function(\Slim\App $app) {
$this->map(['GET', 'POST'], '/listeners', Controller\Stations\ReportsController::class.':listenersAction')
->setName('stations:reports:listeners');
})->add([AzuraCast\Middleware\Permissions::class, 'view station reports', true]);
})->add([Middleware\Permissions::class, 'view station reports', true]);
$this->group('/streamers', function () {
@ -423,7 +426,7 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Stations\StreamersController::class.':deleteAction')
->setName('stations:streamers:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'manage station streamers', true]);
})->add([Middleware\Permissions::class, 'manage station streamers', true]);
$this->group('/webhooks', function () {
@ -442,15 +445,15 @@ return function(\Slim\App $app) {
$this->get('/delete/{id}/{csrf}', Controller\Stations\WebhooksController::class.':deleteAction')
->setName('stations:webhooks:delete');
})->add([AzuraCast\Middleware\Permissions::class, 'manage station web hooks', true]);
})->add([Middleware\Permissions::class, 'manage station web hooks', true]);
// END /stations GROUP
})
->add(AzuraCast\Middleware\Module\Stations::class)
->add([AzuraCast\Middleware\Permissions::class, 'view station management', true])
->add(AzuraCast\Middleware\GetStation::class)
->add(AzuraCast\Middleware\EnableView::class)
->add(AzuraCast\Middleware\RequireLogin::class);
->add(Middleware\Module\Stations::class)
->add([Middleware\Permissions::class, 'view station management', true])
->add(Middleware\GetStation::class)
->add(Middleware\EnableView::class)
->add(Middleware\RequireLogin::class);
};

View File

@ -41,7 +41,7 @@ return function (\Slim\Container $di, $settings) {
};
$di[\App\Config::class] = function () {
return new \App\Config(APP_INCLUDE_BASE . '/config');
return new \App\Config(__DIR__);
};
$di[\Doctrine\ORM\EntityManager::class] = function ($di) {
@ -50,7 +50,7 @@ return function (\Slim\Container $di, $settings) {
'autoGenerateProxies' => !APP_IN_PRODUCTION,
'proxyNamespace' => 'AppProxy',
'proxyPath' => APP_INCLUDE_TEMP . '/proxies',
'modelPath' => APP_INCLUDE_BASE . '/src/Entity',
'modelPath' => APP_INCLUDE_ROOT . '/src/Entity',
'conn' => [
'driver' => 'pdo_mysql',
'charset' => 'utf8mb4',
@ -110,7 +110,7 @@ return function (\Slim\Container $di, $settings) {
$config->setProxyDir($options['proxyPath']);
$config->setProxyNamespace($options['proxyNamespace']);
$config->setAutoGenerateProxyClasses(\Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS);
$config->setDefaultRepositoryClassName(\Entity\Repository\BaseRepository::class);
$config->setDefaultRepositoryClassName(\App\Entity\Repository\BaseRepository::class);
if (isset($options['conn']['debug']) && $options['conn']['debug']) {
$config->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
@ -134,31 +134,31 @@ return function (\Slim\Container $di, $settings) {
return $em->getConnection();
};
$di[\Entity\Repository\SettingsRepository::class] = function($di) {
$di[\App\Entity\Repository\SettingsRepository::class] = function($di) {
/** @var \Doctrine\ORM\EntityManager $em */
$em = $di[\Doctrine\ORM\EntityManager::class];
return $em->getRepository(Entity\Settings::class);
return $em->getRepository(App\Entity\Settings::class);
};
$di[\App\Auth::class] = function ($di) {
/** @var \Doctrine\ORM\EntityManager $em */
$em = $di[\Doctrine\ORM\EntityManager::class];
/** @var Entity\Repository\UserRepository $user_repo */
$user_repo = $em->getRepository(Entity\User::class);
/** @var App\Entity\Repository\UserRepository $user_repo */
$user_repo = $em->getRepository(App\Entity\User::class);
return new \App\Auth($di[\App\Session::class], $user_repo);
};
$di[\AzuraCast\Acl\StationAcl::class] = function ($di) {
$di[\App\Acl::class] = function ($di) {
/** @var \Doctrine\ORM\EntityManager $em */
$em = $di[\Doctrine\ORM\EntityManager::class];
/** @var Entity\Repository\RolePermissionRepository $permissions_repo */
$permissions_repo = $em->getRepository(Entity\RolePermission::class);
/** @var App\Entity\Repository\RolePermissionRepository $permissions_repo */
$permissions_repo = $em->getRepository(App\Entity\RolePermission::class);
return new \AzuraCast\Acl\StationAcl($permissions_repo);
return new \App\Acl($permissions_repo);
};
$di[\Redis::class] = $di->factory(function ($di) {
@ -178,8 +178,8 @@ return function (\Slim\Container $di, $settings) {
};
$di[\App\Url::class] = function ($di) {
/** @var Entity\Repository\SettingsRepository $settings_repo */
$settings_repo = $di[\Entity\Repository\SettingsRepository::class];
/** @var App\Entity\Repository\SettingsRepository $settings_repo */
$settings_repo = $di[\App\Entity\Repository\SettingsRepository::class];
$base_url = $settings_repo->getSetting('base_url', '');
$prefer_browser_url = (bool)$settings_repo->getSetting('prefer_browser_url', 0);
@ -215,14 +215,6 @@ return function (\Slim\Container $di, $settings) {
return new \App\Session;
};
$di[\App\Csrf::class] = function ($di) {
return new \App\Csrf($di[\App\Session::class]);
};
$di[\App\Flash::class] = function ($di) {
return new \App\Flash($di[\App\Session::class]);
};
$di[\InfluxDB\Database::class] = function ($di) {
$opts = [
'host' => (APP_INSIDE_DOCKER) ? 'influxdb' : 'localhost',
@ -255,7 +247,7 @@ return function (\Slim\Container $di, $settings) {
};
$di[\App\Mvc\View::class] = $di->factory(function(\Slim\Container $di) {
$view = new \App\Mvc\View(APP_INCLUDE_BASE . '/templates');
$view = new \App\Mvc\View(dirname(__DIR__) . '/resources/templates');
$view->setFileExtension('phtml');
$view->registerFunction('service', function($service) use ($di) {
@ -285,13 +277,16 @@ return function (\Slim\Container $di, $settings) {
return \App\Utilities::truncate_text($text, $length);
});
/** @var \App\Session $session */
$session = $di[\App\Session::class];
$view->addData([
'assets' => $di[\AzuraCast\Assets::class],
'assets' => $di[\App\Assets::class],
'auth' => $di[\App\Auth::class],
'acl' => $di[\AzuraCast\Acl\StationAcl::class],
'acl' => $di[\App\Acl::class],
'url' => $di[\App\Url::class],
'flash' => $di[\App\Flash::class],
'customization' => $di[\AzuraCast\Customization::class],
'flash' => $session->getFlash(),
'customization' => $di[\App\Customization::class],
'app_settings' => $di['app_settings'],
]);
@ -301,10 +296,7 @@ return function (\Slim\Container $di, $settings) {
$di[\App\Mvc\ErrorHandler::class] = function($di) {
return new \App\Mvc\ErrorHandler(
$di[\App\Url::class],
$di[\App\Session::class],
$di[\App\Flash::class],
$di[\App\Mvc\View::class],
$di[\AzuraCast\Acl\StationAcl::class],
$di[\App\Acl::class],
$di[\Monolog\Logger::class]
);
};
@ -325,10 +317,6 @@ return function (\Slim\Container $di, $settings) {
return $logger;
};
$di[\AzuraCast\Console\Application::class] = function($di) use ($settings) {
return \AzuraCast\Console\Application::create($di, $settings);
};
$di[MaxMind\Db\Reader::class] = function($di) {
$mmdb_path = dirname(APP_INCLUDE_ROOT).'/geoip/GeoLite2-City.mmdb';
return new MaxMind\Db\Reader($mmdb_path);
@ -338,15 +326,15 @@ return function (\Slim\Container $di, $settings) {
// AzuraCast-specific dependencies
//
$di[\AzuraCast\ApiUtilities::class] = function($di) {
return new \AzuraCast\ApiUtilities(
$di[\App\ApiUtilities::class] = function($di) {
return new \App\ApiUtilities(
$di[\Doctrine\ORM\EntityManager::class],
$di[\App\Url::class]
);
};
$di[\AzuraCast\Assets::class] = function ($di) {
$libraries = require('assets.php');
$di[\App\Assets::class] = function ($di) {
$libraries = require(__DIR__.'/assets.php');
$versioned_files = [];
$assets_file = APP_INCLUDE_STATIC . '/assets.json';
@ -354,42 +342,42 @@ return function (\Slim\Container $di, $settings) {
$versioned_files = json_decode(file_get_contents($assets_file), true);
}
return new \AzuraCast\Assets($libraries, $versioned_files, $di[\App\Url::class]);
return new \App\Assets($libraries, $versioned_files, $di[\App\Url::class]);
};
$di[\AzuraCast\Customization::class] = function ($di) {
return new \AzuraCast\Customization(
$di[\App\Customization::class] = function ($di) {
return new \App\Customization(
$di['app_settings'],
$di[\Entity\Repository\SettingsRepository::class],
$di[\App\Entity\Repository\SettingsRepository::class],
$di[\App\Url::class]
);
};
$di[\AzuraCast\RateLimit::class] = function($di) {
$di[\App\RateLimit::class] = function($di) {
/** @var \Redis $redis */
$redis = $di[\Redis::class];
$redis->select(3);
return new \AzuraCast\RateLimit($redis);
return new \App\RateLimit($redis);
};
// Radio management
$di->register(new \AzuraCast\Radio\RadioProvider);
$di->register(new \App\Radio\RadioProvider);
// Synchronization tasks
$di->register(new \AzuraCast\Sync\SyncProvider);
$di->register(new \App\Sync\SyncProvider);
// Web Hooks
$di->register(new \AzuraCast\Webhook\WebhookProvider);
$di->register(new \App\Webhook\WebhookProvider);
// Middleware
$di->register(new \AzuraCast\Middleware\MiddlewareProvider);
$di->register(new \App\Middleware\MiddlewareProvider);
// Controller groups
$di->register(new \Controller\Admin\AdminProvider);
$di->register(new \Controller\Api\ApiProvider);
$di->register(new \Controller\Frontend\FrontendProvider);
$di->register(new \Controller\Stations\StationsProvider);
$di->register(new \App\Controller\Admin\AdminProvider);
$di->register(new \App\Controller\Api\ApiProvider);
$di->register(new \App\Controller\Frontend\FrontendProvider);
$di->register(new \App\Controller\Stations\StationsProvider);
// Main Slim Application
$di['app'] = function ($di) {
@ -397,13 +385,16 @@ return function (\Slim\Container $di, $settings) {
$app = new \Slim\App($di);
// Get the current user entity object and assign it into the request if it exists.
$app->add(\AzuraCast\Middleware\GetCurrentUser::class);
$app->add(\App\Middleware\GetCurrentUser::class);
// Inject the session manager into the request object.
$app->add(\App\Middleware\EnableSession::class);
// Check HTTPS setting and enforce Content Security Policy accordingly.
$app->add(\AzuraCast\Middleware\EnforceSecurity::class);
$app->add(\App\Middleware\EnforceSecurity::class);
// Remove trailing slash from all URLs when routing.
$app->add(\AzuraCast\Middleware\RemoveSlashes::class);
$app->add(\App\Middleware\RemoveSlashes::class);
// Load routes
call_user_func(include(__DIR__.'/routes.php'), $app);

View File

@ -1,7 +1,7 @@
<?php $this->layout('main', ['title' => __('Custom Branding')]); ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets
->load('codemirror_css');
?>
@ -25,4 +25,4 @@ $assets
});
</script>
<?=$form->render() ?>
<?=$form->render() ?>

View File

@ -1,8 +1,8 @@
<?php $this->layout('main', ['title' => __('Dashboard'), 'manual' => true]); ?>
<?php
/** @var \AzuraCast\Customization $customization */
/** @var \AzuraCast\Assets $assets */
/** @var \App\Customization $customization */
/** @var \App\Assets $assets */
$assets
->load('vue')
->load('radio');
@ -212,4 +212,4 @@ function loadNowPlaying() {
setTimeout(loadNowPlaying, 15000);
});
}
</script>
</script>

View File

@ -3,7 +3,7 @@
<?php $this->layout('minimal', ['page_class' => 'embed', 'title' => $this->e($station->getName()), 'hide_footer' => true]) ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets
->load('vue')
->load('radio');
@ -36,4 +36,4 @@ $(function() {
loadNowPlaying();
});
</script>
</script>

View File

@ -3,7 +3,7 @@
<?php $this->layout('minimal', ['page_class' => 'embed', 'title' => $this->e($station->getName()), 'hide_footer' => true]) ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets->load('bootgrid');
?>
@ -59,4 +59,4 @@ $(function() {
});
});
});
</script>
</script>

View File

@ -3,7 +3,7 @@
<?php $this->layout('minimal', ['title' => $this->e($station->getName()), 'page_class' => 'public-page-content']) ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets
->load('vue')
->load('radio')
@ -184,4 +184,4 @@ request_dialog.on('show.bs.modal', function (event) {
}
});
</script>
</script>

View File

@ -1,5 +1,5 @@
<?php
/** @var \AzuraCast\Customization $customization */
/** @var \App\Customization $customization */
$vue_data_model = [
'np' => [

View File

@ -1,7 +1,7 @@
<?php $this->layout('minimal', ['title' => 'Set Up', 'page_class' => 'login-content']) ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets
->load('zxcvbn');
?>
@ -32,4 +32,4 @@ $assets
<button type="submit" role="button" title="<?=__('Create Account') ?>" class="btn btn-login btn-primary btn-float"><i class="zmdi zmdi-arrow-forward"></i></button>
</form>
</div>
</div>
</div>

View File

@ -3,11 +3,11 @@
/**
* @var \League\Plates\Template\Template $this
* @var \App\Auth $auth
* @var \AzuraCast\Acl\StationAcl $acl
* @var \App\Acl $acl
* @var \App\Url $url
* @var \App\Flash $flash
* @var \AzuraCast\Customization $customization
* @var \AzuraCast\Assets $assets
* @var \App\Session\Flash $flash
* @var \App\Customization $customization
* @var \App\Assets $assets
* @var array $app_settings
*/
?>
@ -128,7 +128,7 @@ var APP_ContentPath = '<?=$url->content('') ?>';
</section>
<footer id="footer" <?php if (empty($sidebar)): ?>class="footer-alt"<?php endif; ?> role="contentinfo">
<?=sprintf(__('Powered by %s'), '<a href="https://azuracast.com/" target="_blank">'.$app_settings['name'].'</a>'.' '.\AzuraCast\Version::getVersionText().' '.(APP_INSIDE_DOCKER ? '(Docker)' : '(Traditional)')) ?><br>
<?=sprintf(__('Powered by %s'), '<a href="https://azuracast.com/" target="_blank">'.$app_settings['name'].'</a>'.' '.\App\Version::getVersionText().' '.(APP_INSIDE_DOCKER ? '(Docker)' : '(Traditional)')) ?><br>
PHP <?=\PHP_VERSION ?>, SlimPHP 3
</footer>
@ -146,4 +146,4 @@ var APP_ContentPath = '<?=$url->content('') ?>';
</script>
<?php endif; ?>
</body>
</html>
</html>

View File

@ -3,11 +3,11 @@
/**
* @var \League\Plates\Template\Template $this
* @var \App\Auth $auth
* @var \AzuraCast\Acl\StationAcl $acl
* @var \App\Acl $acl
* @var \App\Url $url
* @var \App\Flash $flash
* @var \AzuraCast\Customization $customization
* @var \AzuraCast\Assets $assets
* @var \App\Session\Flash $flash
* @var \App\Customization $customization
* @var \App\Assets $assets
* @var array $app_settings
*/
?>
@ -78,4 +78,4 @@ $assets
<?=$customization->getCustomPublicJs() ?>
</script>
</body>
</html>
</html>

View File

@ -1,7 +1,7 @@
<?php $this->layout('main', ['title' => __('Music Files'), 'manual' => true, 'page_class' => 'page-file-manager']) ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets
->load('vue')
->load('radio')
@ -451,4 +451,4 @@ $(function() {
return pos ? [parseInt(d/10),".",d%10," ",s[pos]].join('') : bytes + ' bytes';
}
})
</script>
</script>

View File

@ -1,7 +1,7 @@
<?php $this->layout('main', ['title' => __('Station Center'), 'manual' => true]) ?>
<?php
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets
->load('highcharts')
->load('highcharts_theme_'.$customization->getTheme());
@ -173,4 +173,4 @@ $(function () {
</div>
</section>
</div>
</div>
</div>

View File

@ -1,9 +1,9 @@
<?php
use Entity\StationPlaylist;
use App\Entity\StationPlaylist;
$this->layout('main', ['title' => __('Playlists'), 'manual' => true]);
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets->load('fullcalendar');
?>
@ -136,4 +136,4 @@ $(function() {
}
});
});
</script>
</script>

View File

@ -3,7 +3,7 @@ use Entity\StationPlaylist;
$this->layout('main', ['title' => __('Reorder Playlist'), 'manual' => true]);
/** @var \AzuraCast\Assets $assets */
/** @var \App\Assets $assets */
$assets->load('jquery-sortable');
?>
@ -60,4 +60,4 @@ $(function() {
}
});
});
</script>
</script>

Some files were not shown because too many files have changed in this diff Show More