From 3aad2bfca4967d0a9ee33f9d4805bece1c36b151 Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Tue, 12 Apr 2022 21:41:51 +0200 Subject: [PATCH] Week 3: Add Octoleo CMS Stable --- week-03/project/README.md | 28 + .../project/administrator/includes/app.php | 106 +- .../administrator/includes/defines.php | 31 +- .../administrator/includes/framework.php | 113 +- week-03/project/administrator/index.php | 31 +- week-03/project/composer.json | 71 + week-03/project/composer.lock | 5392 +++++++++++++++++ week-03/project/includes/app.php | 104 +- week-03/project/includes/defines.php | 29 +- week-03/project/includes/framework.php | 114 +- week-03/project/index.php | 21 +- week-03/project/installation/includes/app.php | 31 + .../project/installation/includes/defines.php | 23 + .../installation/includes/framework.php | 41 + week-03/project/installation/index.php | 35 + week-03/project/libraries/bootstrap.php | 74 +- week-03/project/libraries/loader.php | 233 +- .../src/Application/AdminApplication.php | 13 +- .../Application/IdentityAwareInterface.php | 57 + .../src/Application/IdentityAwareTrait.php | 41 +- .../SessionMessageAwareInterface.php | 44 + .../Application/SessionMessageAwareTrait.php | 88 + .../src/Application/SiteApplication.php | 9 +- .../libraries/src/Asset/MixPathPackage.php | 3 +- .../libraries/src/Autoload/ClassLoader.php | 10 +- .../src/Controller/DashboardController.php | 83 +- .../src/Controller/HomepageController.php | 40 +- .../src/Controller/LoginController.php | 47 +- .../src/Controller/PageController.php | 52 +- .../src/Controller/WrongCmsController.php | 14 +- week-03/project/libraries/src/Date/Date.php | 57 +- .../src/EventListener/ErrorSubscriber.php | 19 +- week-03/project/libraries/src/Factory.php | 794 +-- .../libraries/src/Filter/InputFilter.php | 6 +- .../libraries/src/Model/DashboardModel.php | 167 +- .../project/libraries/src/Model/PageModel.php | 169 +- .../src/Renderer/ApplicationContext.php | 5 +- .../src/Renderer/FrameworkExtension.php | 3 +- .../src/Renderer/FrameworkTwigRuntime.php | 5 +- .../src/Service/AdminApplicationProvider.php | 642 +- .../src/Service/ConfigurationProvider.php | 30 +- .../libraries/src/Service/EventProvider.php | 15 +- .../libraries/src/Service/HttpProvider.php | 15 +- .../libraries/src/Service/LoggingProvider.php | 7 +- .../libraries/src/Service/SessionProvider.php | 388 +- .../src/Service/SiteApplicationProvider.php | 588 +- .../src/Service/TemplatingProvider.php | 21 +- .../libraries/src/Service/UserProvider.php | 71 +- .../libraries/src/Session/MetadataManager.php | 76 +- .../libraries/src/String/PunycodeHelper.php | 4 +- week-03/project/libraries/src/User/User.php | 924 +-- .../libraries/src/User/UserFactory.php | 428 +- .../src/User/UserFactoryInterface.php | 19 +- .../src/View/Admin/DashboardHtmlView.php | 84 +- .../libraries/src/View/Page/PageHtmlView.php | 77 +- week-03/project/logs/framework.log | 0 week-03/project/logs/index.html | 1 + week-03/project/octoconfig.php.example | 95 + .../project/templates/admin/dashboard.twig | 20 + week-03/project/templates/admin/edit.twig | 37 + .../project/templates/admin/exception.twig | 29 + week-03/project/templates/admin/footer.twig | 9 + week-03/project/templates/admin/header.twig | 43 + week-03/project/templates/admin/index.html | 1 + week-03/project/templates/admin/index.twig | 13 + week-03/project/templates/admin/items.twig | 52 + week-03/project/templates/admin/login.twig | 18 + week-03/project/templates/admin/menus.twig | 50 + week-03/project/templates/admin/nav.twig | 19 + week-03/project/templates/admin/signup.twig | 21 + week-03/project/templates/admin/users.twig | 32 + week-03/project/templates/index.html | 1 + week-03/project/templates/site/exception.twig | 27 + week-03/project/templates/site/footer.twig | 9 + week-03/project/templates/site/header.twig | 43 + week-03/project/templates/site/homepage.twig | 10 + week-03/project/templates/site/index.html | 1 + week-03/project/templates/site/index.twig | 12 + week-03/project/templates/site/nav.twig | 28 + week-03/project/templates/site/page.twig | 14 + .../templates/system/build_incomplete.html | 34 + .../templates/system/incompatible.html | 27 + week-03/project/templates/system/index.html | 1 + .../templates/system/install_notice.html | 36 + week-03/project/tmp/index.html | 1 + 85 files changed, 8100 insertions(+), 4176 deletions(-) create mode 100644 week-03/project/README.md create mode 100644 week-03/project/composer.json create mode 100644 week-03/project/composer.lock create mode 100644 week-03/project/installation/includes/app.php create mode 100644 week-03/project/installation/includes/defines.php create mode 100644 week-03/project/installation/includes/framework.php create mode 100644 week-03/project/installation/index.php create mode 100644 week-03/project/libraries/src/Application/IdentityAwareInterface.php create mode 100644 week-03/project/libraries/src/Application/SessionMessageAwareInterface.php create mode 100644 week-03/project/libraries/src/Application/SessionMessageAwareTrait.php create mode 100644 week-03/project/logs/framework.log create mode 100644 week-03/project/logs/index.html create mode 100644 week-03/project/octoconfig.php.example create mode 100644 week-03/project/templates/admin/dashboard.twig create mode 100644 week-03/project/templates/admin/edit.twig create mode 100644 week-03/project/templates/admin/exception.twig create mode 100644 week-03/project/templates/admin/footer.twig create mode 100644 week-03/project/templates/admin/header.twig create mode 100644 week-03/project/templates/admin/index.html create mode 100644 week-03/project/templates/admin/index.twig create mode 100644 week-03/project/templates/admin/items.twig create mode 100644 week-03/project/templates/admin/login.twig create mode 100644 week-03/project/templates/admin/menus.twig create mode 100644 week-03/project/templates/admin/nav.twig create mode 100644 week-03/project/templates/admin/signup.twig create mode 100644 week-03/project/templates/admin/users.twig create mode 100644 week-03/project/templates/index.html create mode 100644 week-03/project/templates/site/exception.twig create mode 100644 week-03/project/templates/site/footer.twig create mode 100644 week-03/project/templates/site/header.twig create mode 100644 week-03/project/templates/site/homepage.twig create mode 100644 week-03/project/templates/site/index.html create mode 100644 week-03/project/templates/site/index.twig create mode 100644 week-03/project/templates/site/nav.twig create mode 100644 week-03/project/templates/site/page.twig create mode 100644 week-03/project/templates/system/build_incomplete.html create mode 100644 week-03/project/templates/system/incompatible.html create mode 100644 week-03/project/templates/system/index.html create mode 100644 week-03/project/templates/system/install_notice.html create mode 100644 week-03/project/tmp/index.html diff --git a/week-03/project/README.md b/week-03/project/README.md new file mode 100644 index 0000000..73c3ae1 --- /dev/null +++ b/week-03/project/README.md @@ -0,0 +1,28 @@ +# Login To Admin Area or Create an Account + +This is the basic basic dependency injection CMS + +## To install this CMS + +1. Import the SQL tables into your database found in /sql/install.sql +2. Copy the /octoconfig.php.example file to /octoconfig.php +3. Update the /octoconfig.php to reflect your CMS details +4. Remove the installation folder from you root directory + +## To install all composer libraries + +0. Make sure you have [composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos) installed on your system. +1. In your terminal go to the root folder of your Octoleo website where you will find the composer.json file. +2. Run the following command composer install to install all PHP packages. + +## To create an Account + +1. Open [hostname:]/administrator +2. Click on link that says create Account +3. Fill in your details [done] + +## To login to admin/staff area + +1. Open [hostname:]/administrator +2. Add you username and password +3. Click login [done] diff --git a/week-03/project/administrator/includes/app.php b/week-03/project/administrator/includes/app.php index ecdaf99..0f10dc1 100644 --- a/week-03/project/administrator/includes/app.php +++ b/week-03/project/administrator/includes/app.php @@ -1,63 +1,97 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; - -// Saves the start time and memory usage. -$startTime = microtime(1); -$startMem = memory_get_usage(); +defined('_LEXEC') or die; +// Option to override defines from root folder +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L15 if (file_exists(dirname(__DIR__) . '/defines.php')) { include_once dirname(__DIR__) . '/defines.php'; } -if (!defined('_JDEFINES')) +// Load the default defines +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L20 +if (!defined('_LDEFINES')) { - define('JPATH_BASE', dirname(__DIR__)); - require_once JPATH_BASE . '/includes/defines.php'; + define('LPATH_BASE', dirname(__DIR__)); + require_once LPATH_BASE . '/includes/defines.php'; } // Check for presence of vendor dependencies not included in the git repository -if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_ROOT . '/media/vendor')) +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L26 +if (!file_exists(LPATH_LIBRARIES . '/vendor/autoload.php')) { - echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html'); + echo file_get_contents(LPATH_ROOT . '/templates/system/build_incomplete.html'); exit; } -require_once JPATH_BASE . '/includes/framework.php'; +// Load configuration (or install) +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L34 +require_once LPATH_BASE . '/includes/framework.php'; -// Set profiler start time and memory usage and mark afterLoad in the profiler. -JDEBUG ? \Joomla\CMS\Profiler\Profiler::getInstance('Application')->setStart($startTime, $startMem)->mark('afterLoad') : null; +// Wrap in a try/catch so we can display an error if need be +try +{ + $container = (new Joomla\DI\Container) + ->registerServiceProvider(new Octoleo\CMS\Service\ConfigurationProvider(LPATH_CONFIGURATION . '/octoconfig.php')) + ->registerServiceProvider(new Octoleo\CMS\Service\SessionProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\UserProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\AdminApplicationProvider) + ->registerServiceProvider(new Joomla\Database\Service\DatabaseProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\EventProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\HttpProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\LoggingProvider) + ->registerServiceProvider(new Joomla\Preload\Service\PreloadProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\TemplatingProvider); -// Boot the DI container -$container = \Joomla\CMS\Factory::getContainer(); + // Alias the web application to Octoleo's base application class as this is the primary application for the environment + $container->alias(Joomla\Application\AbstractApplication::class, Joomla\Application\AbstractWebApplication::class); -/* - * Alias the session service keys to the web session service as that is the primary session backend for this application - * - * In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects - * is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered - * deprecated to be removed when the class name alias is removed as well. - */ -$container->alias('session.web', 'session.web.administrator') - ->alias('session', 'session.web.administrator') - ->alias('JSession', 'session.web.administrator') - ->alias(\Joomla\CMS\Session\Session::class, 'session.web.administrator') - ->alias(\Joomla\Session\Session::class, 'session.web.administrator') - ->alias(\Joomla\Session\SessionInterface::class, 'session.web.administrator'); + // Alias the web logger to the PSR-3 interface as this is the primary logger for the environment + $container->alias(Monolog\Logger::class, 'monolog.logger.application.web') + ->alias(Psr\Log\LoggerInterface::class, 'monolog.logger.application.web'); +} +catch (\Throwable $e) +{ + error_log($e); -// Instantiate the application. -$app = $container->get(\Joomla\CMS\Application\AdministratorApplication::class); + header('HTTP/1.1 500 Internal Server Error', null, 500); + echo 'Container Initialization Error

Container Initialization Error

An error occurred while creating the DI container: ' . $e->getMessage() . '

'; -// Set the application as global app -\Joomla\CMS\Factory::$application = $app; + exit(1); +} -// Execute the application. -$app->execute(); +// Execute the application +// source: https://github.com/joomla/framework.joomla.org/blob/master/www/index.php#L85 +try +{ + $app = $container->get(Joomla\Application\AbstractApplication::class); + // Set the application as global app + \Octoleo\CMS\Factory::$application = $app; + // Execute the application. + $app->execute(); +} +catch (\Throwable $e) +{ + error_log($e); + + if (!headers_sent()) + { + header('HTTP/1.1 500 Internal Server Error', null, 500); + header('Content-Type: text/html; charset=utf-8'); + } + + echo 'Application Error

Application Error

An error occurred while executing the application: ' . $e->getMessage() . '

'; + + exit(1); +} +// I am just playing around... ((ewɘ))yn purring \ No newline at end of file diff --git a/week-03/project/administrator/includes/defines.php b/week-03/project/administrator/includes/defines.php index e43728b..ed34049 100644 --- a/week-03/project/administrator/includes/defines.php +++ b/week-03/project/administrator/includes/defines.php @@ -1,27 +1,24 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; +defined('_LEXEC') or die; // Global definitions -$parts = explode(DIRECTORY_SEPARATOR, JPATH_BASE); +$parts = explode(DIRECTORY_SEPARATOR, LPATH_BASE); array_pop($parts); -// Defines -define('JPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts)); -define('JPATH_SITE', JPATH_ROOT); -define('JPATH_CONFIGURATION', JPATH_ROOT); -define('JPATH_ADMINISTRATOR', JPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator'); -define('JPATH_LIBRARIES', JPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries'); -define('JPATH_PLUGINS', JPATH_ROOT . DIRECTORY_SEPARATOR . 'plugins'); -define('JPATH_INSTALLATION', JPATH_ROOT . DIRECTORY_SEPARATOR . 'installation'); -define('JPATH_THEMES', JPATH_BASE . DIRECTORY_SEPARATOR . 'templates'); -define('JPATH_CACHE', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'cache'); -define('JPATH_MANIFESTS', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'manifests'); -define('JPATH_API', JPATH_ROOT . DIRECTORY_SEPARATOR . 'api'); -define('JPATH_CLI', JPATH_ROOT . DIRECTORY_SEPARATOR . 'cli'); +// Defines. +define('LPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts)); +define('LPATH_SITE', LPATH_ROOT); +define('LPATH_CONFIGURATION', LPATH_ROOT); +define('LPATH_ADMINISTRATOR', LPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator'); +define('LPATH_LIBRARIES', LPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries'); +define('LPATH_INSTALLATION', LPATH_ROOT . DIRECTORY_SEPARATOR . 'installation'); +define('LPATH_TEMPLATES', LPATH_ROOT . DIRECTORY_SEPARATOR . 'templates/admin'); diff --git a/week-03/project/administrator/includes/framework.php b/week-03/project/administrator/includes/framework.php index 10cf971..649f4b4 100644 --- a/week-03/project/administrator/includes/framework.php +++ b/week-03/project/administrator/includes/framework.php @@ -1,29 +1,30 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; - -use Joomla\CMS\Version; -use Joomla\Utilities\IpHelper; +defined('_LEXEC') or die; // System includes -require_once JPATH_LIBRARIES . '/bootstrap.php'; +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/framework.php#L14 +require_once LPATH_LIBRARIES . '/bootstrap.php'; -// Installation check, and check on removal of the install directory. -if (!file_exists(JPATH_CONFIGURATION . '/configuration.php') - || (filesize(JPATH_CONFIGURATION . '/configuration.php') < 10) - || (file_exists(JPATH_INSTALLATION . '/index.php') && (false === (new Version)->isInDevelopmentState()))) +// Installation check, and check on removal of the installation directory. +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/framework.php#L17 +if (!file_exists(LPATH_CONFIGURATION . '/octoconfig.php') + || (filesize(LPATH_CONFIGURATION . '/octoconfig.php') < 10) + || (file_exists(LPATH_INSTALLATION . '/index.php'))) { - if (file_exists(JPATH_INSTALLATION . '/index.php')) + if (file_exists(LPATH_INSTALLATION . '/index.php')) { header('Location: ../installation/index.php'); - exit(); + exit; } else { @@ -32,89 +33,3 @@ if (!file_exists(JPATH_CONFIGURATION . '/configuration.php') exit; } } - -// Pre-Load configuration. Don't remove the Output Buffering due to BOM issues, see JCode 26026 -ob_start(); -require_once JPATH_CONFIGURATION . '/configuration.php'; -ob_end_clean(); - -// System configuration. -$config = new JConfig; - -// Set the error_reporting, and adjust a global Error Handler -switch ($config->error_reporting) -{ - case 'default': - case '-1': - - break; - - case 'none': - case '0': - error_reporting(0); - - break; - - case 'simple': - error_reporting(E_ERROR | E_WARNING | E_PARSE); - ini_set('display_errors', 1); - - break; - - case 'maximum': - case 'development': // <= Stays for backward compatibility, @TODO: can be removed in 5.0 - error_reporting(E_ALL); - ini_set('display_errors', 1); - - break; - - default: - error_reporting($config->error_reporting); - ini_set('display_errors', 1); - - break; -} - -define('JDEBUG', $config->debug); - -// Check deprecation logging -if (empty($config->log_deprecated)) -{ - // Reset handler for E_USER_DEPRECATED - set_error_handler(null, E_USER_DEPRECATED); -} -else -{ - // Make sure handler for E_USER_DEPRECATED is registered - set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED); -} - -if (JDEBUG || $config->error_reporting === 'maximum') -{ - // Set new Exception handler with debug enabled - $errorHandler->setExceptionHandler( - [ - new \Symfony\Component\ErrorHandler\ErrorHandler(null, true), - 'renderException' - ] - ); -} - -/** - * Correctly set the allowing of IP Overrides if behind a trusted proxy/load balancer. - * - * We need to do this as high up the stack as we can, as the default in \Joomla\Utilities\IpHelper is to - * $allowIpOverride = true which is the wrong default for a generic site NOT behind a trusted proxy/load balancer. - */ -if (property_exists($config, 'behind_loadbalancer') && $config->behind_loadbalancer == 1) -{ - // If Joomla is configured to be behind a trusted proxy/load balancer, allow HTTP Headers to override the REMOTE_ADDR - IpHelper::setAllowIpOverrides(true); -} -else -{ - // We disable the allowing of IP overriding using headers by default. - IpHelper::setAllowIpOverrides(false); -} - -unset($config); diff --git a/week-03/project/administrator/index.php b/week-03/project/administrator/index.php index 6514d2f..5c9f04b 100644 --- a/week-03/project/administrator/index.php +++ b/week-03/project/administrator/index.php @@ -1,34 +1,35 @@ + * @created 3rd April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ // NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/index.php#L9 -// Define the application's minimum supported PHP version as a constant so it can be referenced within the application. -define('JOOMLA_MINIMUM_PHP', '7.2.5'); +// Define the application's minimum supported PHP version as a constant, so it can be referenced within the application. +define('OCTOLEO_MINIMUM_PHP', '7.2.5'); -if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) +if (version_compare(PHP_VERSION, OCTOLEO_MINIMUM_PHP, '<')) { die( - str_replace( - '{{phpversion}}', - JOOMLA_MINIMUM_PHP, - file_get_contents(dirname(__FILE__) . '/../templates/system/incompatible.html') - ) + str_replace( + '{{phpversion}}', + OCTOLEO_MINIMUM_PHP, + file_get_contents(dirname(__FILE__) . '/../templates/system/incompatible.html') + ) ); } /** * Constant that is checked in included files to prevent direct access. - * define() is used rather than "const" to not error for PHP 5.2 and lower */ -define('_JEXEC', 1); +define('_LEXEC', 1); -// Run the application - All executable code should be triggered through this file +// We must setup some house rules, since we can't have all +// this code just doing what it wants can we.... <>yn growling require_once dirname(__FILE__) . '/includes/app.php'; - - diff --git a/week-03/project/composer.json b/week-03/project/composer.json new file mode 100644 index 0000000..7f3b12b --- /dev/null +++ b/week-03/project/composer.json @@ -0,0 +1,71 @@ +{ + "name": "octoleo/cms", + "type": "project", + "description": "Octoleo CMS", + "keywords": [ + "octoleo", + "cms" + ], + "homepage": "https://github.com/mychamplain", + "license": "GPL-2.0-or-later", + "config": { + "optimize-autoloader": true, + "platform": { + "php": "7.2.5" + }, + "vendor-dir": "libraries/vendor", + "github-protocols": ["https"], + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "autoload": { + "psr-4": { + "Octoleo\\CMS\\": "libraries/src/" + } + }, + "require": { + "php": "^7.2.5", + "joomla/application": "~2.0", + "joomla/archive": "~2.0", + "joomla/authentication": "~2.0", + "joomla/console": "~2.0", + "joomla/controller": "~2.0", + "joomla/crypt": "~2.0", + "joomla/data": "~2.0", + "joomla/database": "~2.0", + "joomla/di": "~2.0", + "joomla/event": "~2.0", + "joomla/filter": "~2.0", + "joomla/filesystem": "~2.0", + "joomla/http": "~2.0", + "joomla/input": "~2.0", + "joomla/model": "~2.0", + "joomla/preload": "~2.0", + "joomla/ldap": "~2.0", + "joomla/oauth1": "~2.0", + "joomla/oauth2": "~2.0", + "joomla/registry": "~2.0", + "joomla/renderer": "~2.0", + "joomla/router": "~2.0", + "joomla/session": "~2.0", + "joomla/string": "~2.0", + "joomla/uri": "~2.0", + "joomla/utilities": "~2.0", + "algo26-matthias/idna-convert": "~3.0", + "joomla/view": "~2.0", + "laminas/laminas-diactoros": "^2.3", + "monolog/monolog": "^2.1", + "psr/link": "^1.0", + "ramsey/uuid": "^4.0.1", + "robmorgan/phinx": "^0.12.3", + "defuse/php-encryption": "^2.0", + "symfony/asset": "^5.1.2", + "symfony/process": "^5.1.2", + "symfony/web-link": "^5.1.2", + "symfony/yaml": "^5.1.2", + "theiconic/php-ga-measurement-protocol": "^2.7.2", + "twig/twig": "^2.13", + "phpmailer/phpmailer": "~6.0" + } +} \ No newline at end of file diff --git a/week-03/project/composer.lock b/week-03/project/composer.lock new file mode 100644 index 0000000..ed50632 --- /dev/null +++ b/week-03/project/composer.lock @@ -0,0 +1,5392 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "3442722df6289914de45ee254d28bada", + "packages": [ + { + "name": "algo26-matthias/idna-convert", + "version": "v3.0.5", + "source": { + "type": "git", + "url": "https://github.com/algo26-matthias/idna-convert.git", + "reference": "9cbcfa17ecfed54387ca2ed29acb2773f1870a5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/algo26-matthias/idna-convert/zipball/9cbcfa17ecfed54387ca2ed29acb2773f1870a5e", + "reference": "9cbcfa17ecfed54387ca2ed29acb2773f1870a5e", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "jakeasmith/http_build_url": "^1", + "php": ">=7.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0 || ^9.0" + }, + "suggest": { + "ext-iconv": "Install ext/iconv for using input / output other than UTF-8 or ISO-8859-1", + "ext-mbstring": "Install ext/mbstring for using input / output other than UTF-8 or ISO-8859-1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Algo26\\IdnaConvert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1+" + ], + "authors": [ + { + "name": "Matthias Sommerfeld", + "email": "matthias.sommerfeld@algo26.de", + "role": "Developer" + } + ], + "description": "A library for encoding and decoding internationalized domain names", + "homepage": "http://idnaconv.net/", + "keywords": [ + "idn", + "idna", + "php" + ], + "support": { + "issues": "https://github.com/algo26-matthias/idna-convert/issues", + "source": "https://github.com/algo26-matthias/idna-convert/tree/v3.0.5" + }, + "time": "2020-10-05T05:49:30+00:00" + }, + { + "name": "brick/math", + "version": "0.9.3", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", + "vimeo/psalm": "4.9.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.9.3" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/brick/math", + "type": "tidelift" + } + ], + "time": "2021-08-15T20:50:18+00:00" + }, + { + "name": "cakephp/core", + "version": "4.3.7", + "source": { + "type": "git", + "url": "https://github.com/cakephp/core.git", + "reference": "499f17738d40560ec077d7d2039c9af4969c6b17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/core/zipball/499f17738d40560ec077d7d2039c9af4969c6b17", + "reference": "499f17738d40560ec077d7d2039c9af4969c6b17", + "shasum": "" + }, + "require": { + "cakephp/utility": "^4.0", + "php": ">=7.2.0" + }, + "suggest": { + "cakephp/cache": "To use Configure::store() and restore().", + "cakephp/event": "To use PluginApplicationInterface or plugin applications.", + "league/container": "To use Container and ServiceProvider classes" + }, + "type": "library", + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Cake\\Core\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/core/graphs/contributors" + } + ], + "description": "CakePHP Framework Core classes", + "homepage": "https://cakephp.org", + "keywords": [ + "cakephp", + "core", + "framework" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/cakephp/issues", + "source": "https://github.com/cakephp/core" + }, + "time": "2022-03-10T13:13:51+00:00" + }, + { + "name": "cakephp/database", + "version": "4.3.7", + "source": { + "type": "git", + "url": "https://github.com/cakephp/database.git", + "reference": "0a32584763af097eaaba96cf062e2d5d31e6ea3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/database/zipball/0a32584763af097eaaba96cf062e2d5d31e6ea3b", + "reference": "0a32584763af097eaaba96cf062e2d5d31e6ea3b", + "shasum": "" + }, + "require": { + "cakephp/core": "^4.0", + "cakephp/datasource": "^4.0", + "php": ">=7.2.0" + }, + "suggest": { + "cakephp/i18n": "If you are using locale-aware datetime formats or Chronos types." + }, + "type": "library", + "autoload": { + "psr-4": { + "Cake\\Database\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/database/graphs/contributors" + } + ], + "description": "Flexible and powerful Database abstraction library with a familiar PDO-like API", + "homepage": "https://cakephp.org", + "keywords": [ + "abstraction", + "cakephp", + "database", + "database abstraction", + "pdo" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/cakephp/issues", + "source": "https://github.com/cakephp/database" + }, + "time": "2022-03-12T14:25:33+00:00" + }, + { + "name": "cakephp/datasource", + "version": "4.3.7", + "source": { + "type": "git", + "url": "https://github.com/cakephp/datasource.git", + "reference": "d9e88333a8c6832fddfc38d092f30efcab8cd34d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/datasource/zipball/d9e88333a8c6832fddfc38d092f30efcab8cd34d", + "reference": "d9e88333a8c6832fddfc38d092f30efcab8cd34d", + "shasum": "" + }, + "require": { + "cakephp/core": "^4.0", + "php": ">=7.2.0", + "psr/log": "^1.0 || ^2.0", + "psr/simple-cache": "^1.0 || ^2.0" + }, + "suggest": { + "cakephp/cache": "If you decide to use Query caching.", + "cakephp/collection": "If you decide to use ResultSetInterface.", + "cakephp/utility": "If you decide to use EntityTrait." + }, + "type": "library", + "autoload": { + "psr-4": { + "Cake\\Datasource\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/datasource/graphs/contributors" + } + ], + "description": "Provides connection managing and traits for Entities and Queries that can be reused for different datastores", + "homepage": "https://cakephp.org", + "keywords": [ + "cakephp", + "connection management", + "datasource", + "entity", + "query" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/cakephp/issues", + "source": "https://github.com/cakephp/datasource" + }, + "time": "2022-03-04T04:39:56+00:00" + }, + { + "name": "cakephp/utility", + "version": "4.3.7", + "source": { + "type": "git", + "url": "https://github.com/cakephp/utility.git", + "reference": "3d352060ca3e49c81c3fd2bdb092ee345d8f4e38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/utility/zipball/3d352060ca3e49c81c3fd2bdb092ee345d8f4e38", + "reference": "3d352060ca3e49c81c3fd2bdb092ee345d8f4e38", + "shasum": "" + }, + "require": { + "cakephp/core": "^4.0", + "php": ">=7.2.0" + }, + "suggest": { + "ext-intl": "To use Text::transliterate() or Text::slug()", + "lib-ICU": "To use Text::transliterate() or Text::slug()" + }, + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Cake\\Utility\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/utility/graphs/contributors" + } + ], + "description": "CakePHP Utility classes such as Inflector, String, Hash, and Security", + "homepage": "https://cakephp.org", + "keywords": [ + "cakephp", + "hash", + "inflector", + "security", + "string", + "utility" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/cakephp/issues", + "source": "https://github.com/cakephp/utility" + }, + "time": "2022-01-28T18:02:00+00:00" + }, + { + "name": "composer/ca-bundle", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.3.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-10-28T20:44:15+00:00" + }, + { + "name": "defuse/php-encryption", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/defuse/php-encryption.git", + "reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/77880488b9954b7884c25555c2a0ea9e7053f9d2", + "reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "paragonie/random_compat": ">= 2", + "php": ">=5.6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4|^5|^6|^7|^8|^9" + }, + "bin": [ + "bin/generate-defuse-key" + ], + "type": "library", + "autoload": { + "psr-4": { + "Defuse\\Crypto\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Hornby", + "email": "taylor@defuse.ca", + "homepage": "https://defuse.ca/" + }, + { + "name": "Scott Arciszewski", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "Secure PHP Encryption Library", + "keywords": [ + "aes", + "authenticated encryption", + "cipher", + "crypto", + "cryptography", + "encrypt", + "encryption", + "openssl", + "security", + "symmetric key cryptography" + ], + "support": { + "issues": "https://github.com/defuse/php-encryption/issues", + "source": "https://github.com/defuse/php-encryption/tree/v2.3.1" + }, + "time": "2021-04-09T23:57:26+00:00" + }, + { + "name": "fig/link-util", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link-util.git", + "reference": "5d7b8d04ed3393b4b59968ca1e906fb7186d81e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link-util/zipball/5d7b8d04ed3393b4b59968ca1e906fb7186d81e8", + "reference": "5d7b8d04ed3393b4b59968ca1e906fb7186d81e8", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "psr/link": "~1.0@dev" + }, + "provide": { + "psr/link-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.1", + "squizlabs/php_codesniffer": "^2.3.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common utility implementations for HTTP links", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "support": { + "issues": "https://github.com/php-fig/link-util/issues", + "source": "https://github.com/php-fig/link-util/tree/1.1.2" + }, + "time": "2021-02-03T23:36:04+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ac1ec1cd9b5624694c3a40be801d94137afb12b4", + "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.8.3 || ^2.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.4-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.4.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2022-03-20T14:16:28+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.5.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2021-10-22T20:56:57+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c94a94f120803a18554c1805ef2e539f8285f9a2", + "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.2.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2022-03-20T21:55:58+00:00" + }, + { + "name": "jakeasmith/http_build_url", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/jakeasmith/http_build_url.git", + "reference": "93c273e77cb1edead0cf8bcf8cd2003428e74e37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jakeasmith/http_build_url/zipball/93c273e77cb1edead0cf8bcf8cd2003428e74e37", + "reference": "93c273e77cb1edead0cf8bcf8cd2003428e74e37", + "shasum": "" + }, + "type": "library", + "autoload": { + "files": [ + "src/http_build_url.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jake A. Smith", + "email": "theman@jakeasmith.com" + } + ], + "description": "Provides functionality for http_build_url() to environments without pecl_http.", + "support": { + "issues": "https://github.com/jakeasmith/http_build_url/issues", + "source": "https://github.com/jakeasmith/http_build_url" + }, + "time": "2017-05-01T15:36:40+00:00" + }, + { + "name": "joomla/application", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/application.git", + "reference": "e7b950d2d1358c0baac95a8633a60de20a1e82ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/application/zipball/e7b950d2d1358c0baac95a8633a60de20a1e82ab", + "reference": "e7b950d2d1358c0baac95a8633a60de20a1e82ab", + "shasum": "" + }, + "require": { + "joomla/event": "^2.0", + "joomla/registry": "^1.4.5|^2.0", + "laminas/laminas-diactoros": "^2.2.2", + "php": "^7.2.5", + "psr/http-message": "^1.0", + "psr/log": "^1.0", + "symfony/deprecation-contracts": "^2.1" + }, + "conflict": { + "joomla/di": "<1.5", + "joomla/input": "<1.2", + "joomla/router": "<2.0", + "joomla/session": "<2.0", + "joomla/uri": "<1.1" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/controller": "^1.0|^2.0", + "joomla/di": "^1.5|^2.0", + "joomla/input": "^1.2|^2.0", + "joomla/router": "^2.0", + "joomla/session": "^2.0", + "joomla/test": "^2.0", + "joomla/uri": "^1.1|^2.0", + "phpunit/phpunit": "^8.5|^9.0", + "symfony/phpunit-bridge": "^3.4.26|^4.1.12|^4.2.7|^5.0" + }, + "suggest": { + "joomla/controller": "^1.0|^2.0 To support resolving ControllerInterface objects in ControllerResolverInterface, install joomla/controller", + "joomla/input": "^1.2|^2.0 To use WebApplicationInterface, install joomla/input", + "joomla/router": "^2.0 To use WebApplication or ControllerResolverInterface implementations, install joomla/router", + "joomla/session": "^2.0 To use SessionAwareWebApplicationInterface, install joomla/session", + "joomla/uri": "^1.1|^2.0 To use AbstractWebApplication, install joomla/uri", + "psr/container": "^1.0 To use the ContainerControllerResolver, install any PSR-11 compatible container" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Application\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Application Package", + "homepage": "https://github.com/joomla-framework/application", + "keywords": [ + "application", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/application/issues", + "source": "https://github.com/joomla-framework/application/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-12-10T12:11:13+00:00" + }, + { + "name": "joomla/archive", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/archive.git", + "reference": "cedda2cf21c388c590b8a110df25db6197765b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/archive/zipball/cedda2cf21c388c590b8a110df25db6197765b8c", + "reference": "cedda2cf21c388c590b8a110df25db6197765b8c", + "shasum": "" + }, + "require": { + "joomla/filesystem": "^2.0", + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "ext-bz2": "To extract bzip2 compressed packages", + "ext-zip": "To extract zip compressed packages", + "ext-zlib": "To extract gzip or zip compressed packages" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Archive\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Archive Package", + "homepage": "https://github.com/joomla-framework/archive", + "keywords": [ + "archive", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/archive/issues", + "source": "https://github.com/joomla-framework/archive/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2022-03-29T13:03:06+00:00" + }, + { + "name": "joomla/authentication", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/authentication.git", + "reference": "73d77db3b5d31300ffc0f147936cb420d4dffd96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/authentication/zipball/73d77db3b5d31300ffc0f147936cb420d4dffd96", + "reference": "73d77db3b5d31300ffc0f147936cb420d4dffd96", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "conflict": { + "joomla/database": "<2.0" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/database": "^2.0", + "joomla/input": "^1.0|^2.0", + "phpunit/phpunit": "^8.5|^9.0", + "symfony/phpunit-bridge": "^3.4|^4.4|^5.0" + }, + "suggest": { + "joomla/database": "Required if you want to use Joomla\\Authentication\\Strategies\\DatabaseStrategy", + "joomla/input": "Required if you want to use classes in the Joomla\\Authentication\\Strategies namespace" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Authentication\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Authentication Package", + "homepage": "https://github.com/joomla-framework/authentication", + "keywords": [ + "Authentication", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/authentication/issues", + "source": "https://github.com/joomla-framework/authentication/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-10T18:44:21+00:00" + }, + { + "name": "joomla/console", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/console.git", + "reference": "9db90c5b99e84a48cbaaf14c4c0d881b4d92480d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/console/zipball/9db90c5b99e84a48cbaaf14c4c0d881b4d92480d", + "reference": "9db90c5b99e84a48cbaaf14c4c0d881b4d92480d", + "shasum": "" + }, + "require": { + "joomla/application": "^2.0", + "joomla/event": "^2.0", + "joomla/string": "^2.0", + "php": "^7.2.5", + "symfony/console": "^3.4|^4.4|^5.0" + }, + "require-dev": { + "joomla/coding-standards": "^2.0@alpha", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/container-implementation": "To use the ContainerLoader" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Console\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Console Package", + "homepage": "https://github.com/joomla-framework/console", + "keywords": [ + "console", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/console/issues", + "source": "https://github.com/joomla-framework/console/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-10T20:31:15+00:00" + }, + { + "name": "joomla/controller", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/controller.git", + "reference": "85b26e4b4521bceb346783bd342cb8c7a3f8c1be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/controller/zipball/85b26e4b4521bceb346783bd342cb8c7a3f8c1be", + "reference": "85b26e4b4521bceb346783bd342cb8c7a3f8c1be", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "joomla/application": "^1.0|^2.0", + "joomla/coding-standards": "^2.0@alpha", + "joomla/input": "^1.0|^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "joomla/application": "The joomla/application package is required to use Joomla\\Controller\\AbstractController", + "joomla/input": "The joomla/input package is required to use Joomla\\Controller\\AbstractController" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Controller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Controller Package", + "homepage": "https://github.com/joomla-framework/controller", + "keywords": [ + "controller", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/controller/issues", + "source": "https://github.com/joomla-framework/controller/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:21:42+00:00" + }, + { + "name": "joomla/crypt", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/crypt.git", + "reference": "db9e5c4f8b42df5dee0a3698404affe631fdaba4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/crypt/zipball/db9e5c4f8b42df5dee0a3698404affe631fdaba4", + "reference": "db9e5c4f8b42df5dee0a3698404affe631fdaba4", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "conflict": { + "defuse/php-encryption": "<2.0" + }, + "require-dev": { + "defuse/php-encryption": "^2.0", + "joomla/coding-standards": "^2.0@alpha", + "paragonie/sodium_compat": "^1.0", + "phpunit/phpunit": "^8.5|^9.0", + "symfony/phpunit-bridge": "^4.4|^5.0", + "symfony/polyfill-util": "^1.0" + }, + "suggest": { + "defuse/php-encryption": "To use Crypto cipher", + "ext-openssl": "To use the OpenSSL cipher", + "ext-sodium": "To use the Sodium cipher", + "paragonie/sodium_compat": "To use Sodium cipher if neither ext/sodium or ext/libsodium are available" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Crypt\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Crypt Package", + "homepage": "https://github.com/joomla-framework/crypt", + "keywords": [ + "crypt", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/crypt/issues", + "source": "https://github.com/joomla-framework/crypt/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-10T18:46:07+00:00" + }, + { + "name": "joomla/data", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/data.git", + "reference": "6327825f48ba517d8f35179ac8f7868522d3a23f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/data/zipball/6327825f48ba517d8f35179ac8f7868522d3a23f", + "reference": "6327825f48ba517d8f35179ac8f7868522d3a23f", + "shasum": "" + }, + "require": { + "joomla/registry": "^1.4.5|^2.0", + "php": "^7.2.5" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Data\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Data Package", + "homepage": "https://github.com/joomla-framework/data", + "keywords": [ + "data", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/data/issues", + "source": "https://github.com/joomla-framework/data/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-10T18:47:10+00:00" + }, + { + "name": "joomla/database", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/database.git", + "reference": "194415339358b3ded43d5f68446b4fa93e18c3d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/database/zipball/194415339358b3ded43d5f68446b4fa93e18c3d3", + "reference": "194415339358b3ded43d5f68446b4fa93e18c3d3", + "shasum": "" + }, + "require": { + "joomla/event": "^2.0", + "php": "^7.2.5|^8.0", + "symfony/deprecation-contracts": "^2.1" + }, + "require-dev": { + "joomla/archive": "^1.0|^2.0", + "joomla/coding-standards": "^2.0@alpha", + "joomla/console": "^2.0", + "joomla/di": "^1.0|^2.0", + "joomla/filesystem": "^1.3|^2.0", + "joomla/registry": "^1.4.5|^2.0", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0", + "psr/log": "^1.1", + "symfony/phpunit-bridge": "^4.4|^5.0" + }, + "suggest": { + "ext-mysqli": "To connect to a MySQL database via MySQLi", + "ext-pdo": "To connect to a MySQL, PostgreSQL, or SQLite database via PDO", + "ext-sqlsrv": "To connect to a SQL Server database", + "joomla/archive": "To use the ExportCommand class, install joomla/archive", + "joomla/console": "To use the ExportCommand and ImportCommand classes, install joomla/console", + "joomla/di": "To use the Database ServiceProviderInterface objects, install joomla/di.", + "joomla/filesystem": "To use the ExportCommand and ImportCommand classes, install joomla/filesystem", + "joomla/registry": "To use the Database ServiceProviderInterface objects, install joomla/registry.", + "psr/log": "To use the LoggingMonitor, install psr/log." + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Database\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Database Package", + "homepage": "https://github.com/joomla-framework/database", + "keywords": [ + "database", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/database/issues", + "source": "https://github.com/joomla-framework/database/tree/2.1.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2022-03-02T16:36:31+00:00" + }, + { + "name": "joomla/di", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/di.git", + "reference": "22ef18207e8945c8247aa2372bddbe76383bd0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/di/zipball/22ef18207e8945c8247aa2372bddbe76383bd0bc", + "reference": "22ef18207e8945c8247aa2372bddbe76383bd0bc", + "shasum": "" + }, + "require": { + "php": "^7.2.5|~8", + "psr/container": "^1.0", + "symfony/deprecation-contracts": "^2.1" + }, + "provide": { + "psr/container-implementation": "~1.0" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\DI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla DI Package", + "homepage": "https://github.com/joomla-framework/di", + "keywords": [ + "container", + "dependency injection", + "di", + "framework", + "ioc", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/di/issues", + "source": "https://github.com/joomla-framework/di/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-04-06T22:33:15+00:00" + }, + { + "name": "joomla/event", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/event.git", + "reference": "dc19eae9a6cbffb608d4719f4eeb986e785692bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/event/zipball/dc19eae9a6cbffb608d4719f4eeb986e785692bd", + "reference": "dc19eae9a6cbffb608d4719f4eeb986e785692bd", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/deprecation-contracts": "^2.1" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/console": "^2.0", + "phpunit/phpunit": "^8.5|^9.0", + "psr/container": "^1.0" + }, + "suggest": { + "joomla/console": "If you want to use the DebugEventDispatcherCommand class, please install joomla/console", + "psr/container-implementation": "If you want to use the LazyServiceEventListener class, please install a PSR-11 container" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Event\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Event Package", + "homepage": "https://github.com/joomla-framework/event", + "keywords": [ + "event", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/event/issues", + "source": "https://github.com/joomla-framework/event/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-12-10T11:50:27+00:00" + }, + { + "name": "joomla/filesystem", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/filesystem.git", + "reference": "d991e618da69e557a84ea97e6a601afec28ae8cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/filesystem/zipball/d991e618da69e557a84ea97e6a601afec28ae8cf", + "reference": "d991e618da69e557a84ea97e6a601afec28ae8cf", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/test": "^2.0", + "mikey179/vfsstream": "^1.1", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Filesystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Filesystem Package", + "homepage": "https://github.com/joomla/joomla-framework-filesystem", + "keywords": [ + "filesystem", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/filesystem/issues", + "source": "https://github.com/joomla-framework/filesystem/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2022-03-29T12:43:57+00:00" + }, + { + "name": "joomla/filter", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/filter.git", + "reference": "137ca3f8925c4529a113735404b873fad0a1305f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/filter/zipball/137ca3f8925c4529a113735404b873fad0a1305f", + "reference": "137ca3f8925c4529a113735404b873fad0a1305f", + "shasum": "" + }, + "require": { + "joomla/string": "^1.3|^2.0", + "php": "^7.2.5" + }, + "conflict": { + "joomla/language": "<2.0" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/language": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "joomla/language": "Required only if you want to use `OutputFilter::stringURLSafe`." + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Filter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Filter Package", + "homepage": "https://github.com/joomla-framework/filter", + "keywords": [ + "filter", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/filter/issues", + "source": "https://github.com/joomla-framework/filter/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2022-02-15T21:33:06+00:00" + }, + { + "name": "joomla/http", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/http.git", + "reference": "95f46a39dec738f73839e61c035be4fa597e822a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/http/zipball/95f46a39dec738f73839e61c035be4fa597e822a", + "reference": "95f46a39dec738f73839e61c035be4fa597e822a", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "joomla/uri": "^1.0|^2.0", + "laminas/laminas-diactoros": "^2.2.2", + "php": "^7.2.5", + "psr/http-client": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "joomla/coding-standards": "^2.0@alpha", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "ext-curl": "To use cURL for HTTP connections" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Http\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla HTTP Package", + "homepage": "https://github.com/joomla-framework/http", + "keywords": [ + "framework", + "http", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/http/issues", + "source": "https://github.com/joomla-framework/http/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T19:52:50+00:00" + }, + { + "name": "joomla/input", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/input.git", + "reference": "147229d2e0c5ac7db6f972d19c9faa922575e5c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/input/zipball/147229d2e0c5ac7db6f972d19c9faa922575e5c2", + "reference": "147229d2e0c5ac7db6f972d19c9faa922575e5c2", + "shasum": "" + }, + "require": { + "joomla/filter": "^1.0|^2.0", + "php": "^7.2.5", + "symfony/deprecation-contracts": "^2.1" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Input\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Input Package", + "homepage": "https://github.com/joomla-framework/input", + "keywords": [ + "framework", + "input", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/input/issues", + "source": "https://github.com/joomla-framework/input/tree/2.0.3" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2022-04-06T20:02:40+00:00" + }, + { + "name": "joomla/ldap", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/ldap.git", + "reference": "b02ec8a59297b517b0b843b07971aa2e7bbe91d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/ldap/zipball/b02ec8a59297b517b0b843b07971aa2e7bbe91d2", + "reference": "b02ec8a59297b517b0b843b07971aa2e7bbe91d2", + "shasum": "" + }, + "require": { + "ext-ldap": "*", + "php": "~7.0" + }, + "require-dev": { + "joomla/coding-standards": "~2.0@alpha", + "joomla/registry": "^1.4.5|~2.0", + "phpunit/phpunit": "~6.3" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Ldap\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla LDAP Package", + "homepage": "https://github.com/joomla-framework/ldap", + "keywords": [ + "framework", + "joomla", + "ldap" + ], + "support": { + "issues": "https://github.com/joomla-framework/ldap/issues", + "source": "https://github.com/joomla-framework/ldap/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:01:23+00:00" + }, + { + "name": "joomla/model", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/model.git", + "reference": "e874ca6ea7f463d28f7620dc242973747dc8f0f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/model/zipball/e874ca6ea7f463d28f7620dc242973747dc8f0f0", + "reference": "e874ca6ea7f463d28f7620dc242973747dc8f0f0", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/database": "^1.0|^2.0", + "joomla/registry": "^1.4.5|^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "joomla/database": "^1.0|^2.0 Allows using database models", + "joomla/registry": "^1.4.5|^2.0 Allows using stateful models" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Model\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Model Package", + "homepage": "https://github.com/joomla-framework/model", + "keywords": [ + "framework", + "joomla", + "model" + ], + "support": { + "issues": "https://github.com/joomla-framework/model/issues", + "source": "https://github.com/joomla-framework/model/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:22:12+00:00" + }, + { + "name": "joomla/oauth1", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/oauth1.git", + "reference": "89559f79ff0c3fef73f806fd66814ae8bb1cb655" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/oauth1/zipball/89559f79ff0c3fef73f806fd66814ae8bb1cb655", + "reference": "89559f79ff0c3fef73f806fd66814ae8bb1cb655", + "shasum": "" + }, + "require": { + "joomla/application": "^2.0", + "joomla/http": "^1.2.2|^2.0", + "joomla/input": "^1.2|^2.0", + "joomla/registry": "^1.4.5|^2.0", + "joomla/session": "^2.0", + "joomla/uri": "^1.1|^2.0", + "php": "^7.2.5" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/event": "^2.0", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\OAuth1\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla OAuth1 Package", + "homepage": "https://github.com/joomla-framework/oauth1", + "keywords": [ + "framework", + "joomla", + "oauth1" + ], + "support": { + "issues": "https://github.com/joomla-framework/oauth1/issues", + "source": "https://github.com/joomla-framework/oauth1/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T19:58:37+00:00" + }, + { + "name": "joomla/oauth2", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/oauth2.git", + "reference": "1e6fd0affea9f96376e580ec050145e874b399cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/oauth2/zipball/1e6fd0affea9f96376e580ec050145e874b399cb", + "reference": "1e6fd0affea9f96376e580ec050145e874b399cb", + "shasum": "" + }, + "require": { + "joomla/application": "^2.0", + "joomla/http": "^1.2.2|^2.0", + "joomla/input": "^1.2|^2.0", + "joomla/session": "^1.0|^2.0", + "joomla/uri": "^1.0|^2.0", + "php": "^7.2.5" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\OAuth2\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla OAuth2 Package", + "homepage": "https://github.com/joomla-framework/oauth2", + "keywords": [ + "framework", + "joomla", + "oauth2" + ], + "support": { + "issues": "https://github.com/joomla-framework/oauth2/issues", + "source": "https://github.com/joomla-framework/oauth2/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T19:59:30+00:00" + }, + { + "name": "joomla/preload", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/preload.git", + "reference": "dcd6f3424e3d02e2b47761464e33826b2b6ae7e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/preload/zipball/dcd6f3424e3d02e2b47761464e33826b2b6ae7e0", + "reference": "dcd6f3424e3d02e2b47761464e33826b2b6ae7e0", + "shasum": "" + }, + "require": { + "fig/link-util": "^1.0", + "php": "^7.2.5", + "psr/link": "^1.0" + }, + "conflict": { + "joomla/application": "<2.0", + "joomla/event": "<2.0" + }, + "require-dev": { + "joomla/application": "^2.0", + "joomla/coding-standards": "^2.0@alpha", + "joomla/di": "^1.5|^2.0", + "joomla/event": "^2.0", + "joomla/uri": "^2.0", + "phpunit/phpunit": "^8.2", + "symfony/web-link": "^3.4|^4.4|^5.0" + }, + "suggest": { + "joomla/application": "To use the PreloadSubscriber event listener, install `^2.0`", + "joomla/di": "To use the PreloadProvider service provider, install `^1.5|^2.0`", + "joomla/event": "To use the PreloadSubscriber event listener, install `^2.0`", + "symfony/web-link": "To use the PreloadSubscriber event listener, install `^3.4|^4.4|^5.0`" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Preload\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Preload Package", + "homepage": "https://github.com/joomla-framework/preload", + "keywords": [ + "console", + "framework", + "joomla" + ], + "support": { + "issues": "https://github.com/joomla-framework/preload/issues", + "source": "https://github.com/joomla-framework/preload/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:23:39+00:00" + }, + { + "name": "joomla/registry", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/registry.git", + "reference": "4fcfa060f1ec101ec8311770a1d1c166eba6e367" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/registry/zipball/4fcfa060f1ec101ec8311770a1d1c166eba6e367", + "reference": "4fcfa060f1ec101ec8311770a1d1c166eba6e367", + "shasum": "" + }, + "require": { + "joomla/utilities": "^1.4.1|^2.0", + "php": "^7.2.5" + }, + "conflict": { + "symfony/yaml": "<3.4" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "phpunit/phpunit": "^8.5|^9.0", + "symfony/yaml": "^3.4|^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "Install symfony/yaml if you require YAML support." + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Registry\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Registry Package", + "homepage": "https://github.com/joomla-framework/registry", + "keywords": [ + "framework", + "joomla", + "registry" + ], + "support": { + "issues": "https://github.com/joomla-framework/registry/issues", + "source": "https://github.com/joomla-framework/registry/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-12-10T11:52:55+00:00" + }, + { + "name": "joomla/renderer", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/renderer.git", + "reference": "482896d9b10a3a17bf87cbb531d2ebfb463a3df7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/renderer/zipball/482896d9b10a3a17bf87cbb531d2ebfb463a3df7", + "reference": "482896d9b10a3a17bf87cbb531d2ebfb463a3df7", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "conflict": { + "illuminate/view": "<6.0", + "league/plates": "<3.0", + "mustache/mustache": "<2.3", + "symfony/templating": "<3.4", + "twig/twig": "<1.34 || >=2.0,<2.4" + }, + "require-dev": { + "illuminate/events": "^6.0|^7.0", + "illuminate/filesystem": "^6.0|^7.0", + "illuminate/view": "^6.0|^7.0", + "joomla/coding-standards": "^2.0@alpha", + "joomla/test": "^2.0", + "league/plates": "^3.0", + "mustache/mustache": "^2.3", + "phpunit/phpunit": "^8.5|^9.0", + "symfony/templating": "^3.4|^4.4|^5.0", + "twig/twig": "^1.34|^2.4|^3.0" + }, + "suggest": { + "illuminate/view": "Install ^6.0|^7.0 if you are using Laravel's Blade template engine.", + "league/plates": "Install ^3.0 if you are using the Plates template engine.", + "mustache/mustache": "Install ^2.3 if you are using the Mustache template engine.", + "symfony/templating": "Install ^3.4|^4.4|^5.0 if you are using Symfony's PHP template component.", + "twig/twig": "Install ^1.34|^2.4|^3.0 if you are using the Twig template engine." + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Renderer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "description": "Joomla Renderer Package", + "homepage": "https://github.com/joomla-framework/renderer", + "keywords": [ + "framework", + "joomla", + "renderer" + ], + "support": { + "issues": "https://github.com/joomla-framework/renderer/issues", + "source": "https://github.com/joomla-framework/renderer/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:20:59+00:00" + }, + { + "name": "joomla/router", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/router.git", + "reference": "8dfb320fde8ed2c914c6e52df1e7266e9b25379a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/router/zipball/8dfb320fde8ed2c914c6e52df1e7266e9b25379a", + "reference": "8dfb320fde8ed2c914c6e52df1e7266e9b25379a", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "conflict": { + "jeremeamia/superclosure": "<2.4" + }, + "require-dev": { + "jeremeamia/superclosure": "^2.4", + "joomla/coding-standards": "^2.0@alpha", + "joomla/console": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "jeremeamia/superclosure": "If you use Closure based controllers and want to be able to serialize the router, please install jeremeamia/superclosure", + "joomla/console": "If you want to use the DebugRouterCommand class, please install joomla/console" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Router\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Router Package", + "homepage": "https://github.com/joomla-framework/router", + "keywords": [ + "framework", + "joomla", + "router" + ], + "support": { + "issues": "https://github.com/joomla-framework/router/issues", + "source": "https://github.com/joomla-framework/router/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:04:57+00:00" + }, + { + "name": "joomla/session", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/session.git", + "reference": "a7bb708a988530ce90c95e33efbc56432cf56c07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/session/zipball/a7bb708a988530ce90c95e33efbc56432cf56c07", + "reference": "a7bb708a988530ce90c95e33efbc56432cf56c07", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/deprecation-contracts": "^2.1" + }, + "conflict": { + "joomla/database": "<2.0", + "joomla/event": "<2.0", + "joomla/input": "<2.0" + }, + "require-dev": { + "joomla/coding-standards": "^3.0@dev", + "joomla/console": "^2.0", + "joomla/database": "^2.0", + "joomla/event": "^2.0", + "joomla/input": "^2.0", + "joomla/test": "^2.0", + "joomla/utilities": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "ext-apcu": "To use APCu cache as a session handler", + "ext-memcached": "To use a Memcached server as a session handler", + "ext-redis": "To use a Redis server as a session handler", + "ext-session": "To use the Joomla\\Session\\Storage\\NativeStorage storage class.", + "ext-wincache": "To use WinCache as a session handler", + "joomla/console": "Install joomla/console if you want to use the CreateSessionTableCommand class.", + "joomla/database": "Install joomla/database if you want to use a database connection managed with Joomla\\Database\\DatabaseDriver as a session handler.", + "joomla/event": "The joomla/event package is required to use Joomla\\Session\\Session.", + "joomla/input": "The joomla/input package is required to use Address and Forwarded session validators." + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Session\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Session Package", + "homepage": "https://github.com/joomla-framework/session", + "keywords": [ + "framework", + "joomla", + "session" + ], + "support": { + "issues": "https://github.com/joomla-framework/session/issues", + "source": "https://github.com/joomla-framework/session/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-12-11T19:55:26+00:00" + }, + { + "name": "joomla/string", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/string.git", + "reference": "778682c04a1909323da6a453a5b3030d7a7a2fa9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/string/zipball/778682c04a1909323da6a453a5b3030d7a7a2fa9", + "reference": "778682c04a1909323da6a453a5b3030d7a7a2fa9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/deprecation-contracts": "^2.1" + }, + "conflict": { + "doctrine/inflector": "<1.2" + }, + "require-dev": { + "doctrine/inflector": "1.2", + "joomla/coding-standards": "^3.0@dev", + "joomla/test": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "doctrine/inflector": "To use the string inflector", + "ext-mbstring": "For improved processing" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "files": [ + "src/phputf8/utf8.php", + "src/phputf8/ord.php", + "src/phputf8/str_ireplace.php", + "src/phputf8/str_pad.php", + "src/phputf8/str_split.php", + "src/phputf8/strcasecmp.php", + "src/phputf8/strcspn.php", + "src/phputf8/stristr.php", + "src/phputf8/strrev.php", + "src/phputf8/strspn.php", + "src/phputf8/trim.php", + "src/phputf8/ucfirst.php", + "src/phputf8/ucwords.php", + "src/phputf8/utils/ascii.php", + "src/phputf8/utils/validation.php" + ], + "psr-4": { + "Joomla\\String\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla String Package", + "homepage": "https://github.com/joomla-framework/string", + "keywords": [ + "framework", + "joomla", + "string" + ], + "support": { + "issues": "https://github.com/joomla-framework/string/issues", + "source": "https://github.com/joomla-framework/string/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-10T18:57:12+00:00" + }, + { + "name": "joomla/uri", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/uri.git", + "reference": "5046ea584b76e485ef84390c6d79bafb358fb605" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/uri/zipball/5046ea584b76e485ef84390c6d79bafb358fb605", + "reference": "5046ea584b76e485ef84390c6d79bafb358fb605", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "joomla/coding-standards": "^2.0@alpha", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Uri Package", + "homepage": "https://github.com/joomla-framework/uri", + "keywords": [ + "framework", + "joomla", + "uri" + ], + "support": { + "issues": "https://github.com/joomla-framework/uri/issues", + "source": "https://github.com/joomla-framework/uri/tree/2.0.1" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2022-01-25T12:04:01+00:00" + }, + { + "name": "joomla/utilities", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/utilities.git", + "reference": "f5d4fcf778abbbf1c099814297c87ef177e8b268" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/utilities/zipball/f5d4fcf778abbbf1c099814297c87ef177e8b268", + "reference": "f5d4fcf778abbbf1c099814297c87ef177e8b268", + "shasum": "" + }, + "require": { + "joomla/string": "^1.3|^2.0", + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "joomla/coding-standards": "^2.0@alpha", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\Utilities\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla Utilities Package", + "homepage": "https://github.com/joomla-framework/utilities", + "keywords": [ + "framework", + "joomla", + "utilities" + ], + "support": { + "issues": "https://github.com/joomla-framework/utilities/issues", + "source": "https://github.com/joomla-framework/utilities/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:13:00+00:00" + }, + { + "name": "joomla/view", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/view.git", + "reference": "3b43c84eba02c037190de3c796c81b31883694ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/view/zipball/3b43c84eba02c037190de3c796c81b31883694ef", + "reference": "3b43c84eba02c037190de3c796c81b31883694ef", + "shasum": "" + }, + "require": { + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "joomla/coding-standards": "^2.0@alpha", + "joomla/renderer": "^2.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "suggest": { + "joomla/renderer": "Required to use Joomla\\View\\BaseHtmlView" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\View\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "Joomla View Package", + "homepage": "https://github.com/joomla-framework/view", + "keywords": [ + "framework", + "joomla", + "view" + ], + "support": { + "issues": "https://github.com/joomla-framework/view/issues", + "source": "https://github.com/joomla-framework/view/tree/2.0.0" + }, + "funding": [ + { + "url": "https://community.joomla.org/sponsorship-campaigns.html", + "type": "custom" + }, + { + "url": "https://github.com/joomla", + "type": "github" + } + ], + "time": "2021-08-16T20:22:32+00:00" + }, + { + "name": "laminas/laminas-diactoros", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-diactoros.git", + "reference": "36ef09b73e884135d2059cc498c938e90821bb57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/36ef09b73e884135d2059cc498c938e90821bb57", + "reference": "36ef09b73e884135d2059cc498c938e90821bb57", + "shasum": "" + }, + "require": { + "laminas/laminas-zendframework-bridge": "^1.0", + "php": "^7.1", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "conflict": { + "phpspec/prophecy": "<1.9.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "replace": { + "zendframework/zend-diactoros": "^2.2.1" + }, + "require-dev": { + "ext-curl": "*", + "ext-dom": "*", + "ext-gd": "*", + "ext-libxml": "*", + "http-interop/http-factory-tests": "^0.5.0", + "laminas/laminas-coding-standard": "~1.0.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5.18" + }, + "type": "library", + "extra": { + "laminas": { + "config-provider": "Laminas\\Diactoros\\ConfigProvider", + "module": "Laminas\\Diactoros" + } + }, + "autoload": { + "files": [ + "src/functions/create_uploaded_file.php", + "src/functions/marshal_headers_from_sapi.php", + "src/functions/marshal_method_from_sapi.php", + "src/functions/marshal_protocol_version_from_sapi.php", + "src/functions/marshal_uri_from_sapi.php", + "src/functions/normalize_server.php", + "src/functions/normalize_uploaded_files.php", + "src/functions/parse_cookie_header.php", + "src/functions/create_uploaded_file.legacy.php", + "src/functions/marshal_headers_from_sapi.legacy.php", + "src/functions/marshal_method_from_sapi.legacy.php", + "src/functions/marshal_protocol_version_from_sapi.legacy.php", + "src/functions/marshal_uri_from_sapi.legacy.php", + "src/functions/normalize_server.legacy.php", + "src/functions/normalize_uploaded_files.legacy.php", + "src/functions/parse_cookie_header.legacy.php" + ], + "psr-4": { + "Laminas\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://laminas.dev", + "keywords": [ + "http", + "laminas", + "psr", + "psr-17", + "psr-7" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-diactoros/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-diactoros/issues", + "rss": "https://github.com/laminas/laminas-diactoros/releases.atom", + "source": "https://github.com/laminas/laminas-diactoros" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2020-09-03T14:29:41+00:00" + }, + { + "name": "laminas/laminas-zendframework-bridge", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-zendframework-bridge.git", + "reference": "6ede70583e101030bcace4dcddd648f760ddf642" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642", + "reference": "6ede70583e101030bcace4dcddd648f760ddf642", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laminas": { + "module": "Laminas\\ZendFrameworkBridge" + } + }, + "autoload": { + "files": [ + "src/autoload.php" + ], + "psr-4": { + "Laminas\\ZendFrameworkBridge\\": "src//" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Alias legacy ZF class names to Laminas Project equivalents.", + "keywords": [ + "ZendFramework", + "autoloading", + "laminas", + "zf" + ], + "support": { + "forum": "https://discourse.laminas.dev/", + "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", + "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", + "source": "https://github.com/laminas/laminas-zendframework-bridge" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2020-09-14T14:23:00+00:00" + }, + { + "name": "monolog/monolog", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "4192345e260f1d51b365536199744b987e160edc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4192345e260f1d51b365536199744b987e160edc", + "reference": "4192345e260f1d51b365536199744b987e160edc", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7", + "graylog2/gelf-php": "^1.4.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.3", + "phpspec/prophecy": "^1.6.1", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5", + "predis/predis": "^1.1", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": ">=0.90@dev", + "swiftmailer/swiftmailer": "^5.3|^6.0" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.5.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2022-04-08T15:43:54+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "phpmailer/phpmailer", + "version": "v6.6.0", + "source": { + "type": "git", + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "e43bac82edc26ca04b36143a48bde1c051cfd5b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e43bac82edc26ca04b36143a48bde1c051cfd5b1", + "reference": "e43bac82edc26ca04b36143a48bde1c051cfd5b1", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "php": ">=5.5.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.2", + "php-parallel-lint/php-console-highlighter": "^0.5.0", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.3.5", + "roave/security-advisories": "dev-latest", + "squizlabs/php_codesniffer": "^3.6.2", + "yoast/phpunit-polyfills": "^1.0.0" + }, + "suggest": { + "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", + "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", + "league/oauth2-google": "Needed for Google XOAUTH2 authentication", + "psr/log": "For optional PSR-3 debug logging", + "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication", + "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPMailer\\PHPMailer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-only" + ], + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "support": { + "issues": "https://github.com/PHPMailer/PHPMailer/issues", + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.0" + }, + "funding": [ + { + "url": "https://github.com/Synchro", + "type": "github" + } + ], + "time": "2022-02-28T15:31:21+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "time": "2021-03-05T17:36:06+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/link", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link/zipball/eea8e8662d5cd3ae4517c9b864493f59fca95562", + "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for HTTP links", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "support": { + "source": "https://github.com/php-fig/link/tree/master" + }, + "time": "2016-10-28T16:06:13+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "ab2237657ad99667a5143e32ba2683c8029563d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4", + "reference": "ab2237657ad99667a5143e32ba2683c8029563d4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8" + }, + "require-dev": { + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP 7.2+ library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/1.1.4" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2021-07-30T00:58:27+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.2.3", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "shasum": "" + }, + "require": { + "brick/math": "^0.8 || ^0.9", + "ext-json": "*", + "php": "^7.2 || ^8.0", + "ramsey/collection": "^1.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php80": "^1.14" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "moontoast/math": "^1.1", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5 || ^9", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.x-dev" + }, + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.2.3" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2021-09-25T23:10:38+00:00" + }, + { + "name": "robmorgan/phinx", + "version": "0.12.10", + "source": { + "type": "git", + "url": "https://github.com/cakephp/phinx.git", + "reference": "ad056cff354fc67fedf9bf96c441c2b428afad0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/phinx/zipball/ad056cff354fc67fedf9bf96c441c2b428afad0c", + "reference": "ad056cff354fc67fedf9bf96c441c2b428afad0c", + "shasum": "" + }, + "require": { + "cakephp/database": "^4.0", + "php": ">=7.2", + "psr/container": "^1.0 || ^2.0", + "symfony/config": "^3.4|^4.0|^5.0|^6.0", + "symfony/console": "^3.4|^4.0|^5.0|^6.0" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^4.0", + "ext-json": "*", + "ext-pdo": "*", + "phpunit/phpunit": "^8.5|^9.3", + "sebastian/comparator": ">=1.2.3", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "ext-json": "Install if using JSON configuration format", + "ext-pdo": "PDO extension is needed", + "symfony/yaml": "Install if using YAML configuration format" + }, + "bin": [ + "bin/phinx" + ], + "type": "library", + "autoload": { + "psr-4": { + "Phinx\\": "src/Phinx/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Morgan", + "email": "robbym@gmail.com", + "homepage": "https://robmorgan.id.au", + "role": "Lead Developer" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "homepage": "https://shadowhand.me", + "role": "Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Developer" + }, + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/phinx/graphs/contributors", + "role": "Developer" + } + ], + "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.", + "homepage": "https://phinx.org", + "keywords": [ + "database", + "database migrations", + "db", + "migrations", + "phinx" + ], + "support": { + "issues": "https://github.com/cakephp/phinx/issues", + "source": "https://github.com/cakephp/phinx/tree/0.12.10" + }, + "time": "2022-01-21T19:53:14+00:00" + }, + { + "name": "symfony/asset", + "version": "v5.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset.git", + "reference": "4affdca3da5f380caa27a338269b36ac288b3981" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset/zipball/4affdca3da5f380caa27a338269b36ac288b3981", + "reference": "4affdca3da5f380caa27a338269b36ac288b3981", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/http-foundation": "<5.3" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^5.3|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/http-foundation": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/asset/tree/v5.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-18T16:00:30+00:00" + }, + { + "name": "symfony/config", + "version": "v5.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "05624c386afa1b4ccc1357463d830fade8d9d404" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/05624c386afa1b4ccc1357463d830fade8d9d404", + "reference": "05624c386afa1b4ccc1357463d830fade8d9d404", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^4.4|^5.0|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/yaml": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v5.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-21T13:42:03+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/900275254f0a1a2afff1ab0e11abd5587a10e1d6", + "reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-31T17:09:19+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/3a4442138d80c9f7b600fb297534ac718b61d37f", + "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-04-01T12:33:59+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "30885182c981ab175d4d034db0f6f469898070ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-10-20T20:35:02+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-11-23T21:10:46+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-11-30T18:21:41+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T09:17:38+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-06-05T21:20:04+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-04T08:16:47+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-09-13T13:58:11+00:00" + }, + { + "name": "symfony/process", + "version": "v5.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "38a44b2517b470a436e1c944bf9b9ba3961137fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/38a44b2517b470a436e1c944bf9b9ba3961137fb", + "reference": "38a44b2517b470a436e1c944bf9b9ba3961137fb", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-18T16:18:52+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-13T20:07:29+00:00" + }, + { + "name": "symfony/string", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", + "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/web-link", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-link.git", + "reference": "8b9b073390359549fec5f5d797f23bbe9e2997a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-link/zipball/8b9b073390359549fec5f5d797f23bbe9e2997a5", + "reference": "8b9b073390359549fec5f5d797f23bbe9e2997a5", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/link": "^1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/http-kernel": "<5.3" + }, + "provide": { + "psr/link-implementation": "1.0" + }, + "require-dev": { + "symfony/http-kernel": "^5.3|^6.0" + }, + "suggest": { + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\WebLink\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages links between resources", + "homepage": "https://symfony.com", + "keywords": [ + "dns-prefetch", + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" + ], + "support": { + "source": "https://github.com/symfony/web-link/tree/v5.4.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/yaml", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "e80f87d2c9495966768310fc531b487ce64237a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", + "reference": "e80f87d2c9495966768310fc531b487ce64237a2", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.3" + }, + "require-dev": { + "symfony/console": "^5.3|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.4.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-26T16:32:32+00:00" + }, + { + "name": "theiconic/php-ga-measurement-protocol", + "version": "v2.9.0", + "source": { + "type": "git", + "url": "https://github.com/theiconic/php-ga-measurement-protocol.git", + "reference": "6136c2f2ef159045402ef985843db0ad0f136125" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theiconic/php-ga-measurement-protocol/zipball/6136c2f2ef159045402ef985843db0ad0f136125", + "reference": "6136c2f2ef159045402ef985843db0ad0f136125", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0 || ^7.0", + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "4.7.*", + "satooshi/php-coveralls": "1.0.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "TheIconic\\Tracking\\GoogleAnalytics\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "THE ICONIC ENGINEERING TEAM", + "email": "engineering@theiconic.com.au" + } + ], + "description": "Send data to Google Analytics from the server using PHP. This library fully implements GA measurement protocol.", + "support": { + "issues": "https://github.com/theiconic/php-ga-measurement-protocol/issues", + "source": "https://github.com/theiconic/php-ga-measurement-protocol/tree/v2.9.0" + }, + "time": "2020-09-24T23:37:47+00:00" + }, + { + "name": "twig/twig", + "version": "v2.14.13", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "66856cd0459df3dc97d32077a98454dc2a0ee75a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/66856cd0459df3dc97d32077a98454dc2a0ee75a", + "reference": "66856cd0459df3dc97d32077a98454dc2a0ee75a", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.8" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.14-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v2.14.13" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2022-04-06T06:45:17+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.2.5" + }, + "platform-dev": [], + "platform-overrides": { + "php": "7.2.5" + }, + "plugin-api-version": "2.1.0" +} diff --git a/week-03/project/includes/app.php b/week-03/project/includes/app.php index 15fdbdd..603becf 100644 --- a/week-03/project/includes/app.php +++ b/week-03/project/includes/app.php @@ -1,63 +1,95 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; - -// Saves the start time and memory usage. -$startTime = microtime(1); -$startMem = memory_get_usage(); +defined('_LEXEC') or die; +// Option to override defines from root folder +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L15 if (file_exists(dirname(__DIR__) . '/defines.php')) { include_once dirname(__DIR__) . '/defines.php'; } -if (!defined('_JDEFINES')) +// Load the default defines +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L20 +if (!defined('_LDEFINES')) { - define('JPATH_BASE', dirname(__DIR__)); - require_once JPATH_BASE . '/includes/defines.php'; + define('LPATH_BASE', dirname(__DIR__)); + require_once LPATH_BASE . '/includes/defines.php'; } // Check for presence of vendor dependencies not included in the git repository -if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_ROOT . '/media/vendor')) +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L26 +if (!file_exists(LPATH_LIBRARIES . '/vendor/autoload.php')) { - echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html'); + echo file_get_contents(LPATH_ROOT . '/templates/system/build_incomplete.html'); exit; } -require_once JPATH_BASE . '/includes/framework.php'; +// Load configuration (or install) +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L34 +require_once LPATH_BASE . '/includes/framework.php'; -// Set profiler start time and memory usage and mark afterLoad in the profiler. -JDEBUG && \Joomla\CMS\Profiler\Profiler::getInstance('Application')->setStart($startTime, $startMem)->mark('afterLoad'); +// Wrap in a try/catch so we can display an error if need be +try +{ + $container = (new Joomla\DI\Container) + ->registerServiceProvider(new Octoleo\CMS\Service\SiteApplicationProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\ConfigurationProvider(LPATH_CONFIGURATION . '/octoconfig.php')) + ->registerServiceProvider(new Joomla\Database\Service\DatabaseProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\EventProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\HttpProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\LoggingProvider) + ->registerServiceProvider(new Joomla\Preload\Service\PreloadProvider) + ->registerServiceProvider(new Octoleo\CMS\Service\TemplatingProvider); -// Boot the DI container -$container = \Joomla\CMS\Factory::getContainer(); + // Alias the web application to Octoleo's base application class as this is the primary application for the environment + $container->alias(Joomla\Application\AbstractApplication::class, Joomla\Application\AbstractWebApplication::class); -/* - * Alias the session service keys to the web session service as that is the primary session backend for this application - * - * In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects - * is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered - * deprecated to be removed when the class name alias is removed as well. - */ -$container->alias('session.web', 'session.web.site') - ->alias('session', 'session.web.site') - ->alias('JSession', 'session.web.site') - ->alias(\Joomla\CMS\Session\Session::class, 'session.web.site') - ->alias(\Joomla\Session\Session::class, 'session.web.site') - ->alias(\Joomla\Session\SessionInterface::class, 'session.web.site'); + // Alias the web logger to the PSR-3 interface as this is the primary logger for the environment + $container->alias(Monolog\Logger::class, 'monolog.logger.application.web') + ->alias(Psr\Log\LoggerInterface::class, 'monolog.logger.application.web'); +} +catch (\Throwable $e) +{ + error_log($e); -// Instantiate the application. -$app = $container->get(\Joomla\CMS\Application\SiteApplication::class); + header('HTTP/1.1 500 Internal Server Error', null, 500); + echo 'Container Initialization Error

Container Initialization Error

An error occurred while creating the DI container: ' . $e->getMessage() . '

'; -// Set the application as global app -\Joomla\CMS\Factory::$application = $app; + exit(1); +} -// Execute the application. -$app->execute(); +// Execute the application +// source: https://github.com/joomla/framework.joomla.org/blob/master/www/index.php#L85 +try +{ + $app = $container->get(Joomla\Application\AbstractApplication::class); + // Set the application as global app + \Octoleo\CMS\Factory::$application = $app; + // Execute the application. + $app->execute(); +} +catch (\Throwable $e) +{ + error_log($e); + + if (!headers_sent()) + { + header('HTTP/1.1 500 Internal Server Error', null, 500); + header('Content-Type: text/html; charset=utf-8'); + } + + echo 'Application Error

Application Error

An error occurred while executing the application: ' . $e->getMessage() . '

'; + + exit(1); +} +// I am just playing around... ((ewɘ))yn purring \ No newline at end of file diff --git a/week-03/project/includes/defines.php b/week-03/project/includes/defines.php index 1b89ecb..b95081f 100644 --- a/week-03/project/includes/defines.php +++ b/week-03/project/includes/defines.php @@ -1,26 +1,23 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; +defined('_LEXEC') or die; // Global definitions -$parts = explode(DIRECTORY_SEPARATOR, JPATH_BASE); +$parts = explode(DIRECTORY_SEPARATOR, LPATH_BASE); // Defines. -define('JPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts)); -define('JPATH_SITE', JPATH_ROOT); -define('JPATH_CONFIGURATION', JPATH_ROOT); -define('JPATH_ADMINISTRATOR', JPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator'); -define('JPATH_LIBRARIES', JPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries'); -define('JPATH_PLUGINS', JPATH_ROOT . DIRECTORY_SEPARATOR . 'plugins'); -define('JPATH_INSTALLATION', JPATH_ROOT . DIRECTORY_SEPARATOR . 'installation'); -define('JPATH_THEMES', JPATH_BASE . DIRECTORY_SEPARATOR . 'templates'); -define('JPATH_CACHE', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'cache'); -define('JPATH_MANIFESTS', JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'manifests'); -define('JPATH_API', JPATH_ROOT . DIRECTORY_SEPARATOR . 'api'); -define('JPATH_CLI', JPATH_ROOT . DIRECTORY_SEPARATOR . 'cli'); +define('LPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts)); +define('LPATH_SITE', LPATH_ROOT); +define('LPATH_CONFIGURATION', LPATH_ROOT); +define('LPATH_ADMINISTRATOR', LPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator'); +define('LPATH_LIBRARIES', LPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries'); +define('LPATH_INSTALLATION', LPATH_ROOT . DIRECTORY_SEPARATOR . 'installation'); +define('LPATH_TEMPLATES', LPATH_ROOT . DIRECTORY_SEPARATOR . 'templates/site'); diff --git a/week-03/project/includes/framework.php b/week-03/project/includes/framework.php index 94d5e7f..1e4cbff 100644 --- a/week-03/project/includes/framework.php +++ b/week-03/project/includes/framework.php @@ -1,25 +1,26 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; - -use Joomla\CMS\Version; -use Joomla\Utilities\IpHelper; +defined('_LEXEC') or die; // System includes -require_once JPATH_LIBRARIES . '/bootstrap.php'; +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/framework.php#L14 +require_once LPATH_LIBRARIES . '/bootstrap.php'; -// Installation check, and check on removal of the install directory. -if (!file_exists(JPATH_CONFIGURATION . '/configuration.php') - || (filesize(JPATH_CONFIGURATION . '/configuration.php') < 10) - || (file_exists(JPATH_INSTALLATION . '/index.php') && (false === (new Version)->isInDevelopmentState()))) +// Installation check, and check on removal of the installation directory. +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/framework.php#L17 +if (!file_exists(LPATH_CONFIGURATION . '/octoconfig.php') + || (filesize(LPATH_CONFIGURATION . '/octoconfig.php') < 10) + || (file_exists(LPATH_INSTALLATION . '/index.php'))) { - if (file_exists(JPATH_INSTALLATION . '/index.php')) + if (file_exists(LPATH_INSTALLATION . '/index.php')) { header('Location: ' . substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], 'index.php')) . 'installation/index.php'); @@ -32,92 +33,3 @@ if (!file_exists(JPATH_CONFIGURATION . '/configuration.php') exit; } } - -// Pre-Load configuration. Don't remove the Output Buffering due to BOM issues, see JCode 26026 -ob_start(); -require_once JPATH_CONFIGURATION . '/configuration.php'; -ob_end_clean(); - -// System configuration. -$config = new JConfig; - -// Set the error_reporting, and adjust a global Error Handler -switch ($config->error_reporting) -{ - case 'default': - case '-1': - - break; - - case 'none': - case '0': - error_reporting(0); - - break; - - case 'simple': - error_reporting(E_ERROR | E_WARNING | E_PARSE); - ini_set('display_errors', 1); - - break; - - case 'maximum': - case 'development': // <= Stays for backward compatibility, @TODO: can be removed in 5.0 - error_reporting(E_ALL); - ini_set('display_errors', 1); - - break; - - default: - error_reporting($config->error_reporting); - ini_set('display_errors', 1); - - break; -} - -if (!defined('JDEBUG')) -{ - define('JDEBUG', $config->debug); -} - -// Check deprecation logging -if (empty($config->log_deprecated)) -{ - // Reset handler for E_USER_DEPRECATED - set_error_handler(null, E_USER_DEPRECATED); -} -else -{ - // Make sure handler for E_USER_DEPRECATED is registered - set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED); -} - -if (JDEBUG || $config->error_reporting === 'maximum') -{ - // Set new Exception handler with debug enabled - $errorHandler->setExceptionHandler( - [ - new \Symfony\Component\ErrorHandler\ErrorHandler(null, true), - 'renderException' - ] - ); -} - -/** - * Correctly set the allowing of IP Overrides if behind a trusted proxy/load balancer. - * - * We need to do this as high up the stack as we can, as the default in \Joomla\Utilities\IpHelper is to - * $allowIpOverride = true which is the wrong default for a generic site NOT behind a trusted proxy/load balancer. - */ -if (property_exists($config, 'behind_loadbalancer') && $config->behind_loadbalancer == 1) -{ - // If Joomla is configured to be behind a trusted proxy/load balancer, allow HTTP Headers to override the REMOTE_ADDR - IpHelper::setAllowIpOverrides(true); -} -else -{ - // We disable the allowing of IP overriding using headers by default. - IpHelper::setAllowIpOverrides(false); -} - -unset($config); diff --git a/week-03/project/index.php b/week-03/project/index.php index c2b6893..e55461f 100644 --- a/week-03/project/index.php +++ b/week-03/project/index.php @@ -1,22 +1,25 @@ + * @created 3rd April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ // NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/index.php#L9 -// Define the application's minimum supported PHP version as a constant so it can be referenced within the application. -define('JOOMLA_MINIMUM_PHP', '7.2.5'); +// Define the application's minimum supported PHP version as a constant, so it can be referenced within the application. +define('OCTOLEO_MINIMUM_PHP', '7.2.5'); -if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) +if (version_compare(PHP_VERSION, OCTOLEO_MINIMUM_PHP, '<')) { die( str_replace( '{{phpversion}}', - JOOMLA_MINIMUM_PHP, + OCTOLEO_MINIMUM_PHP, file_get_contents(dirname(__FILE__) . '/templates/system/incompatible.html') ) ); @@ -24,9 +27,9 @@ if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) /** * Constant that is checked in included files to prevent direct access. - * define() is used rather than "const" to not error for PHP 5.2 and lower */ -define('_JEXEC', 1); +define('_LEXEC', 1); -// Run the application - All executable code should be triggered through this file +// We must setup some house rules, since we can't have all +// this code just doing what it wants can we?... <>yn growling require_once dirname(__FILE__) . '/includes/app.php'; diff --git a/week-03/project/installation/includes/app.php b/week-03/project/installation/includes/app.php new file mode 100644 index 0000000..9aa0219 --- /dev/null +++ b/week-03/project/installation/includes/app.php @@ -0,0 +1,31 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_LEXEC') or die; + +// Option to override defines from root folder +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L15 +if (file_exists(dirname(__DIR__) . '/defines.php')) +{ + include_once dirname(__DIR__) . '/defines.php'; +} + +// Load the default defines +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/includes/app.php#L20 +if (!defined('_LDEFINES')) +{ + define('LPATH_BASE', dirname(__DIR__)); + require_once LPATH_BASE . '/includes/defines.php'; +} + +// I have not yet had time to finish this part of the application (CMS) +echo file_get_contents(LPATH_ROOT . '/templates/system/install_notice.html'); + +exit; diff --git a/week-03/project/installation/includes/defines.php b/week-03/project/installation/includes/defines.php new file mode 100644 index 0000000..20db660 --- /dev/null +++ b/week-03/project/installation/includes/defines.php @@ -0,0 +1,23 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_LEXEC') or die; + +// Global definitions +$parts = explode(DIRECTORY_SEPARATOR, LPATH_BASE); +array_pop($parts); + +// Defines. +define('LPATH_ROOT', implode(DIRECTORY_SEPARATOR, $parts)); +define('LPATH_SITE', LPATH_ROOT); +define('LPATH_CONFIGURATION', LPATH_ROOT); +define('LPATH_ADMINISTRATOR', LPATH_ROOT . DIRECTORY_SEPARATOR . 'administrator'); +define('LPATH_LIBRARIES', LPATH_ROOT . DIRECTORY_SEPARATOR . 'libraries'); +define('LPATH_INSTALLATION', LPATH_ROOT . DIRECTORY_SEPARATOR . 'installation'); diff --git a/week-03/project/installation/includes/framework.php b/week-03/project/installation/includes/framework.php new file mode 100644 index 0000000..6643c3e --- /dev/null +++ b/week-03/project/installation/includes/framework.php @@ -0,0 +1,41 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_LEXEC') or die; + +// System includes +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/administrator/includes/framework.php#L14 +require_once LPATH_LIBRARIES . '/bootstrap.php'; + +// Installation check, and check on removal of the installation directory. +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/administrator/includes/framework.php#L17 +if (!file_exists(LPATH_CONFIGURATION . '/octoconfig.php') + || (filesize(LPATH_CONFIGURATION . '/octoconfig.php') < 10) + || (file_exists(LPATH_INSTALLATION . '/index.php'))) +{ + if (file_exists(LPATH_INSTALLATION . '/index.php')) + { + header('Location: ../installation/index.php'); + + exit; + } + else + { + echo 'No configuration file found and no installation code available. Exiting...'; + + exit; + } +} + +// Pre-Load configuration. Don't remove the Output Buffering due to BOM issues. +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/administrator/includes/framework.php#L36 +ob_start(); +require_once LPATH_CONFIGURATION . '/octoconfig.php'; +ob_end_clean(); diff --git a/week-03/project/installation/index.php b/week-03/project/installation/index.php new file mode 100644 index 0000000..50766b7 --- /dev/null +++ b/week-03/project/installation/index.php @@ -0,0 +1,35 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/index.php#L9 + +// Define the application's minimum supported PHP version as a constant, so it can be referenced within the application. +define('OCTOLEO_MINIMUM_PHP', '7.2.5'); + +if (version_compare(PHP_VERSION, OCTOLEO_MINIMUM_PHP, '<')) +{ + die( + str_replace( + '{{phpversion}}', + OCTOLEO_MINIMUM_PHP, + file_get_contents(dirname(__FILE__) . '/../templates/system/incompatible.html') + ) + ); +} + +/** + * Constant that is checked in included files to prevent direct access. + */ +define('_LEXEC', 1); + +// We must setup some house rules, since we can't have all +// this code just doing what it wants can we.... <>yn growling +require_once dirname(__FILE__) . '/includes/app.php'; \ No newline at end of file diff --git a/week-03/project/libraries/bootstrap.php b/week-03/project/libraries/bootstrap.php index 54a5976..2130e47 100644 --- a/week-03/project/libraries/bootstrap.php +++ b/week-03/project/libraries/bootstrap.php @@ -1,16 +1,18 @@ - * @license GNU General Public License version 2 or later; see LICENSE + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; +defined('_LEXEC') or die; // Set the platform root path as a constant if necessary. -defined('JPATH_PLATFORM') or define('JPATH_PLATFORM', __DIR__); +// source: https://github.com/joomla/joomla-cms/blob/4.1-dev/libraries/bootstrap.php#L12 +defined('LPATH_PLATFORM') or define('LPATH_PLATFORM', __DIR__); // Detect the native operating system type. $os = strtoupper(substr(PHP_OS, 0, 3)); @@ -19,72 +21,28 @@ defined('IS_WIN') or define('IS_WIN', ($os === 'WIN')); defined('IS_UNIX') or define('IS_UNIX', (($os !== 'MAC') && ($os !== 'WIN'))); // Import the library loader if necessary. -if (!class_exists('JLoader')) +if (!class_exists('LLoader')) { - require_once JPATH_PLATFORM . '/loader.php'; + require_once LPATH_PLATFORM . '/loader.php'; // If JLoader still does not exist panic. - if (!class_exists('JLoader')) + if (!class_exists('LLoader')) { - throw new RuntimeException('Joomla Platform not loaded.'); + throw new RuntimeException('Octoleo Platform not loaded.'); } } // Setup the autoloaders. -JLoader::setup(); +LLoader::setup(); // Create the Composer autoloader /** @var \Composer\Autoload\ClassLoader $loader */ -$loader = require JPATH_LIBRARIES . '/vendor/autoload.php'; +$loader = require LPATH_LIBRARIES . '/vendor/autoload.php'; // We need to pull our decorated class loader into memory before unregistering Composer's loader -class_exists('\\Joomla\\CMS\\Autoload\\ClassLoader'); +class_exists('\\Octoleo\\CMS\\Autoload\\ClassLoader'); $loader->unregister(); // Decorate Composer autoloader -spl_autoload_register([new \Joomla\CMS\Autoload\ClassLoader($loader), 'loadClass'], true, true); - -// Register the class aliases for Framework classes that have replaced their Platform equivalents -require_once JPATH_LIBRARIES . '/classmap.php'; - -/** - * Register the global exception handler. And set error level to server default error level. - * The error level may be changed later in boot up process, after application config will be loaded. - * Do not remove the variable, to allow to use it further, after including this file. - */ -$errorHandler = \Symfony\Component\ErrorHandler\ErrorHandler::register(); -\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::setTemplate(__DIR__ . '/../templates/system/fatal.php'); - -// Register the error handler which processes E_USER_DEPRECATED errors -if (error_reporting() & E_USER_DEPRECATED) -{ - set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED); -} - -// Suppress phar stream wrapper for non .phar files -$behavior = new \TYPO3\PharStreamWrapper\Behavior; -\TYPO3\PharStreamWrapper\Manager::initialize( - $behavior->withAssertion(new \TYPO3\PharStreamWrapper\Interceptor\PharExtensionInterceptor) -); - -if (in_array('phar', stream_get_wrappers())) -{ - stream_wrapper_unregister('phar'); - stream_wrapper_register('phar', 'TYPO3\\PharStreamWrapper\\PharStreamWrapper'); -} - -// Define the Joomla version if not already defined. -defined('JVERSION') or define('JVERSION', (new \Joomla\CMS\Version)->getShortVersion()); - -// Set up the message queue logger for web requests -if (array_key_exists('REQUEST_METHOD', $_SERVER)) -{ - \Joomla\CMS\Log\Log::addLogger(['logger' => 'messagequeue'], \Joomla\CMS\Log\Log::ALL, ['jerror']); -} - -// Register the Crypto lib -JLoader::register('Crypto', JPATH_PLATFORM . '/php-encryption/Crypto.php'); - -// Register the PasswordHash library. -JLoader::register('PasswordHash', JPATH_PLATFORM . '/phpass/PasswordHash.php'); +spl_autoload_register([new \Octoleo\CMS\Autoload\ClassLoader($loader), 'loadClass'], true, true); diff --git a/week-03/project/libraries/loader.php b/week-03/project/libraries/loader.php index 2389dca..f04d40f 100644 --- a/week-03/project/libraries/loader.php +++ b/week-03/project/libraries/loader.php @@ -1,19 +1,24 @@ - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ + * @source https://github.com/joomla/joomla-cms/blob/4.1-dev/libraries/loader.php + * @adapted Llewellyn van der Merwe + * + * @copyright (C) 2005 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + **/ -defined('JPATH_PLATFORM') or die; +defined('LPATH_PLATFORM') or die; /** * Static class to handle loading of libraries. * - * @since 1.7.0 + * @since 1.0.0 */ -abstract class JLoader +abstract class LLoader { /** * Container for already imported library paths. @@ -79,61 +84,6 @@ abstract class JLoader */ protected static $extensionRootFolders = array(); - /** - * Method to discover classes of a given type in a given path. - * - * @param string $classPrefix The class name prefix to use for discovery. - * @param string $parentPath Full path to the parent folder for the classes to discover. - * @param boolean $force True to overwrite the autoload path value for the class if it already exists. - * @param boolean $recurse Recurse through all child directories as well as the parent path. - * - * @return void - * - * @since 1.7.0 - * @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for - * your files. - */ - public static function discover($classPrefix, $parentPath, $force = true, $recurse = false) - { - try - { - if ($recurse) - { - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($parentPath), - RecursiveIteratorIterator::SELF_FIRST - ); - } - else - { - $iterator = new DirectoryIterator($parentPath); - } - - /** @type $file DirectoryIterator */ - foreach ($iterator as $file) - { - $fileName = $file->getFilename(); - - // Only load for php files. - if ($file->isFile() && $file->getExtension() === 'php') - { - // Get the class name and full path for each file. - $class = strtolower($classPrefix . preg_replace('#\.php$#', '', $fileName)); - - // Register the class with the autoloader if not already registered or the force flag is set. - if ($force || empty(self::$classes[$class])) - { - self::register($class, $file->getPath() . '/' . $fileName); - } - } - } - } - catch (UnexpectedValueException $e) - { - // Exception will be thrown if the path is not a directory. Ignore it. - } - } - /** * Method to get the list of registered classes and their respective file paths for the autoloader. * @@ -170,74 +120,6 @@ abstract class JLoader return self::$namespaces; } - /** - * Loads a class from specified directories. - * - * @param string $key The class name to look for (dot notation). - * @param string $base Search this directory for the class. - * - * @return boolean True on success. - * - * @since 1.7.0 - * @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for - * your files. - */ - public static function import($key, $base = null) - { - // Only import the library if not already attempted. - if (!isset(self::$imported[$key])) - { - // Setup some variables. - $success = false; - $parts = explode('.', $key); - $class = array_pop($parts); - $base = (!empty($base)) ? $base : __DIR__; - $path = str_replace('.', DIRECTORY_SEPARATOR, $key); - - // Handle special case for helper classes. - if ($class === 'helper') - { - $class = ucfirst(array_pop($parts)) . ucfirst($class); - } - // Standard class. - else - { - $class = ucfirst($class); - } - - // If we are importing a library from the Joomla namespace set the class to autoload. - if (strpos($path, 'joomla') === 0) - { - // Since we are in the Joomla namespace prepend the classname with J. - $class = 'J' . $class; - - // Only register the class for autoloading if the file exists. - if (is_file($base . '/' . $path . '.php')) - { - self::$classes[strtolower($class)] = $base . '/' . $path . '.php'; - $success = true; - } - } - /* - * If we are not importing a library from the Joomla namespace directly include the - * file since we cannot assert the file/folder naming conventions. - */ - else - { - // If the file exists attempt to include it. - if (is_file($base . '/' . $path . '.php')) - { - $success = (bool) include_once $base . '/' . $path . '.php'; - } - } - - // Add the import key to the memory cache container. - self::$imported[$key] = $success; - } - - return self::$imported[$key]; - } - /** * Load the file for a class. * @@ -287,41 +169,6 @@ abstract class JLoader return false; } - /** - * Directly register a class to the autoload list. - * - * @param string $class The class name to register. - * @param string $path Full path to the file that holds the class to register. - * @param boolean $force True to overwrite the autoload path value for the class if it already exists. - * - * @return void - * - * @since 1.7.0 - * @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for - * your files. - */ - public static function register($class, $path, $force = true) - { - // When an alias exists, register it as well - if (array_key_exists(strtolower($class), self::$classAliases)) - { - self::register(self::stripFirstBackslash(self::$classAliases[strtolower($class)]), $path, $force); - } - - // Sanitize class name. - $class = strtolower($class); - - // Only attempt to register the class if the name and file exist. - if (!empty($class) && is_file($path)) - { - // Register the class with the autoloader if not already registered or the force flag is set. - if ($force || empty(self::$classes[$class])) - { - self::$classes[$class] = $path; - } - } - } - /** * Register a class prefix with lookup path. This will allow developers to register library * packages with different class prefixes to the system autoloader. More than one lookup path @@ -345,7 +192,7 @@ abstract class JLoader // Verify the library path exists. if (!is_dir($path)) { - $path = (str_replace(JPATH_ROOT, '', $path) == $path) ? basename($path) : str_replace(JPATH_ROOT, '', $path); + $path = (str_replace(LPATH_ROOT, '', $path) == $path) ? basename($path) : str_replace(LPATH_ROOT, '', $path); throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500); } @@ -432,7 +279,7 @@ abstract class JLoader // Verify the library path exists. if (!is_dir($path)) { - $path = (str_replace(JPATH_ROOT, '', $path) == $path) ? basename($path) : str_replace(JPATH_ROOT, '', $path); + $path = (str_replace(LPATH_ROOT, '', $path) == $path) ? basename($path) : str_replace(LPATH_ROOT, '', $path); throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500); } @@ -461,15 +308,15 @@ abstract class JLoader } /** - * Method to setup the autoloaders for the Joomla Platform. + * Method to setup the autoloaders for the Octoleo Platform. * Since the SPL autoloaders are called in a queue we will add our explicit * class-registration based loader first, then fall back on the autoloader based on conventions. * This will allow people to register a class in a specific location and override platform libraries * as was previously possible. * * @param boolean $enablePsr True to enable autoloading based on PSR-0. - * @param boolean $enablePrefixes True to enable prefix based class loading (needed to auto load the Joomla core). - * @param boolean $enableClasses True to enable class map based class loading (needed to auto load the Joomla core). + * @param boolean $enablePrefixes True to enable prefix based class loading (needed to auto load the Octoleo core). + * @param boolean $enableClasses True to enable class map based class loading (needed to auto load the Octoleo core). * * @return void * @@ -480,20 +327,20 @@ abstract class JLoader if ($enableClasses) { // Register the class map based autoloader. - spl_autoload_register(array('JLoader', 'load')); + spl_autoload_register(array('LLoader', 'load')); } if ($enablePrefixes) { // Register the prefix autoloader. - spl_autoload_register(array('JLoader', '_autoload')); + spl_autoload_register(array('LLoader', '_autoload')); } if ($enablePsr) { // Register the PSR based autoloader. - spl_autoload_register(array('JLoader', 'loadByPsr')); - spl_autoload_register(array('JLoader', 'loadByAlias')); + spl_autoload_register(array('LLoader', 'loadByPsr')); + spl_autoload_register(array('LLoader', 'loadByAlias')); } } @@ -505,7 +352,7 @@ abstract class JLoader * @return boolean True on success, false otherwise. * * @since 3.7.0 - * @deprecated 5.0 Use JLoader::loadByPsr instead + * @deprecated 5.0 Use LLoader::loadByPsr instead */ public static function loadByPsr4($class) { @@ -750,41 +597,3 @@ abstract class JLoader return $class && $class[0] === '\\' ? substr($class, 1) : $class; } } - -// Check if jexit is defined first (our unit tests mock this) -if (!function_exists('jexit')) -{ - /** - * Global application exit. - * - * This function provides a single exit point for the platform. - * - * @param mixed $message Exit code or string. Defaults to zero. - * - * @return void - * - * @codeCoverageIgnore - * @since 1.7.0 - */ - function jexit($message = 0) - { - exit($message); - } -} - -/** - * Intelligent file importer. - * - * @param string $path A dot syntax path. - * @param string $base Search this directory for the class. - * - * @return boolean True on success. - * - * @since 1.7.0 - * @deprecated 5.0 Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to register an autoloader for - * your files. - */ -function jimport($path, $base = null) -{ - return JLoader::import($path, $base); -} diff --git a/week-03/project/libraries/src/Application/AdminApplication.php b/week-03/project/libraries/src/Application/AdminApplication.php index ff6b81c..b1aaa64 100644 --- a/week-03/project/libraries/src/Application/AdminApplication.php +++ b/week-03/project/libraries/src/Application/AdminApplication.php @@ -6,10 +6,12 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite; +namespace Octoleo\CMS\Application; use Joomla\Application\AbstractWebApplication; use Joomla\Application\Controller\ControllerResolverInterface; +use Joomla\Application\SessionAwareWebApplicationInterface; +use Joomla\Application\SessionAwareWebApplicationTrait; use Joomla\Application\Web\WebClient; use Joomla\Input\Input; use Joomla\Registry\Registry; @@ -17,10 +19,13 @@ use Joomla\Router\RouterInterface; use Psr\Http\Message\ResponseInterface; /** - * Web application class + * Site application class + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/WebApplication.php */ -class WebApplication extends AbstractWebApplication +class AdminApplication extends AbstractWebApplication implements SessionAwareWebApplicationInterface, SessionMessageAwareInterface, IdentityAwareInterface { + use IdentityAwareTrait, SessionMessageAwareTrait, SessionAwareWebApplicationTrait; + /** * The application's controller resolver. * @@ -82,4 +87,4 @@ class WebApplication extends AbstractWebApplication \call_user_func($this->controllerResolver->resolve($route)); } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/Application/IdentityAwareInterface.php b/week-03/project/libraries/src/Application/IdentityAwareInterface.php new file mode 100644 index 0000000..3c5147d --- /dev/null +++ b/week-03/project/libraries/src/Application/IdentityAwareInterface.php @@ -0,0 +1,57 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Octoleo\CMS\Application; + +use Octoleo\CMS\User\User; +use Octoleo\CMS\User\UserFactoryInterface; + +interface IdentityAwareInterface +{ + /** + * Get the application identity. + * + * @return User + * + * @since 1.0.0 + */ + public function getIdentity(): User; + + /** + * Allows the application to load a custom or default identity. + * + * @param User $identity An optional identity object. If omitted, a null user object is created. + * + * @return $this + * + * @since 1.0.0 + */ + public function loadIdentity(User $identity = null): IdentityAwareInterface; + + /** + * Set the user factory to use. + * + * @param UserFactoryInterface $userFactory The user factory to use + * + * @return void + * + * @since 1.0.0 + */ + public function setUserFactory(UserFactoryInterface $userFactory); + + /** + * Get the user factory to use. + * + * @return UserFactoryInterface + * + * @since 1.0.0 + */ + public function getUserFactory(): UserFactoryInterface; +} diff --git a/week-03/project/libraries/src/Application/IdentityAwareTrait.php b/week-03/project/libraries/src/Application/IdentityAwareTrait.php index 03152ac..7f9e77b 100644 --- a/week-03/project/libraries/src/Application/IdentityAwareTrait.php +++ b/week-03/project/libraries/src/Application/IdentityAwareTrait.php @@ -6,25 +6,23 @@ * @license GNU General Public License version 2 or later; see LICENSE */ -namespace Joomla\CMS\Application; +namespace Octoleo\CMS\Application; -\defined('JPATH_PLATFORM') or die; - -use Joomla\CMS\User\User; -use Joomla\CMS\User\UserFactoryInterface; +use Octoleo\CMS\User\User; +use Octoleo\CMS\User\UserFactoryInterface; /** * Trait for application classes which are identity (user) aware * - * @since 4.0.0 + * @since 1.0.0 */ -trait IdentityAware +trait IdentityAwareTrait { /** * The application identity object. * * @var User - * @since 4.0.0 + * @since 1.0.0 */ protected $identity; @@ -32,7 +30,7 @@ trait IdentityAware * UserFactoryInterface * * @var UserFactoryInterface - * @since 4.0.0 + * @since 1.0.0 */ private $userFactory; @@ -41,9 +39,9 @@ trait IdentityAware * * @return User * - * @since 4.0.0 + * @since 1.0.0 */ - public function getIdentity() + public function getIdentity(): User { return $this->identity; } @@ -53,11 +51,11 @@ trait IdentityAware * * @param User $identity An optional identity object. If omitted, a null user object is created. * - * @return $this + * @return IdentityAwareInterface * - * @since 4.0.0 + * @since 1.0.0 */ - public function loadIdentity(User $identity = null) + public function loadIdentity(User $identity = null): IdentityAwareInterface { $this->identity = $identity ?: $this->userFactory->loadUserById(0); @@ -71,10 +69,23 @@ trait IdentityAware * * @return void * - * @since 4.0.0 + * @since 1.0.0 */ public function setUserFactory(UserFactoryInterface $userFactory) { $this->userFactory = $userFactory; } + + /** + * Get the user factory to use. + * + * @return UserFactoryInterface + * + * @since 1.0.0 + */ + public function getUserFactory(): UserFactoryInterface + { + return $this->userFactory; + } } + diff --git a/week-03/project/libraries/src/Application/SessionMessageAwareInterface.php b/week-03/project/libraries/src/Application/SessionMessageAwareInterface.php new file mode 100644 index 0000000..ce418fc --- /dev/null +++ b/week-03/project/libraries/src/Application/SessionMessageAwareInterface.php @@ -0,0 +1,44 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Octoleo\CMS\Application; + +/** + * Application Session Message Aware Interface + * + * @since 1.0.0 + */ +interface SessionMessageAwareInterface +{ + const MSG_INFO = 'info'; + + /** + * Enqueue a system message. + * + * @param string $msg The message to enqueue. + * @param string $type The message type. Default is message. + * + * @return void + * + * @since 3.2 + */ + public function enqueueMessage(string $msg, string $type = self::MSG_INFO); + + /** + * Get the system message queue. + * + * @param boolean $clear Clear the messages currently attached to the application object + * + * @return array The system message queue. + * + * @since 3.2 + */ + public function getMessageQueue(bool $clear = false): array; +} diff --git a/week-03/project/libraries/src/Application/SessionMessageAwareTrait.php b/week-03/project/libraries/src/Application/SessionMessageAwareTrait.php new file mode 100644 index 0000000..a1eab3e --- /dev/null +++ b/week-03/project/libraries/src/Application/SessionMessageAwareTrait.php @@ -0,0 +1,88 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Octoleo\CMS\Application; + +use Joomla\Filter\InputFilter as InputFilterAlias; +use Octoleo\CMS\Filter\InputFilter; + +/** + * Trait for application classes which are identity (user) aware + * + * @since 1.0.0 + */ +trait SessionMessageAwareTrait +{ + /** + * Enqueue a system message. + * + * @param string $msg The message to enqueue. + * @param string $type The message type. Default is message. + * + * @return void + * + * @since 1.0.0 + */ + public function enqueueMessage(string $msg, string $type = self::MSG_INFO) + { + // Don't add empty messages. + if ($msg === null || trim($msg) === '') + { + return; + } + + $inputFilter = InputFilter::getInstance( + [], + [], + InputFilterAlias::ONLY_BLOCK_DEFINED_TAGS, + InputFilterAlias::ONLY_BLOCK_DEFINED_ATTRIBUTES + ); + + // Build the message array and apply the HTML InputFilter with the default blacklist to the message + $message = array( + 'message' => $inputFilter->clean($msg, 'html'), + 'type' => $inputFilter->clean(strtolower($type), 'cmd'), + ); + + // For empty queue, if messages exists in the session, enqueue them first. + $messages = $this->getMessageQueue(); + + if (!\in_array($message, $messages)) + { + // Enqueue the message. + $messages[] = $message; + + // update the session + $this->getSession()->set('application.queue', $messages); + } + } + + /** + * Get the system message queue. + * + * @param boolean $clear Clear the messages currently attached to the application object + * + * @return array The system message queue. + * + * @since 1.0.0 + */ + public function getMessageQueue(bool $clear = false): array + { + // Get messages from Session + $sessionQueue = $this->getSession()->get('application.queue', []); + + if ($clear) + { + $this->getSession()->set('application.queue', []); + } + + return $sessionQueue; + } +} diff --git a/week-03/project/libraries/src/Application/SiteApplication.php b/week-03/project/libraries/src/Application/SiteApplication.php index ff6b81c..c381173 100644 --- a/week-03/project/libraries/src/Application/SiteApplication.php +++ b/week-03/project/libraries/src/Application/SiteApplication.php @@ -6,7 +6,7 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite; +namespace Octoleo\CMS\Application; use Joomla\Application\AbstractWebApplication; use Joomla\Application\Controller\ControllerResolverInterface; @@ -17,9 +17,10 @@ use Joomla\Router\RouterInterface; use Psr\Http\Message\ResponseInterface; /** - * Web application class + * Site application class + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/WebApplication.php */ -class WebApplication extends AbstractWebApplication +class SiteApplication extends AbstractWebApplication { /** * The application's controller resolver. @@ -82,4 +83,4 @@ class WebApplication extends AbstractWebApplication \call_user_func($this->controllerResolver->resolve($route)); } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/Asset/MixPathPackage.php b/week-03/project/libraries/src/Asset/MixPathPackage.php index a1626e7..59af91d 100644 --- a/week-03/project/libraries/src/Asset/MixPathPackage.php +++ b/week-03/project/libraries/src/Asset/MixPathPackage.php @@ -6,7 +6,7 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite\Asset; +namespace Octoleo\CMS\Asset; use Symfony\Component\Asset\Context\ContextInterface; use Symfony\Component\Asset\Package; @@ -15,6 +15,7 @@ use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface; /** * Extended path package for resolving assets from a Laravel Mix manifest + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Asset/MixPathPackage.php */ class MixPathPackage extends PathPackage { diff --git a/week-03/project/libraries/src/Autoload/ClassLoader.php b/week-03/project/libraries/src/Autoload/ClassLoader.php index 918028e..91f2399 100644 --- a/week-03/project/libraries/src/Autoload/ClassLoader.php +++ b/week-03/project/libraries/src/Autoload/ClassLoader.php @@ -6,17 +6,17 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\Autoload; +namespace Octoleo\CMS\Autoload; -\defined('_JEXEC') or die; +\defined('_LEXEC') or die; use Composer\Autoload\ClassLoader as ComposerClassLoader; /** - * Decorate Composer ClassLoader for Joomla! + * Decorate Composer ClassLoader for Octoleo! * * For backward compatibility due to class aliasing in the CMS, the loadClass() method was modified to call - * the JLoader::applyAliasFor() method. + * the LLoader::applyAliasFor() method. * * @since 3.4 */ @@ -55,7 +55,7 @@ class ClassLoader { if ($result = $this->loader->loadClass($class)) { - \JLoader::applyAliasFor($class); + \LLoader::applyAliasFor($class); } return $result; diff --git a/week-03/project/libraries/src/Controller/DashboardController.php b/week-03/project/libraries/src/Controller/DashboardController.php index 58bcc79..c324ad9 100644 --- a/week-03/project/libraries/src/Controller/DashboardController.php +++ b/week-03/project/libraries/src/Controller/DashboardController.php @@ -1,42 +1,47 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Controller; +namespace Octoleo\CMS\Controller; use Joomla\Application\AbstractApplication; use Joomla\Controller\AbstractController; -use Joomla\FrameworkWebsite\View\Package\PackageHtmlView; use Joomla\Input\Input; +use Joomla\Uri\Uri; +use Laminas\Diactoros\Response\RedirectResponse; +use Octoleo\CMS\View\Admin\DashboardHtmlView; use Laminas\Diactoros\Response\HtmlResponse; /** - * Controller handling a package's status data listing + * Controller handling the site's homepage * - * @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object. - * @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object + * @method \Octoleo\CMS\Application\AdminApplication getApplication() Get the application object. + * @property-read \Octoleo\CMS\Application\AdminApplication $app Application object */ -class PackageController extends AbstractController +class DashboardController extends AbstractController { /** * The view object. * - * @var PackageHtmlView + * @var DashboardHtmlView */ private $view; /** * Constructor. * - * @param PackageHtmlView $view The view object. - * @param Input $input The input object. - * @param AbstractApplication $app The application object. + * @param DashboardHtmlView $view The view object. + * @param Input $user The user object. + * @param Input $input The input object. + * @param AbstractApplication $app The application object. */ - public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null) + public function __construct(DashboardHtmlView $view, Input $input = null, AbstractApplication $app = null) { parent::__construct($input, $app); @@ -47,15 +52,61 @@ class PackageController extends AbstractController * Execute the controller. * * @return boolean + * @throws \Exception */ public function execute(): bool { + // our little access controller TODO: we can do better + $has_access = false; + // Enable browser caching $this->getApplication()->allowCache(true); - $this->view->setPackage($this->getInput()->getString('package')); + $dashboard = $this->getInput()->getString('dashboard', ''); + $id = $this->getInput()->getInt('id', 0); - $this->getApplication()->setResponse(new HtmlResponse($this->view->render())); + $this->view->setActiveDashboard($dashboard); + $this->view->setActiveId($id); + + /** @var \Octoleo\CMS\User\UserFactory $userFactory */ + $userFactory = $this->getApplication()->getUserFactory(); + + // user actions [access, signup] + if ('access' === $dashboard || 'signup' === $dashboard || 'logout' === $dashboard) + { + if ('access' === $dashboard && $userFactory->login()) + { + $has_access = true; + } + elseif ('signup' === $dashboard && $userFactory->create()) + { + $has_access = true; + } + elseif ('logout' === $dashboard && $userFactory->logout()) + { + $has_access = false; + } + + // we by default always load the dashboard + $this->view->setActiveDashboard('dashboard'); + } + elseif ($userFactory->active()) + { + $has_access = true; + } + + if ($has_access) + { + $this->getApplication()->setResponse(new HtmlResponse($this->view->render())); + } + else + { + // get uri request to get host + $uri = new Uri($this->getApplication()->get('uri.request')); + + // Redirect to the administrator area + $this->getApplication()->redirect($uri->getScheme() . '://' . $uri->getHost() . '/administrator/'); + } return true; } diff --git a/week-03/project/libraries/src/Controller/HomepageController.php b/week-03/project/libraries/src/Controller/HomepageController.php index 58bcc79..fc90113 100644 --- a/week-03/project/libraries/src/Controller/HomepageController.php +++ b/week-03/project/libraries/src/Controller/HomepageController.php @@ -1,46 +1,48 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Controller; +namespace Octoleo\CMS\Controller; use Joomla\Application\AbstractApplication; use Joomla\Controller\AbstractController; -use Joomla\FrameworkWebsite\View\Package\PackageHtmlView; use Joomla\Input\Input; +use Joomla\Renderer\RendererInterface; use Laminas\Diactoros\Response\HtmlResponse; /** - * Controller handling a package's status data listing + * Controller handling the site's homepage * - * @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object. - * @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object + * @method \Octoleo\CMS\Application\SiteApplication getApplication() Get the application object. + * @property-read \Octoleo\CMS\Application\SiteApplication $app Application object */ -class PackageController extends AbstractController +class HomepageController extends AbstractController { /** - * The view object. + * The template renderer. * - * @var PackageHtmlView + * @var RendererInterface */ - private $view; + private $renderer; /** * Constructor. * - * @param PackageHtmlView $view The view object. - * @param Input $input The input object. - * @param AbstractApplication $app The application object. + * @param RendererInterface $renderer The template renderer. + * @param Input $input The input object. + * @param AbstractApplication $app The application object. */ - public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null) + public function __construct(RendererInterface $renderer, Input $input = null, AbstractApplication $app = null) { parent::__construct($input, $app); - $this->view = $view; + $this->renderer = $renderer; } /** @@ -53,9 +55,7 @@ class PackageController extends AbstractController // Enable browser caching $this->getApplication()->allowCache(true); - $this->view->setPackage($this->getInput()->getString('package')); - - $this->getApplication()->setResponse(new HtmlResponse($this->view->render())); + $this->getApplication()->setResponse(new HtmlResponse($this->renderer->render('homepage.twig'))); return true; } diff --git a/week-03/project/libraries/src/Controller/LoginController.php b/week-03/project/libraries/src/Controller/LoginController.php index 58bcc79..5745503 100644 --- a/week-03/project/libraries/src/Controller/LoginController.php +++ b/week-03/project/libraries/src/Controller/LoginController.php @@ -1,46 +1,48 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Controller; +namespace Octoleo\CMS\Controller; use Joomla\Application\AbstractApplication; use Joomla\Controller\AbstractController; -use Joomla\FrameworkWebsite\View\Package\PackageHtmlView; use Joomla\Input\Input; +use Joomla\Renderer\RendererInterface; use Laminas\Diactoros\Response\HtmlResponse; /** - * Controller handling a package's status data listing + * Controller handling the site's homepage * - * @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object. - * @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object + * @method \Octoleo\CMS\Application\SiteApplication getApplication() Get the application object. + * @property-read \Octoleo\CMS\Application\SiteApplication $app Application object */ -class PackageController extends AbstractController +class LoginController extends AbstractController { /** - * The view object. + * The template renderer. * - * @var PackageHtmlView + * @var RendererInterface */ - private $view; + private $renderer; /** * Constructor. * - * @param PackageHtmlView $view The view object. - * @param Input $input The input object. - * @param AbstractApplication $app The application object. + * @param RendererInterface $renderer The template renderer. + * @param Input $input The input object. + * @param AbstractApplication $app The application object. */ - public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null) + public function __construct(RendererInterface $renderer, Input $input = null, AbstractApplication $app = null) { parent::__construct($input, $app); - $this->view = $view; + $this->renderer = $renderer; } /** @@ -53,9 +55,16 @@ class PackageController extends AbstractController // Enable browser caching $this->getApplication()->allowCache(true); - $this->view->setPackage($this->getInput()->getString('package')); + $task = $this->getInput()->getString('account', null); - $this->getApplication()->setResponse(new HtmlResponse($this->view->render())); + if ('signup' === $task) + { + $this->getApplication()->setResponse(new HtmlResponse($this->renderer->render('signup.twig'))); + } + else + { + $this->getApplication()->setResponse(new HtmlResponse($this->renderer->render('login.twig'))); + } return true; } diff --git a/week-03/project/libraries/src/Controller/PageController.php b/week-03/project/libraries/src/Controller/PageController.php index 58bcc79..ad246d3 100644 --- a/week-03/project/libraries/src/Controller/PageController.php +++ b/week-03/project/libraries/src/Controller/PageController.php @@ -1,42 +1,46 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Controller; +namespace Octoleo\CMS\Controller; use Joomla\Application\AbstractApplication; use Joomla\Controller\AbstractController; -use Joomla\FrameworkWebsite\View\Package\PackageHtmlView; use Joomla\Input\Input; +use Joomla\Uri\Uri; +use Octoleo\CMS\View\Page\PageHtmlView; use Laminas\Diactoros\Response\HtmlResponse; +use Laminas\Diactoros\Response\RedirectResponse; /** - * Controller handling a package's status data listing + * Controller handling the site's simple text pages * - * @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object. - * @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object + * @method \Octoleo\CMS\Application\SiteApplication getApplication() Get the application object. + * @property-read \Octoleo\CMS\Application\SiteApplication $app Application object */ -class PackageController extends AbstractController +class PageController extends AbstractController { /** * The view object. * - * @var PackageHtmlView + * @var PageHtmlView */ private $view; /** * Constructor. * - * @param PackageHtmlView $view The view object. - * @param Input $input The input object. - * @param AbstractApplication $app The application object. + * @param PageHtmlView $view The view object. + * @param Input $input The input object. + * @param AbstractApplication $app The application object. */ - public function __construct(PackageHtmlView $view, Input $input = null, AbstractApplication $app = null) + public function __construct(PageHtmlView $view, Input $input = null, AbstractApplication $app = null) { parent::__construct($input, $app); @@ -53,9 +57,25 @@ class PackageController extends AbstractController // Enable browser caching $this->getApplication()->allowCache(true); - $this->view->setPackage($this->getInput()->getString('package')); + $page = $this->getInput()->getString('view', ''); + $details = $this->getInput()->getString('details', ''); - $this->getApplication()->setResponse(new HtmlResponse($this->view->render())); + // if for some reason the view value is administrator + if ('administrator' === $page) + { + // get uri request to get host + $uri = new Uri($this->getApplication()->get('uri.request')); + + // Redirect to the administrator area + $this->getApplication()->setResponse(new RedirectResponse($uri->getScheme() . '://' . $uri->getHost() . '/administrator/', 301)); + } + else + { + $this->view->setPage($page); + $this->view->setDetails($details); + + $this->getApplication()->setResponse(new HtmlResponse($this->view->render())); + } return true; } diff --git a/week-03/project/libraries/src/Controller/WrongCmsController.php b/week-03/project/libraries/src/Controller/WrongCmsController.php index 8ab023e..701e222 100644 --- a/week-03/project/libraries/src/Controller/WrongCmsController.php +++ b/week-03/project/libraries/src/Controller/WrongCmsController.php @@ -1,12 +1,14 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Controller; +namespace Octoleo\CMS\Controller; use Joomla\Controller\AbstractController; use Laminas\Diactoros\Response\TextResponse; @@ -14,8 +16,8 @@ use Laminas\Diactoros\Response\TextResponse; /** * Controller class to display a message to individuals looking for the wrong CMS * - * @method \Joomla\FrameworkWebsite\WebApplication getApplication() Get the application object. - * @property-read \Joomla\FrameworkWebsite\WebApplication $app Application object + * @method \Octoleo\CMS\Application\SiteApplication getApplication() Get the application object. + * @property-read \Octoleo\CMS\Application\SiteApplication $app Application object */ class WrongCmsController extends AbstractController { diff --git a/week-03/project/libraries/src/Date/Date.php b/week-03/project/libraries/src/Date/Date.php index c26cc0f..7573d13 100644 --- a/week-03/project/libraries/src/Date/Date.php +++ b/week-03/project/libraries/src/Date/Date.php @@ -6,13 +6,10 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\Date; +namespace Octoleo\CMS\Date; -\defined('JPATH_PLATFORM') or die; - -use Joomla\CMS\Factory; -use Joomla\CMS\Language\Text; -use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseInterface; +use Octoleo\CMS\Factory; /** * Date is a class that stores a date and provides logic to manipulate @@ -249,19 +246,19 @@ class Date extends \DateTime switch ($day) { case 0: - return $abbr ? Text::_('SUN') : Text::_('SUNDAY'); + return $abbr ? 'Sun' : 'Sunday'; case 1: - return $abbr ? Text::_('MON') : Text::_('MONDAY'); + return $abbr ? 'Mon' : 'Monday'; case 2: - return $abbr ? Text::_('TUE') : Text::_('TUESDAY'); + return $abbr ? 'Tue' : 'Tuesday'; case 3: - return $abbr ? Text::_('WED') : Text::_('WEDNESDAY'); + return $abbr ? 'Wed' : 'Wednesday'; case 4: - return $abbr ? Text::_('THU') : Text::_('THURSDAY'); + return $abbr ? 'Thu' : 'Thursday'; case 5: - return $abbr ? Text::_('FRI') : Text::_('FRIDAY'); + return $abbr ? 'Fri' : 'Friday'; case 6: - return $abbr ? Text::_('SAT') : Text::_('SATURDAY'); + return $abbr ? 'Sat' : 'Saturday'; } } @@ -374,29 +371,29 @@ class Date extends \DateTime switch ($month) { case 1: - return $abbr ? Text::_('JANUARY_SHORT') : Text::_('JANUARY'); + return $abbr ? 'Jan' : 'January'; // case 2: - return $abbr ? Text::_('FEBRUARY_SHORT') : Text::_('FEBRUARY'); + return $abbr ? 'Feb' : 'February'; case 3: - return $abbr ? Text::_('MARCH_SHORT') : Text::_('MARCH'); + return $abbr ? 'Mar' : 'March'; case 4: - return $abbr ? Text::_('APRIL_SHORT') : Text::_('APRIL'); + return $abbr ? 'Apr' : 'April'; case 5: - return $abbr ? Text::_('MAY_SHORT') : Text::_('MAY'); + return 'May'; case 6: - return $abbr ? Text::_('JUNE_SHORT') : Text::_('JUNE'); + return $abbr ? 'Jun' : 'June'; case 7: - return $abbr ? Text::_('JULY_SHORT') : Text::_('JULY'); + return $abbr ? 'Jul' : 'July'; case 8: - return $abbr ? Text::_('AUGUST_SHORT') : Text::_('AUGUST'); + return $abbr ? 'Aug' : 'August'; case 9: - return $abbr ? Text::_('SEPTEMBER_SHORT') : Text::_('SEPTEMBER'); + return $abbr ? 'Sep' : 'September'; case 10: - return $abbr ? Text::_('OCTOBER_SHORT') : Text::_('OCTOBER'); + return $abbr ? 'Oct' : 'October'; case 11: - return $abbr ? Text::_('NOVEMBER_SHORT') : Text::_('NOVEMBER'); + return $abbr ? 'Nov' : 'November'; case 12: - return $abbr ? Text::_('DECEMBER_SHORT') : Text::_('DECEMBER'); + return $abbr ? 'Dec' : 'December'; } } @@ -438,18 +435,20 @@ class Date extends \DateTime * Gets the date as an SQL datetime string. * * @param boolean $local True to return the date string in the local time zone, false to return it in GMT. - * @param DatabaseDriver $db The database driver or null to use Factory::getDbo() + * @param DatabaseInterface $db The database driver or null to use Factory::getDbo() * * @return string The date string in SQL datetime format. * - * @link http://dev.mysql.com/doc/refman/5.0/en/datetime.html + * @throws \Exception * @since 2.5.0 + * @link http://dev.mysql.com/doc/refman/5.0/en/datetime.html */ - public function toSql($local = false, DatabaseDriver $db = null) + public function toSql($local = false, DatabaseInterface $db = null) { if ($db === null) { - $db = Factory::getDbo(); + /** @var \Joomla\Database\DatabaseInterface $db */ + $db = Factory::getContainer()->get(DatabaseInterface::class); } return $this->format($db->getDateFormat(), $local, false); diff --git a/week-03/project/libraries/src/EventListener/ErrorSubscriber.php b/week-03/project/libraries/src/EventListener/ErrorSubscriber.php index a233439..caef55e 100644 --- a/week-03/project/libraries/src/EventListener/ErrorSubscriber.php +++ b/week-03/project/libraries/src/EventListener/ErrorSubscriber.php @@ -1,19 +1,19 @@ getApplication(); switch (true) @@ -142,7 +143,7 @@ class ErrorSubscriber implements SubscriberInterface, LoggerAwareInterface */ private function prepareResponse(ApplicationErrorEvent $event): void { - /** @var WebApplication $app */ + /** @var SiteApplication $app */ $app = $event->getApplication(); $app->allowCache(false); diff --git a/week-03/project/libraries/src/Factory.php b/week-03/project/libraries/src/Factory.php index dbc52d5..042209d 100644 --- a/week-03/project/libraries/src/Factory.php +++ b/week-03/project/libraries/src/Factory.php @@ -1,65 +1,45 @@ + * @created 3rd April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS; +namespace Octoleo\CMS; -\defined('JPATH_PLATFORM') or die; +\defined('LPATH_PLATFORM') or die; -use Joomla\CMS\Application\CMSApplicationInterface; -use Joomla\CMS\Cache\Cache; -use Joomla\CMS\Cache\CacheControllerFactoryInterface; -use Joomla\CMS\Client\ClientHelper; -use Joomla\CMS\Date\Date; -use Joomla\CMS\Document\Document; -use Joomla\CMS\Document\FactoryInterface; -use Joomla\CMS\Filesystem\Stream; -use Joomla\CMS\Language\Language; -use Joomla\CMS\Language\LanguageFactoryInterface; -use Joomla\CMS\Log\Log; -use Joomla\CMS\Mail\Mail; -use Joomla\CMS\Mail\MailHelper; -use Joomla\CMS\Session\Session; -use Joomla\CMS\User\User; -use Joomla\Database\DatabaseDriver; -use Joomla\Database\DatabaseInterface; +use Joomla\Application\WebApplicationInterface; +use Joomla\Database\Service\DatabaseProvider; use Joomla\DI\Container; use Joomla\Registry\Registry; use PHPMailer\PHPMailer\Exception as phpmailerException; /** - * Joomla Platform Factory class. + * Octoleo Platform Factory class. * - * @since 1.7.0 + * @since 1.0.0 + * + * SOURCE: https://github.com/joomla/joomla-cms/blob/4.1-dev/libraries/src/Factory.php#L39 */ abstract class Factory { /** * Global application object * - * @var CMSApplicationInterface - * @since 1.7.0 + * @var WebApplicationInterface + * @since 1.0.0 */ public static $application = null; - /** - * Global cache object - * - * @var Cache - * @since 1.7.0 - */ - public static $cache = null; - /** * Global configuration object * - * @var \JConfig - * @since 1.7.0 - * @deprecated 5.0 Use the configuration object within the application + * @var \LConfig + * @since 1.0.0 */ public static $config = null; @@ -67,71 +47,27 @@ abstract class Factory * Global container object * * @var Container - * @since 4.0.0 + * @since 1.0.0 */ public static $container = null; - /** - * Container for Date instances - * - * @var array - * @since 1.7.3 - */ - public static $dates = array(); - - /** - * Global session object - * - * @var Session - * @since 1.7.0 - * @deprecated 5.0 Use the session service in the DI container - */ - public static $session = null; - - /** - * Global language object - * - * @var Language - * @since 1.7.0 - * @deprecated 5.0 Use the language service in the DI container - */ - public static $language = null; - - /** - * Global document object - * - * @var Document - * @since 1.7.0 - * @deprecated 5.0 Use the document service in the DI container - */ - public static $document = null; - - /** - * Global database object - * - * @var DatabaseDriver - * @since 1.7.0 - * @deprecated 5.0 Use the database service in the DI container - */ - public static $database = null; - /** * Global mailer object * * @var Mail - * @since 1.7.0 + * @since 1.0.0 */ public static $mailer = null; /** * Get the global application object. When the global application doesn't exist, an exception is thrown. * - * @return CMSApplicationInterface object + * @return WebApplicationInterface object * - * @since 1.7.0 + * @since 1.0.0 * @throws \Exception */ - public static function getApplication() + public static function getApplication() : WebApplicationInterface { if (!self::$application) { @@ -141,54 +77,6 @@ abstract class Factory return self::$application; } - /** - * Get a configuration object - * - * Returns the global {@link \JConfig} object, only creating it if it doesn't already exist. - * - * @param string $file The path to the configuration file - * @param string $type The type of the configuration file - * @param string $namespace The namespace of the configuration file - * - * @return Registry - * - * @see Registry - * @since 1.7.0 - * @deprecated 5.0 Use the configuration object within the application. - */ - public static function getConfig($file = null, $type = 'PHP', $namespace = '') - { - @trigger_error( - sprintf( - '%s() is deprecated. The configuration object should be read from the application.', - __METHOD__ - ), - E_USER_DEPRECATED - ); - - /** - * If there is an application object, fetch the configuration from there. - * Check it's not null because LanguagesModel can make it null and if it's null - * we would want to re-init it from configuration.php. - */ - if (self::$application && self::$application->getConfig() !== null) - { - return self::$application->getConfig(); - } - - if (!self::$config) - { - if ($file === null) - { - $file = JPATH_CONFIGURATION . '/configuration.php'; - } - - self::$config = self::createConfig($file, $type, $namespace); - } - - return self::$config; - } - /** * Get a container object * @@ -224,219 +112,6 @@ abstract class Factory return self::$container; } - /** - * Get a session object. - * - * Returns the global {@link Session} object, only creating it if it doesn't already exist. - * - * @param array $options An array containing session options - * - * @return Session object - * - * @see Session - * @since 1.7.0 - * @deprecated 5.0 Load the session service from the dependency injection container or via $app->getSession() - */ - public static function getSession(array $options = array()) - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the session from the dependency injection container or via %2$s::getApplication()->getSession().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - return self::getApplication()->getSession(); - } - - /** - * Get a language object. - * - * Returns the global {@link Language} object, only creating it if it doesn't already exist. - * - * @return Language object - * - * @see Language - * @since 1.7.0 - * @deprecated 5.0 Load the language service from the dependency injection container or via $app->getLanguage() - */ - public static function getLanguage() - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the language from the dependency injection container or via %2$s::getApplication()->getLanguage().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - if (!self::$language) - { - self::$language = self::createLanguage(); - } - - return self::$language; - } - - /** - * Get a document object. - * - * Returns the global {@link \Joomla\CMS\Document\Document} object, only creating it if it doesn't already exist. - * - * @return Document object - * - * @see Document - * @since 1.7.0 - * @deprecated 5.0 Load the document service from the dependency injection container or via $app->getDocument() - */ - public static function getDocument() - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the document from the dependency injection container or via %2$s::getApplication()->getDocument().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - if (!self::$document) - { - self::$document = self::createDocument(); - } - - return self::$document; - } - - /** - * Get a user object. - * - * Returns the global {@link User} object, only creating it if it doesn't already exist. - * - * @param integer $id The user to load - Can be an integer or string - If string, it is converted to ID automatically. - * - * @return User object - * - * @see User - * @since 1.7.0 - * @deprecated 5.0 Load the user service from the dependency injection container or via $app->getIdentity() - */ - public static function getUser($id = null) - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the user from the dependency injection container or via %2$s::getApplication()->getIdentity().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - $instance = self::getApplication()->getSession()->get('user'); - - if (\is_null($id)) - { - if (!($instance instanceof User)) - { - $instance = User::getInstance(); - } - } - // Check if we have a string as the id or if the numeric id is the current instance - elseif (!($instance instanceof User) || \is_string($id) || $instance->id !== $id) - { - $instance = User::getInstance($id); - } - - return $instance; - } - - /** - * Get a cache object - * - * Returns the global {@link CacheController} object - * - * @param string $group The cache group name - * @param string $handler The handler to use - * @param string $storage The storage method - * - * @return \Joomla\CMS\Cache\CacheController object - * - * @see Cache - * @since 1.7.0 - * @deprecated 5.0 Use the cache controller factory instead - */ - public static function getCache($group = '', $handler = 'callback', $storage = null) - { - @trigger_error( - sprintf( - '%s() is deprecated. The cache controller should be fetched from the factory.', - __METHOD__ - ), - E_USER_DEPRECATED - ); - - $hash = md5($group . $handler . $storage); - - if (isset(self::$cache[$hash])) - { - return self::$cache[$hash]; - } - - $handler = ($handler === 'function') ? 'callback' : $handler; - - $options = array('defaultgroup' => $group); - - if (isset($storage)) - { - $options['storage'] = $storage; - } - - $cache = self::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($handler, $options); - - self::$cache[$hash] = $cache; - - return self::$cache[$hash]; - } - - /** - * Get a database object. - * - * Returns the global {@link DatabaseDriver} object, only creating it if it doesn't already exist. - * - * @return DatabaseDriver - * - * @see DatabaseDriver - * @since 1.7.0 - * @deprecated 5.0 Load the database service from the dependency injection container - */ - public static function getDbo() - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the database from the dependency injection container.', - __METHOD__ - ), - E_USER_DEPRECATED - ); - - if (!self::$database) - { - if (self::getContainer()->has('DatabaseDriver')) - { - self::$database = self::getContainer()->get('DatabaseDriver'); - } - else - { - self::$database = self::createDbo(); - } - } - - return self::$database; - } - /** * Get a mailer object. * @@ -460,56 +135,61 @@ abstract class Factory } /** - * Return the {@link Date} object + * Create a container object * - * @param mixed $time The initial time for the Date object - * @param mixed $tzOffset The timezone offset. + * @return Container * - * @return Date object - * - * @see Date - * @since 1.7.0 + * @since 4.0.0 */ - public static function getDate($time = 'now', $tzOffset = null) + protected static function createContainer(): Container { - static $classname; - static $mainLocale; + return (new Container) + ->registerServiceProvider(new Service\ConfigurationProvider(LPATH_CONFIGURATION . '/octoconfig.php')) + ->registerServiceProvider(new Service\SessionProvider) + ->registerServiceProvider(new Service\UserProvider) + ->registerServiceProvider(new DatabaseProvider) + ->registerServiceProvider(new Service\EventProvider) + ->registerServiceProvider(new Service\HttpProvider) + ->registerServiceProvider(new Service\LoggingProvider); + } - $language = self::getLanguage(); - $locale = $language->getTag(); - - if (!isset($classname) || $locale != $mainLocale) + /** + * Get a configuration object + * + * Returns the global {@link \JConfig} object, only creating it if it doesn't already exist. + * + * @param string $file The path to the configuration file + * @param string $type The type of the configuration file + * @param string $namespace The namespace of the configuration file + * + * @return Registry + * + * @see Registry + * @since 1.1.1 + */ + public static function getConfig($file = null, $type = 'PHP', $namespace = '') + { + /** + * If there is an application object, fetch the configuration from there. + * Check it's not null because LanguagesModel can make it null and if it's null + * we would want to re-init it from configuration.php. + */ + if (self::$application && self::$application->getConfig() !== null) { - // Store the locale for future reference - $mainLocale = $locale; - - if ($mainLocale !== false) - { - $classname = str_replace('-', '_', $mainLocale) . 'Date'; - - if (!class_exists($classname)) - { - // The class does not exist, default to Date - $classname = 'Joomla\\CMS\\Date\\Date'; - } - } - else - { - // No tag, so default to Date - $classname = 'Joomla\\CMS\\Date\\Date'; - } + return self::$application->getConfig(); } - $key = $time . '-' . ($tzOffset instanceof \DateTimeZone ? $tzOffset->getName() : (string) $tzOffset); - - if (!isset(self::$dates[$classname][$key])) + if (!self::$config) { - self::$dates[$classname][$key] = new $classname($time, $tzOffset); + if ($file === null) + { + $file = JPATH_CONFIGURATION . '/octoconfig.php'; + } + + self::$config = self::createConfig($file, $type, $namespace); } - $date = clone self::$dates[$classname][$key]; - - return $date; + return self::$config; } /** @@ -522,19 +202,10 @@ abstract class Factory * @return Registry * * @see Registry - * @since 1.7.0 - * @deprecated 5.0 Use the configuration object within the application. + * @since 1.0.0 */ protected static function createConfig($file, $type = 'PHP', $namespace = '') { - @trigger_error( - sprintf( - '%s() is deprecated. The configuration object should be read from the application.', - __METHOD__ - ), - E_USER_DEPRECATED - ); - if (is_file($file)) { include_once $file; @@ -547,12 +218,12 @@ abstract class Factory $namespace = ucfirst((string) preg_replace('/[^A-Z_]/i', '', $namespace)); // Build the config name. - $name = 'JConfig' . $namespace; + $name = 'LConfig' . $namespace; // Handle the PHP configuration type. if ($type === 'PHP' && class_exists($name)) { - // Create the JConfig object + // Create the LConfig object $config = new $name; // Load the configuration values into the registry @@ -562,289 +233,68 @@ abstract class Factory return $registry; } - /** - * Create a container object - * - * @return Container - * - * @since 4.0.0 - */ - protected static function createContainer(): Container - { - $container = (new Container) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Application) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Authentication) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\CacheController) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Config) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Console) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Database) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Dispatcher) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Document) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Form) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Logger) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Language) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Menu) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Pathway) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\HTMLRegistry) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Session) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\Toolbar) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\WebAssetRegistry) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\ApiRouter) - ->registerServiceProvider(new \Joomla\CMS\Service\Provider\User); - - return $container; - } - - /** - * Create a database object - * - * @return DatabaseDriver - * - * @see DatabaseDriver - * @since 1.7.0 - * @deprecated 5.0 Use the database service in the DI container - */ - protected static function createDbo() - { - @trigger_error( - sprintf( - '%1$s() is deprecated, register a service provider to create a %2$s instance instead.', - __METHOD__, - DatabaseInterface::class - ), - E_USER_DEPRECATED - ); - - $conf = self::getConfig(); - - $host = $conf->get('host'); - $user = $conf->get('user'); - $password = $conf->get('password'); - $database = $conf->get('db'); - $prefix = $conf->get('dbprefix'); - $driver = $conf->get('dbtype'); - - $options = array('driver' => $driver, 'host' => $host, 'user' => $user, 'password' => $password, 'database' => $database, 'prefix' => $prefix); - - if ((int) $conf->get('dbencryption') !== 0) - { - $options['ssl'] = [ - 'enable' => true, - 'verify_server_cert' => (bool) $conf->get('dbsslverifyservercert'), - ]; - - foreach (['cipher', 'ca', 'key', 'cert'] as $value) - { - $confVal = trim($conf->get('dbssl' . $value, '')); - - if ($confVal !== '') - { - $options['ssl'][$value] = $confVal; - } - } - } - - try - { - $db = DatabaseDriver::getInstance($options); - } - catch (\RuntimeException $e) - { - if (!headers_sent()) - { - header('HTTP/1.1 500 Internal Server Error'); - } - - jexit('Database Error: ' . $e->getMessage()); - } - - return $db; - } - /** * Create a mailer object * * @return Mail object * * @see Mail - * @since 1.7.0 + * @since 1.0.0 */ protected static function createMailer() { - $conf = self::getConfig(); - - $smtpauth = ($conf->get('smtpauth') == 0) ? null : 1; - $smtpuser = $conf->get('smtpuser'); - $smtppass = $conf->get('smtppass'); - $smtphost = $conf->get('smtphost'); - $smtpsecure = $conf->get('smtpsecure'); - $smtpport = $conf->get('smtpport'); - $mailfrom = $conf->get('mailfrom'); - $fromname = $conf->get('fromname'); - $mailer = $conf->get('mailer'); - - // Create a Mail object - $mail = Mail::getInstance(); - - // Clean the email address - $mailfrom = MailHelper::cleanLine($mailfrom); - - // Set default sender without Reply-to if the mailfrom is a valid address - if (MailHelper::isEmailAddress($mailfrom)) - { - // Wrap in try/catch to catch phpmailerExceptions if it is throwing them - try - { - // Check for a false return value if exception throwing is disabled - if ($mail->setFrom($mailfrom, MailHelper::cleanLine($fromname), false) === false) - { - Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail'); - } - } - catch (phpmailerException $e) - { - Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail'); - } - } - - // Default mailer is to use PHP's mail function - switch ($mailer) - { - case 'smtp': - $mail->useSmtp($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport); - break; - - case 'sendmail': - $mail->isSendmail(); - break; - - default: - $mail->isMail(); - break; - } - - return $mail; - } - - /** - * Create a language object - * - * @return Language object - * - * @see Language - * @since 1.7.0 - * @deprecated 5.0 Load the language service from the dependency injection container or via $app->getLanguage() - */ - protected static function createLanguage() - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the language from the dependency injection container or via %2$s::getApplication()->getLanguage().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - $conf = self::getConfig(); - $locale = $conf->get('language'); - $debug = $conf->get('debug_lang'); - $lang = self::getContainer()->get(LanguageFactoryInterface::class)->createLanguage($locale, $debug); - - return $lang; - } - - /** - * Create a document object - * - * @return Document object - * - * @see Document - * @since 1.7.0 - * @deprecated 5.0 Load the document service from the dependency injection container or via $app->getDocument() - */ - protected static function createDocument() - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the document from the dependency injection container or via %2$s::getApplication()->getDocument().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - $lang = self::getLanguage(); - - $input = self::getApplication()->input; - $type = $input->get('format', 'html', 'cmd'); - - $version = new Version; - - $attributes = array( - 'charset' => 'utf-8', - 'lineend' => 'unix', - 'tab' => "\t", - 'language' => $lang->getTag(), - 'direction' => $lang->isRtl() ? 'rtl' : 'ltr', - 'mediaversion' => $version->getMediaVersion(), - ); - - return self::getContainer()->get(FactoryInterface::class)->createDocument($type, $attributes); - } - - /** - * Creates a new stream object with appropriate prefix - * - * @param boolean $usePrefix Prefix the connections for writing - * @param boolean $useNetwork Use network if available for writing; use false to disable (e.g. FTP, SCP) - * @param string $userAgentSuffix String to append to user agent - * @param boolean $maskUserAgent User agent masking (prefix Mozilla) - * - * @return Stream - * - * @see Stream - * @since 1.7.0 - */ - public static function getStream($usePrefix = true, $useNetwork = true, $userAgentSuffix = 'Joomla', $maskUserAgent = false) - { - // Setup the context; Joomla! UA and overwrite - $context = array(); - $version = new Version; - - // Set the UA for HTTP and overwrite for FTP - $context['http']['user_agent'] = $version->getUserAgent($userAgentSuffix, $maskUserAgent); - $context['ftp']['overwrite'] = true; - - if ($usePrefix) - { - $FTPOptions = ClientHelper::getCredentials('ftp'); - $SCPOptions = ClientHelper::getCredentials('scp'); - - if ($FTPOptions['enabled'] == 1 && $useNetwork) - { - $prefix = 'ftp://' . $FTPOptions['user'] . ':' . $FTPOptions['pass'] . '@' . $FTPOptions['host']; - $prefix .= $FTPOptions['port'] ? ':' . $FTPOptions['port'] : ''; - $prefix .= $FTPOptions['root']; - } - elseif ($SCPOptions['enabled'] == 1 && $useNetwork) - { - $prefix = 'ssh2.sftp://' . $SCPOptions['user'] . ':' . $SCPOptions['pass'] . '@' . $SCPOptions['host']; - $prefix .= $SCPOptions['port'] ? ':' . $SCPOptions['port'] : ''; - $prefix .= $SCPOptions['root']; - } - else - { - $prefix = JPATH_ROOT . '/'; - } - - $retval = new Stream($prefix, JPATH_ROOT, $context); - } - else - { - $retval = new Stream('', '', $context); - } - - return $retval; +// $conf = self::getConfig(); +// +// $smtpauth = ($conf->get('smtpauth') == 0) ? null : 1; +// $smtpuser = $conf->get('smtpuser'); +// $smtppass = $conf->get('smtppass'); +// $smtphost = $conf->get('smtphost'); +// $smtpsecure = $conf->get('smtpsecure'); +// $smtpport = $conf->get('smtpport'); +// $mailfrom = $conf->get('mailfrom'); +// $fromname = $conf->get('fromname'); +// $mailer = $conf->get('mailer'); +// +// // Create a Mail object +// $mail = Mail::getInstance(); +// +// // Clean the email address +// $mailfrom = MailHelper::cleanLine($mailfrom); +// +// // Set default sender without Reply-to if the mailfrom is a valid address +// if (MailHelper::isEmailAddress($mailfrom)) +// { +// // Wrap in try/catch to catch phpmailerExceptions if it is throwing them +// try +// { +// // Check for a false return value if exception throwing is disabled +// if ($mail->setFrom($mailfrom, MailHelper::cleanLine($fromname), false) === false) +// { +// Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail'); +// } +// } +// catch (phpmailerException $e) +// { +// Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail'); +// } +// } +// +// // Default mailer is to use PHP's mail function +// switch ($mailer) +// { +// case 'smtp': +// $mail->useSmtp($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport); +// break; +// +// case 'sendmail': +// $mail->isSendmail(); +// break; +// +// default: +// $mail->isMail(); +// break; +// } +// +// return $mail; } } diff --git a/week-03/project/libraries/src/Filter/InputFilter.php b/week-03/project/libraries/src/Filter/InputFilter.php index b654049..570db4f 100644 --- a/week-03/project/libraries/src/Filter/InputFilter.php +++ b/week-03/project/libraries/src/Filter/InputFilter.php @@ -6,11 +6,9 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\Filter; +namespace Octoleo\CMS\Filter; -\defined('JPATH_PLATFORM') or die; - -use Joomla\CMS\String\PunycodeHelper; +use Octoleo\CMS\String\PunycodeHelper; use Joomla\Filter\InputFilter as BaseInputFilter; /** diff --git a/week-03/project/libraries/src/Model/DashboardModel.php b/week-03/project/libraries/src/Model/DashboardModel.php index f2213c9..d942bdd 100644 --- a/week-03/project/libraries/src/Model/DashboardModel.php +++ b/week-03/project/libraries/src/Model/DashboardModel.php @@ -1,12 +1,14 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Model; +namespace Octoleo\CMS\Model; use Joomla\Database\DatabaseDriver; use Joomla\Database\ParameterType; @@ -14,12 +16,27 @@ use Joomla\Model\DatabaseModelInterface; use Joomla\Model\DatabaseModelTrait; /** - * Model class for packages + * Model class for pages + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Model/PackageModel.php */ -class PackageModel implements DatabaseModelInterface +class DashboardModel implements DatabaseModelInterface { use DatabaseModelTrait; + /** + * Array of legal dashboards + * + * @var array + */ + private $legalDashboards = [ + 'items' => 'items.twig', + 'item' => 'edit.twig', + 'menus' => 'menus.twig', + 'menu' => 'edit.twig', + 'users' => 'users.twig', + 'user' => 'edit.twig' + ]; + /** * Instantiate the model. * @@ -31,142 +48,20 @@ class PackageModel implements DatabaseModelInterface } /** - * Add a package + * Get a active dashboard template name * - * @param string $packageName The package name as registered with Packagist - * @param string $displayName The package's display name - * @param string $repoName The package's repo name - * @param boolean $isStable Flag indicating the package is stable - * @param boolean $isDeprecated Flag indicating the package is deprecated - * @param boolean $isAbandoned Flag indicating the package is abandoned + * @param string $dashboardName The dashboard to lookup + * + * @return string * - * @return void */ - public function addPackage(string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void + public function getDashboard(string $dashboardName): string { - $db = $this->getDb(); - - $data = (object) [ - 'package' => $packageName, - 'display' => $displayName, - 'repo' => $repoName, - 'stable' => (int) $isStable, - 'deprecated' => (int) $isDeprecated, - 'abandoned' => (int) $isAbandoned, - ]; - - $db->insertObject('#__packages', $data); - } - - /** - * Get the active package data - * - * @return array - */ - public function getActivePackages(): array - { - $abandoned = false; - - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select('*') - ->from($db->quoteName('#__packages')) - ->where($db->quoteName('abandoned') . ' = :abandoned') - ->bind('abandoned', $abandoned, ParameterType::INTEGER); - - return $db->setQuery($query)->loadObjectList('id'); - } - - /** - * Get a package's data - * - * @param string $packageName The package to lookup - * - * @return \stdClass - * - * @throws \RuntimeException - */ - public function getPackage(string $packageName): \stdClass - { - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select('*') - ->from($db->quoteName('#__packages')) - ->where($db->quoteName('package') . ' = :package'); - - $query->bind('package', $packageName, ParameterType::STRING); - - $package = $db->setQuery($query)->loadObject(); - - if (!$package) + if (!isset($this->legalDashboards[$dashboardName])) { - throw new \RuntimeException(sprintf('Unable to find release data for the `%s` package', $package->display), 404); + return 'dashboard.twig'; } - return $package; - } - - /** - * Get the known package names - * - * @return array - */ - public function getPackageNames(): array - { - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select(['id', 'package']) - ->from($db->quoteName('#__packages')); - - return $db->setQuery($query)->loadAssocList('id', 'package'); - } - - /** - * Get the known package data - * - * @return array - */ - public function getPackages(): array - { - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select('*') - ->from($db->quoteName('#__packages')); - - return $db->setQuery($query)->loadObjectList('id'); - } - - /** - * Update a package - * - * @param integer $packageId The local package ID - * @param string $packageName The package name as registered with Packagist - * @param string $displayName The package's display name - * @param string $repoName The package's repo name - * @param boolean $isStable Flag indicating the package is stable - * @param boolean $isDeprecated Flag indicating the package is deprecated - * @param boolean $isAbandoned Flag indicating the package is abandoned - * - * @return void - */ - public function updatePackage(int $packageId, string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void - { - $db = $this->getDb(); - - $data = (object) [ - 'id' => $packageId, - 'package' => $packageName, - 'display' => $displayName, - 'repo' => $repoName, - 'stable' => (int) $isStable, - 'deprecated' => (int) $isDeprecated, - 'abandoned' => (int) $isAbandoned, - ]; - - $db->updateObject('#__packages', $data, 'id'); + return $this->legalDashboards[$dashboardName]; } } diff --git a/week-03/project/libraries/src/Model/PageModel.php b/week-03/project/libraries/src/Model/PageModel.php index f2213c9..69eccbd 100644 --- a/week-03/project/libraries/src/Model/PageModel.php +++ b/week-03/project/libraries/src/Model/PageModel.php @@ -1,12 +1,14 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Model; +namespace Octoleo\CMS\Model; use Joomla\Database\DatabaseDriver; use Joomla\Database\ParameterType; @@ -14,12 +16,27 @@ use Joomla\Model\DatabaseModelInterface; use Joomla\Model\DatabaseModelTrait; /** - * Model class for packages + * Model class for pages + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Model/PackageModel.php */ -class PackageModel implements DatabaseModelInterface +class PageModel implements DatabaseModelInterface { use DatabaseModelTrait; + /** + * Array of legal pages + * + * @var array + */ + private $legalPages = ['products', 'blog', 'about-us', 'location', 'contact-us']; + + /** + * Array of legal details pages + * + * @var array + */ + private $legalDetailsPages = ['yachts', 'ski-boats', 'drones']; + /** * Instantiate the model. * @@ -31,142 +48,40 @@ class PackageModel implements DatabaseModelInterface } /** - * Add a package + * Get a page's data * - * @param string $packageName The package name as registered with Packagist - * @param string $displayName The package's display name - * @param string $repoName The package's repo name - * @param boolean $isStable Flag indicating the package is stable - * @param boolean $isDeprecated Flag indicating the package is deprecated - * @param boolean $isAbandoned Flag indicating the package is abandoned + * @param string $pageName The page to lookup * - * @return void - */ - public function addPackage(string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void - { - $db = $this->getDb(); - - $data = (object) [ - 'package' => $packageName, - 'display' => $displayName, - 'repo' => $repoName, - 'stable' => (int) $isStable, - 'deprecated' => (int) $isDeprecated, - 'abandoned' => (int) $isAbandoned, - ]; - - $db->insertObject('#__packages', $data); - } - - /** - * Get the active package data - * - * @return array - */ - public function getActivePackages(): array - { - $abandoned = false; - - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select('*') - ->from($db->quoteName('#__packages')) - ->where($db->quoteName('abandoned') . ' = :abandoned') - ->bind('abandoned', $abandoned, ParameterType::INTEGER); - - return $db->setQuery($query)->loadObjectList('id'); - } - - /** - * Get a package's data - * - * @param string $packageName The package to lookup - * - * @return \stdClass + * @return string * * @throws \RuntimeException */ - public function getPackage(string $packageName): \stdClass + public function getPage(string $pageName): string { - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select('*') - ->from($db->quoteName('#__packages')) - ->where($db->quoteName('package') . ' = :package'); - - $query->bind('package', $packageName, ParameterType::STRING); - - $package = $db->setQuery($query)->loadObject(); - - if (!$package) + if (!in_array($pageName, $this->legalPages)) { - throw new \RuntimeException(sprintf('Unable to find release data for the `%s` package', $package->display), 404); + throw new \RuntimeException(sprintf('Unable to find page data for the `%s`', $pageName), 404); } - return $package; + return $pageName; } /** - * Get the known package names + * Get a page's details data * - * @return array + * @param string $detailsName The page details to lookup + * + * @return string + * + * @throws \RuntimeException */ - public function getPackageNames(): array + public function getDetails(string $detailsName): string { - $db = $this->getDb(); + if (strlen($detailsName) && !in_array($detailsName, $this->legalDetailsPages)) + { + throw new \RuntimeException(sprintf('Unable to find page details data for the `%s`', $detailsName), 404); + } - $query = $db->getQuery(true) - ->select(['id', 'package']) - ->from($db->quoteName('#__packages')); - - return $db->setQuery($query)->loadAssocList('id', 'package'); - } - - /** - * Get the known package data - * - * @return array - */ - public function getPackages(): array - { - $db = $this->getDb(); - - $query = $db->getQuery(true) - ->select('*') - ->from($db->quoteName('#__packages')); - - return $db->setQuery($query)->loadObjectList('id'); - } - - /** - * Update a package - * - * @param integer $packageId The local package ID - * @param string $packageName The package name as registered with Packagist - * @param string $displayName The package's display name - * @param string $repoName The package's repo name - * @param boolean $isStable Flag indicating the package is stable - * @param boolean $isDeprecated Flag indicating the package is deprecated - * @param boolean $isAbandoned Flag indicating the package is abandoned - * - * @return void - */ - public function updatePackage(int $packageId, string $packageName, string $displayName, string $repoName, bool $isStable, bool $isDeprecated, bool $isAbandoned): void - { - $db = $this->getDb(); - - $data = (object) [ - 'id' => $packageId, - 'package' => $packageName, - 'display' => $displayName, - 'repo' => $repoName, - 'stable' => (int) $isStable, - 'deprecated' => (int) $isDeprecated, - 'abandoned' => (int) $isAbandoned, - ]; - - $db->updateObject('#__packages', $data, 'id'); + return $detailsName; } } diff --git a/week-03/project/libraries/src/Renderer/ApplicationContext.php b/week-03/project/libraries/src/Renderer/ApplicationContext.php index 9347d04..690268d 100644 --- a/week-03/project/libraries/src/Renderer/ApplicationContext.php +++ b/week-03/project/libraries/src/Renderer/ApplicationContext.php @@ -6,7 +6,7 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite\Renderer; +namespace Octoleo\CMS\Renderer; use Joomla\Application\AbstractApplication; use Joomla\Application\AbstractWebApplication; @@ -14,6 +14,7 @@ use Symfony\Component\Asset\Context\ContextInterface; /** * Joomla! application aware context + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Renderer/ApplicationContext.php */ class ApplicationContext implements ContextInterface { @@ -58,4 +59,4 @@ class ApplicationContext implements ContextInterface return false; } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/Renderer/FrameworkExtension.php b/week-03/project/libraries/src/Renderer/FrameworkExtension.php index a3535b0..33c612e 100644 --- a/week-03/project/libraries/src/Renderer/FrameworkExtension.php +++ b/week-03/project/libraries/src/Renderer/FrameworkExtension.php @@ -6,7 +6,7 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite\Renderer; +namespace Octoleo\CMS\Renderer; use Symfony\Component\Asset\Packages; use Twig\Extension\AbstractExtension; @@ -15,6 +15,7 @@ use Twig\TwigFunction; /** * Framework site's Twig extension class + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Renderer/FrameworkExtension.php */ class FrameworkExtension extends AbstractExtension { diff --git a/week-03/project/libraries/src/Renderer/FrameworkTwigRuntime.php b/week-03/project/libraries/src/Renderer/FrameworkTwigRuntime.php index 41a8733..3db62bb 100644 --- a/week-03/project/libraries/src/Renderer/FrameworkTwigRuntime.php +++ b/week-03/project/libraries/src/Renderer/FrameworkTwigRuntime.php @@ -6,13 +6,14 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite\Renderer; +namespace Octoleo\CMS\Renderer; use Joomla\Application\AbstractApplication; use Joomla\Preload\PreloadManager; /** * Twig runtime class + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Renderer/FrameworkTwigRuntime.php */ class FrameworkTwigRuntime { @@ -157,4 +158,4 @@ class FrameworkTwigRuntime return $uri; } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/Service/AdminApplicationProvider.php b/week-03/project/libraries/src/Service/AdminApplicationProvider.php index 648b1bf..b4202c0 100644 --- a/week-03/project/libraries/src/Service/AdminApplicationProvider.php +++ b/week-03/project/libraries/src/Service/AdminApplicationProvider.php @@ -1,65 +1,44 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Service; +namespace Octoleo\CMS\Service; use Joomla\Application\AbstractWebApplication; use Joomla\Application\Controller\ContainerControllerResolver; use Joomla\Application\Controller\ControllerResolverInterface; use Joomla\Application\Web\WebClient; -use Joomla\Console\Application as ConsoleApplication; -use Joomla\Console\Loader\ContainerLoader; -use Joomla\Console\Loader\LoaderInterface; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; -use Joomla\Event\Command\DebugEventDispatcherCommand; use Joomla\Event\DispatcherInterface; -use Joomla\FrameworkWebsite\Command\GenerateSriCommand; -use Joomla\FrameworkWebsite\Command\Package\SyncCommand as PackageSyncCommand; -use Joomla\FrameworkWebsite\Command\Packagist\DownloadsCommand; -use Joomla\FrameworkWebsite\Command\Packagist\SyncCommand as PackagistSyncCommand; -use Joomla\FrameworkWebsite\Command\Twig\ResetCacheCommand; -use Joomla\FrameworkWebsite\Command\UpdateCommand; -use Joomla\FrameworkWebsite\Controller\Api\PackageControllerGet; -use Joomla\FrameworkWebsite\Controller\Api\StatusControllerGet; -use Joomla\FrameworkWebsite\Controller\HomepageController; -use Joomla\FrameworkWebsite\Controller\PackageController; -use Joomla\FrameworkWebsite\Controller\PageController; -use Joomla\FrameworkWebsite\Controller\StatusController; -use Joomla\FrameworkWebsite\Controller\WrongCmsController; -use Joomla\FrameworkWebsite\Helper; -use Joomla\FrameworkWebsite\Helper\PackagistHelper; -use Joomla\FrameworkWebsite\Model\PackageModel; -use Joomla\FrameworkWebsite\Model\ReleaseModel; -use Joomla\FrameworkWebsite\View\Package\PackageHtmlView; -use Joomla\FrameworkWebsite\View\Package\PackageJsonView; -use Joomla\FrameworkWebsite\View\Status\StatusHtmlView; -use Joomla\FrameworkWebsite\View\Status\StatusJsonView; -use Joomla\FrameworkWebsite\WebApplication; -use Joomla\Http\Http; + +use Joomla\Session\SessionInterface; +use Octoleo\CMS\Controller\DashboardController; +use Octoleo\CMS\Controller\LoginController; +use Octoleo\CMS\Controller\WrongCmsController; +use Octoleo\CMS\Model\DashboardModel; +use Octoleo\CMS\User\UserFactoryInterface; +use Octoleo\CMS\View\Admin\DashboardHtmlView; +use Octoleo\CMS\Application\AdminApplication; + use Joomla\Input\Input; -use Joomla\Registry\Registry; use Joomla\Renderer\RendererInterface; -use Joomla\Renderer\TwigRenderer; -use Joomla\Router\Command\DebugRouterCommand; -use Joomla\Router\Route; use Joomla\Router\Router; use Joomla\Router\RouterInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Output\ConsoleOutput; -use TheIconic\Tracking\GoogleAnalytics\Analytics; /** * Application service provider + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Service/ApplicationProvider.php */ -class ApplicationProvider implements ServiceProviderInterface +class AdminApplicationProvider implements ServiceProviderInterface { /** * Registers the service provider with a DI container. @@ -74,34 +53,18 @@ class ApplicationProvider implements ServiceProviderInterface * Application Classes */ - $container->share(ConsoleApplication::class, [$this, 'getConsoleApplicationService'], true); - // This service cannot be protected as it is decorated when the debug bar is available - $container->alias(WebApplication::class, AbstractWebApplication::class) - ->share(AbstractWebApplication::class, [$this, 'getWebApplicationClassService']); + $container->alias(AdminApplication::class, AbstractWebApplication::class) + ->share(AbstractWebApplication::class, [$this, 'getAdminApplicationClassService']); /* * Application Helpers and Dependencies */ - $container->alias(Analytics::class, 'analytics') - ->share('analytics', [$this, 'getAnalyticsService'], true); - - $container->alias(ContainerLoader::class, LoaderInterface::class) - ->share(LoaderInterface::class, [$this, 'getCommandLoaderService'], true); - // This service cannot be protected as it is decorated when the debug bar is available $container->alias(ContainerControllerResolver::class, ControllerResolverInterface::class) ->share(ControllerResolverInterface::class, [$this, 'getControllerResolverService']); - $container->alias(Helper::class, 'application.helper') - ->share('application.helper', [$this, 'getApplicationHelperService'], true); - - $container->alias(PackagistHelper::class, 'application.helper.packagist') - ->share('application.helper.packagist', [$this, 'getApplicationHelperPackagistService'], true); - - $container->share('application.packages', [$this, 'getApplicationPackagesService'], true); - $container->share(WebClient::class, [$this, 'getWebClientService'], true); // This service cannot be protected as it is decorated when the debug bar is available @@ -111,118 +74,27 @@ class ApplicationProvider implements ServiceProviderInterface $container->share(Input::class, [$this, 'getInputClassService'], true); - /* - * Console Commands - */ - - $container->share(DebugEventDispatcherCommand::class, [$this, 'getDebugEventDispatcherCommandService'], true); - $container->share(DebugRouterCommand::class, [$this, 'getDebugRouterCommandService'], true); - $container->share(DownloadsCommand::class, [$this, 'getDownloadsCommandService'], true); - $container->share(GenerateSriCommand::class, [$this, 'getGenerateSriCommandService'], true); - $container->share(PackageSyncCommand::class, [$this, 'getPackageSyncCommandService'], true); - $container->share(PackagistSyncCommand::class, [$this, 'getPackagistSyncCommandService'], true); - $container->share(ResetCacheCommand::class, [$this, 'getResetCacheCommandService'], true); - $container->share(UpdateCommand::class, [$this, 'getUpdateCommandService'], true); - /* * MVC Layer */ // Controllers - $container->alias(PackageControllerGet::class, 'controller.api.package') - ->share('controller.api.package', [$this, 'getControllerApiPackageService'], true); + $container->alias(DashboardController::class, 'controller.dashboard') + ->share('controller.dashboard', [$this, 'getControllerDashboardService'], true); - $container->alias(StatusControllerGet::class, 'controller.api.status') - ->share('controller.api.status', [$this, 'getControllerApiStatusService'], true); - - $container->alias(HomepageController::class, 'controller.homepage') - ->share('controller.homepage', [$this, 'getControllerHomepageService'], true); - - $container->alias(PackageController::class, 'controller.package') - ->share('controller.package', [$this, 'getControllerPackageService'], true); - - $container->alias(PageController::class, 'controller.page') - ->share('controller.page', [$this, 'getControllerPageService'], true); - - $container->alias(StatusController::class, 'controller.status') - ->share('controller.status', [$this, 'getControllerStatusService'], true); + $container->alias(LoginController::class, 'controller.login') + ->share('controller.login', [$this, 'getControllerLoginService'], true); $container->alias(WrongCmsController::class, 'controller.wrong.cms') ->share('controller.wrong.cms', [$this, 'getControllerWrongCmsService'], true); // Models - $container->alias(PackageModel::class, 'model.package') - ->share('model.package', [$this, 'getModelPackageService'], true); - - $container->alias(ReleaseModel::class, 'model.release') - ->share('model.release', [$this, 'getModelReleaseService'], true); + $container->alias(DashboardModel::class, 'model.dashboard') + ->share('model.dashboard', [$this, 'getModelDashboardService'], true); // Views - $container->alias(PackageHtmlView::class, 'view.package.html') - ->share('view.package.html', [$this, 'getViewPackageHtmlService'], true); - - $container->alias(PackageJsonView::class, 'view.package.json') - ->share('view.package.json', [$this, 'getViewPackageJsonService'], true); - - $container->alias(StatusHtmlView::class, 'view.status.html') - ->share('view.status.html', [$this, 'getViewStatusHtmlService'], true); - - $container->alias(StatusJsonView::class, 'view.status.json') - ->share('view.status.json', [$this, 'getViewStatusJsonService'], true); - } - - /** - * Get the Analytics class service - * - * @param Container $container The DI container. - * - * @return Analytics - */ - public function getAnalyticsService(Container $container) - { - return new Analytics(true); - } - - /** - * Get the `application.helper` service - * - * @param Container $container The DI container. - * - * @return Helper - */ - public function getApplicationHelperService(Container $container): Helper - { - $helper = new Helper; - $helper->setPackages($container->get('application.packages')); - - return $helper; - } - - /** - * Get the `application.helper.packagist` service - * - * @param Container $container The DI container. - * - * @return PackagistHelper - */ - public function getApplicationHelperPackagistService(Container $container): PackagistHelper - { - $helper = new PackagistHelper($container->get(Http::class), $container->get(DatabaseInterface::class)); - $helper->setPackages($container->get('application.packages')); - - return $helper; - } - - /** - * Get the `application.packages` service - * - * @param Container $container The DI container. - * - * @return Registry - */ - public function getApplicationPackagesService(Container $container): Registry - { - return (new Registry)->loadFile(JPATH_ROOT . '/packages.yml', 'YAML'); + $container->alias(DashboardHtmlView::class, 'view.dashboard.html') + ->share('view.dashboard.html', [$this, 'getViewDashboardHtmlService'], true); } /** @@ -239,232 +111,47 @@ class ApplicationProvider implements ServiceProviderInterface /* * CMS Admin Panels */ - $router->get( - '/administrator', - WrongCmsController::class + $router->all( + '/index.php?dashboard=*', + DashboardController::class ); - $router->get( - '/administrator/*', - WrongCmsController::class - ); - - $router->get( - '/wp-admin', - WrongCmsController::class - ); - - $router->get( - '/wp-admin/*', - WrongCmsController::class - ); - - $router->get( - 'wp-login.php', - WrongCmsController::class - ); - - /* - * Web routes - */ - $router->addRoute(new Route(['GET', 'HEAD'], '/', HomepageController::class)); - - $router->get( - '/status', - StatusController::class - ); - - $router->get( - '/:view', - PageController::class - ); - - $router->get( - '/status/:package', - PackageController::class - ); - - /* - * API routes - */ - $router->get( - '/api/v1/packages', - StatusControllerGet::class, - [], - [ - '_format' => 'json', - ] - ); - - $router->get( - '/api/v1/packages/:package', - PackageControllerGet::class, - [], - [ - '_format' => 'json', - ] + '/*', + LoginController::class ); return $router; } /** - * Get the LoaderInterface service + * Get the `controller.login` service * * @param Container $container The DI container. * - * @return LoaderInterface + * @return LoginController */ - public function getCommandLoaderService(Container $container): LoaderInterface + public function getControllerLoginService(Container $container): LoginController { - $mapping = [ - DebugEventDispatcherCommand::getDefaultName() => DebugEventDispatcherCommand::class, - DebugRouterCommand::getDefaultName() => DebugRouterCommand::class, - DownloadsCommand::getDefaultName() => DownloadsCommand::class, - PackageSyncCommand::getDefaultName() => PackageSyncCommand::class, - PackagistSyncCommand::getDefaultName() => PackagistSyncCommand::class, - GenerateSriCommand::getDefaultName() => GenerateSriCommand::class, - ResetCacheCommand::getDefaultName() => ResetCacheCommand::class, - UpdateCommand::getDefaultName() => UpdateCommand::class, - ]; - - return new ContainerLoader($container, $mapping); - } - - /** - * Get the ConsoleApplication service - * - * @param Container $container The DI container. - * - * @return ConsoleApplication - */ - public function getConsoleApplicationService(Container $container): ConsoleApplication - { - $application = new ConsoleApplication(new ArgvInput, new ConsoleOutput, $container->get('config')); - - $application->setCommandLoader($container->get(LoaderInterface::class)); - $application->setDispatcher($container->get(DispatcherInterface::class)); - $application->setLogger($container->get(LoggerInterface::class)); - $application->setName('Joomla! Framework Website'); - - return $application; - } - - /** - * Get the `controller.api.package` service - * - * @param Container $container The DI container. - * - * @return PackageControllerGet - */ - public function getControllerApiPackageService(Container $container): PackageControllerGet - { - $controller = new PackageControllerGet( - $container->get(PackageJsonView::class), - $container->get(Analytics::class), - $container->get(Input::class), - $container->get(WebApplication::class) - ); - - $controller->setLogger($container->get(LoggerInterface::class)); - - return $controller; - } - - /** - * Get the `controller.api.status` service - * - * @param Container $container The DI container. - * - * @return StatusControllerGet - */ - public function getControllerApiStatusService(Container $container): StatusControllerGet - { - $controller = new StatusControllerGet( - $container->get(StatusJsonView::class), - $container->get(Analytics::class), - $container->get(Input::class), - $container->get(WebApplication::class) - ); - - $controller->setLogger($container->get(LoggerInterface::class)); - - return $controller; - } - - /** - * Get the `controller.homepage` service - * - * @param Container $container The DI container. - * - * @return HomepageController - */ - public function getControllerHomepageService(Container $container): HomepageController - { - return new HomepageController( + return new LoginController( $container->get(RendererInterface::class), $container->get(Input::class), - $container->get(WebApplication::class) + $container->get(AdminApplication::class) ); } /** - * Get the `controller.package` service + * Get the `controller.dashboard` service * * @param Container $container The DI container. * - * @return PackageController + * @return DashboardController */ - public function getControllerPackageService(Container $container): PackageController + public function getControllerDashboardService(Container $container): DashboardController { - return new PackageController( - $container->get(PackageHtmlView::class), + return new DashboardController( + $container->get(DashboardHtmlView::class), $container->get(Input::class), - $container->get(WebApplication::class) - ); - } - - /** - * Get the `controller.page` service - * - * @param Container $container The DI container. - * - * @return PageController - */ - public function getControllerPageService(Container $container): PageController - { - return new PageController( - $container->get(RendererInterface::class), - $container->get(Input::class), - $container->get(WebApplication::class) - ); - } - - /** - * Get the controller resolver service - * - * @param Container $container The DI container. - * - * @return ControllerResolverInterface - */ - public function getControllerResolverService(Container $container): ControllerResolverInterface - { - return new ContainerControllerResolver($container); - } - - /** - * Get the `controller.status` service - * - * @param Container $container The DI container. - * - * @return StatusController - */ - public function getControllerStatusService(Container $container): StatusController - { - return new StatusController( - $container->get(StatusHtmlView::class), - $container->get(Input::class), - $container->get(WebApplication::class) + $container->get(AdminApplication::class) ); } @@ -479,64 +166,10 @@ class ApplicationProvider implements ServiceProviderInterface { return new WrongCmsController( $container->get(Input::class), - $container->get(WebApplication::class) + $container->get(AdminApplication::class) ); } - /** - * Get the DebugEventDispatcherCommand service - * - * @param Container $container The DI container. - * - * @return DebugEventDispatcherCommand - */ - public function getDebugEventDispatcherCommandService(Container $container): DebugEventDispatcherCommand - { - return new DebugEventDispatcherCommand( - $container->get(DispatcherInterface::class) - ); - } - - /** - * Get the DebugRouterCommand service - * - * @param Container $container The DI container. - * - * @return DebugRouterCommand - */ - public function getDebugRouterCommandService(Container $container): DebugRouterCommand - { - return new DebugRouterCommand( - $container->get(Router::class) - ); - } - - /** - * Get the DownloadsCommand service - * - * @param Container $container The DI container. - * - * @return DownloadsCommand - */ - public function getDownloadsCommandService(Container $container): DownloadsCommand - { - return new DownloadsCommand( - $container->get(PackagistHelper::class) - ); - } - - /** - * Get the GenerateSriCommand service - * - * @param Container $container The DI container. - * - * @return GenerateSriCommand - */ - public function getGenerateSriCommandService(Container $container): GenerateSriCommand - { - return new GenerateSriCommand; - } - /** * Get the Input class service * @@ -550,156 +183,15 @@ class ApplicationProvider implements ServiceProviderInterface } /** - * Get the `model.package` service + * Get the `model.dashboard` service * * @param Container $container The DI container. * - * @return PackageModel + * @return DashboardModel */ - public function getModelPackageService(Container $container): PackageModel + public function getModelDashboardService(Container $container): DashboardModel { - return new PackageModel($container->get(DatabaseInterface::class)); - } - - /** - * Get the `model.release` service - * - * @param Container $container The DI container. - * - * @return ReleaseModel - */ - public function getModelReleaseService(Container $container): ReleaseModel - { - return new ReleaseModel($container->get(DatabaseInterface::class)); - } - - /** - * Get the PackageSyncCommand service - * - * @param Container $container The DI container. - * - * @return PackageSyncCommand - */ - public function getPackageSyncCommandService(Container $container): PackageSyncCommand - { - return new PackageSyncCommand( - $container->get(Helper::class), - $container->get(PackageModel::class) - ); - } - - /** - * Get the PackagistSyncCommand service - * - * @param Container $container The DI container. - * - * @return PackagistSyncCommand - */ - public function getPackagistSyncCommandService(Container $container): PackagistSyncCommand - { - return new PackagistSyncCommand( - $container->get(Http::class), - $container->get(PackageModel::class), - $container->get(ReleaseModel::class) - ); - } - - /** - * Get the ResetCacheCommand service - * - * @param Container $container The DI container. - * - * @return ResetCacheCommand - */ - public function getResetCacheCommandService(Container $container): ResetCacheCommand - { - return new ResetCacheCommand( - $container->get(TwigRenderer::class), - $container->get('config') - ); - } - - /** - * Get the UpdateCommand service - * - * @param Container $container The DI container. - * - * @return UpdateCommand - */ - public function getUpdateCommandService(Container $container): UpdateCommand - { - return new UpdateCommand; - } - - /** - * Get the `view.package.html` service - * - * @param Container $container The DI container. - * - * @return PackageHtmlView - */ - public function getViewPackageHtmlService(Container $container): PackageHtmlView - { - $view = new PackageHtmlView( - $container->get('model.package'), - $container->get('model.release'), - $container->get(Helper::class), - $container->get('renderer') - ); - - $view->setLayout('package.twig'); - - return $view; - } - - /** - * Get the `view.package.json` service - * - * @param Container $container The DI container. - * - * @return PackageJsonView - */ - public function getViewPackageJsonService(Container $container): PackageJsonView - { - return new PackageJsonView( - $container->get('model.package'), - $container->get('model.release') - ); - } - - /** - * Get the `view.status.html` service - * - * @param Container $container The DI container. - * - * @return StatusHtmlView - */ - public function getViewStatusHtmlService(Container $container): StatusHtmlView - { - $view = new StatusHtmlView( - $container->get('model.package'), - $container->get('model.release'), - $container->get('renderer') - ); - - $view->setLayout('status.twig'); - - return $view; - } - - /** - * Get the `view.status.json` service - * - * @param Container $container The DI container. - * - * @return StatusJsonView - */ - public function getViewStatusJsonService(Container $container): StatusJsonView - { - return new StatusJsonView( - $container->get('model.package'), - $container->get('model.release') - ); + return new DashboardModel($container->get(DatabaseInterface::class)); } /** @@ -707,11 +199,12 @@ class ApplicationProvider implements ServiceProviderInterface * * @param Container $container The DI container. * - * @return WebApplication + * @return AdminApplication */ - public function getWebApplicationClassService(Container $container): WebApplication + public function getAdminApplicationClassService(Container $container): AdminApplication { - $application = new WebApplication( + /** @var \Octoleo\CMS\Application\AdminApplication $application */ + $application = new AdminApplication( $container->get(ControllerResolverInterface::class), $container->get(RouterInterface::class), $container->get(Input::class), @@ -724,10 +217,39 @@ class ApplicationProvider implements ServiceProviderInterface // Inject extra services $application->setDispatcher($container->get(DispatcherInterface::class)); $application->setLogger($container->get(LoggerInterface::class)); + $application->setSession($container->get(SessionInterface::class)); + $application->setUserFactory($container->get(UserFactoryInterface::class)); return $application; } + /** + * Get the controller resolver service + * + * @param Container $container The DI container. + * + * @return ControllerResolverInterface + */ + public function getControllerResolverService(Container $container): ControllerResolverInterface + { + return new ContainerControllerResolver($container); + } + + /** + * Get the `view.page.html` service + * + * @param Container $container The DI container. + * + * @return DashboardHtmlView + */ + public function getViewDashboardHtmlService(Container $container): DashboardHtmlView + { + return new DashboardHtmlView( + $container->get('model.dashboard'), + $container->get('renderer') + ); + } + /** * Get the web client service * diff --git a/week-03/project/libraries/src/Service/ConfigurationProvider.php b/week-03/project/libraries/src/Service/ConfigurationProvider.php index 455c294..f655f82 100644 --- a/week-03/project/libraries/src/Service/ConfigurationProvider.php +++ b/week-03/project/libraries/src/Service/ConfigurationProvider.php @@ -1,20 +1,19 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Service; +namespace Octoleo\CMS\Service; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Registry\Registry; -/** - * Configuration service provider - */ class ConfigurationProvider implements ServiceProviderInterface { /** @@ -39,10 +38,21 @@ class ConfigurationProvider implements ServiceProviderInterface throw new \RuntimeException('Configuration file does not exist or is unreadable.'); } - $this->config = (new Registry)->loadFile($file); + // load the class + include_once $file; + $this->config = new Registry(new \LConfig()); - // Hardcode database driver option - $this->config->set('database.driver', 'mysql'); + // Set database values based on config values + $this->config->loadObject( (object) ['database' => [ + 'driver' => 'mysql', + 'host' => $this->config->get('host'), + 'port' => $this->config->get('port', ''), + 'user' => $this->config->get('user'), + 'password' => $this->config->get('password'), + 'database' => $this->config->get('db'), + 'prefix' => $this->config->get('dbprefix') + ] + ]); } /** diff --git a/week-03/project/libraries/src/Service/EventProvider.php b/week-03/project/libraries/src/Service/EventProvider.php index 4fdfa8d..9940861 100644 --- a/week-03/project/libraries/src/Service/EventProvider.php +++ b/week-03/project/libraries/src/Service/EventProvider.php @@ -1,23 +1,24 @@ get('log.application', $config->get('log.level', 'error'))); - return new StreamHandler(JPATH_ROOT . '/logs/framework.log', \constant('\\Monolog\\Logger::' . $level)); + return new StreamHandler(LPATH_ROOT . '/logs/framework.log', \constant('\\Monolog\\Logger::' . $level)); } /** @@ -128,4 +129,4 @@ class LoggingProvider implements ServiceProviderInterface { return new WebProcessor; } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/Service/SessionProvider.php b/week-03/project/libraries/src/Service/SessionProvider.php index 82b06a6..4ee6fda 100644 --- a/week-03/project/libraries/src/Service/SessionProvider.php +++ b/week-03/project/libraries/src/Service/SessionProvider.php @@ -1,47 +1,32 @@ - * @license GNU General Public License version 2 or later; see LICENSE + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\Service\Provider; +namespace Octoleo\CMS\Service; -\defined('JPATH_PLATFORM') or die; - -use Joomla\CMS\Application\AdministratorApplication; -use Joomla\CMS\Application\ApplicationHelper; -use Joomla\CMS\Application\CMSApplicationInterface; -use Joomla\CMS\Application\ConsoleApplication; -use Joomla\CMS\Application\SiteApplication; -use Joomla\CMS\Factory; -use Joomla\CMS\Installation\Application\InstallationApplication; -use Joomla\CMS\Session\EventListener\MetadataManagerListener; -use Joomla\CMS\Session\MetadataManager; -use Joomla\CMS\Session\SessionFactory; -use Joomla\CMS\Session\SessionManager; -use Joomla\CMS\Session\Storage\JoomlaStorage; +use Joomla\Application\AbstractWebApplication; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; -use Joomla\DI\Exception\DependencyResolutionException; use Joomla\DI\ServiceProviderInterface; -use Joomla\Event\DispatcherInterface; -use Joomla\Event\LazyServiceEventListener; -use Joomla\Event\Priority; -use Joomla\Registry\Registry; -use Joomla\Session\HandlerInterface; -use Joomla\Session\SessionEvents; +use Joomla\Event\Dispatcher; +use Joomla\Session\Session; use Joomla\Session\SessionInterface; -use Joomla\Session\Storage\RuntimeStorage; +use Joomla\Session\Storage\NativeStorage as SessionNativeStorage; use Joomla\Session\StorageInterface; +use Joomla\Session\Handler\DatabaseHandler as SessionDatabaseHandler; +use Joomla\Session\HandlerInterface; +use Octoleo\CMS\Session\MetadataManager; /** - * Service provider for the application's session dependency - * - * @since 4.0.0 + * Session service provider */ -class Session implements ServiceProviderInterface +class SessionProvider implements ServiceProviderInterface { /** * Registers the service provider with a DI container. @@ -49,312 +34,95 @@ class Session implements ServiceProviderInterface * @param Container $container The DI container. * * @return void - * - * @since 4.0.0 */ - public function register(Container $container) + public function register(Container $container): void { - $container->share( - 'session.web.administrator', - function (Container $container) - { - /** @var Registry $config */ - $config = $container->get('config'); - $app = Factory::getApplication(); - // Generate a session name. - $name = ApplicationHelper::getHash($config->get('session_name', AdministratorApplication::class)); + $container->alias(SessionDatabaseHandler::class, HandlerInterface::class) + ->share(HandlerInterface::class, [$this, 'getSessionDatabaseHandlerClassService'], true); - // Calculate the session lifetime. - $lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900; + $container->alias(SessionNativeStorage::class, StorageInterface::class) + ->share(StorageInterface::class, [$this, 'getSessionNativeStorageClassService'], true); - // Initialize the options for the Session object. - $options = [ - 'name' => $name, - 'expire' => $lifetime, - ]; + $container->alias(Session::class, SessionInterface::class) + ->share(SessionInterface::class, [$this, 'getSessionClassService'], true); - if ($config->get('force_ssl') >= 1) - { - $options['force_ssl'] = true; - } - - $handler = $container->get('session.factory')->createSessionHandler($options); - - if (!$container->has('session.handler')) - { - $this->registerSessionHandlerAsService($container, $handler); - } - - return $this->buildSession( - new JoomlaStorage($app->input, $handler), - $app, - $container->get(DispatcherInterface::class), - $options - ); - }, - true - ); - - $container->share( - 'session.web.installation', - function (Container $container) - { - /** @var Registry $config */ - $config = $container->get('config'); - $app = Factory::getApplication(); - - /** - * Session handler for the session is always filesystem so it doesn't flip to the database after - * configuration.php has been written to - */ - $config->set('session_handler', 'filesystem'); - - /** - * Generate a session name - unlike all the other apps we don't have either a secret or a session name - * (that's not the app name) until we complete installation which then leads to us dropping things like - * language preferences after installation as the app refreshes. - */ - $name = md5(serialize(JPATH_ROOT . InstallationApplication::class)); - - // Calculate the session lifetime. - $lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900; - - // Initialize the options for the Session object. - $options = [ - 'name' => $name, - 'expire' => $lifetime, - ]; - - $handler = $container->get('session.factory')->createSessionHandler($options); - - if (!$container->has('session.handler')) - { - $this->registerSessionHandlerAsService($container, $handler); - } - - return $this->buildSession( - new JoomlaStorage($app->input, $handler), - $app, - $container->get(DispatcherInterface::class), - $options - ); - }, - true - ); - - $container->share( - 'session.web.site', - function (Container $container) - { - /** @var Registry $config */ - $config = $container->get('config'); - $app = Factory::getApplication(); - - // Generate a session name. - $name = ApplicationHelper::getHash($config->get('session_name', SiteApplication::class)); - - // Calculate the session lifetime. - $lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900; - - // Initialize the options for the Session object. - $options = [ - 'name' => $name, - 'expire' => $lifetime, - ]; - - if ($config->get('force_ssl') == 2) - { - $options['force_ssl'] = true; - } - - $handler = $container->get('session.factory')->createSessionHandler($options); - - if (!$container->has('session.handler')) - { - $this->registerSessionHandlerAsService($container, $handler); - } - - return $this->buildSession( - new JoomlaStorage($app->input, $handler), - $app, - $container->get(DispatcherInterface::class), - $options - ); - }, - true - ); - - $container->share( - 'session.cli', - function (Container $container) - { - /** @var Registry $config */ - $config = $container->get('config'); - $app = Factory::getApplication(); - - // Generate a session name. - $name = ApplicationHelper::getHash($config->get('session_name', ConsoleApplication::class)); - - // Calculate the session lifetime. - $lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900; - - // Initialize the options for the Session object. - $options = [ - 'name' => $name, - 'expire' => $lifetime, - ]; - - // Unlike the web apps, we will only toggle the force SSL setting based on it being enabled and not based on client - if ($config->get('force_ssl') >= 1) - { - $options['force_ssl'] = true; - } - - $handler = $container->get('session.factory')->createSessionHandler($options); - - if (!$container->has('session.handler')) - { - $this->registerSessionHandlerAsService($container, $handler); - } - - return $this->buildSession( - new RuntimeStorage, - $app, - $container->get(DispatcherInterface::class), - $options - ); - }, - true - ); - - $container->alias(SessionFactory::class, 'session.factory') - ->share( - 'session.factory', - function (Container $container) - { - $factory = new SessionFactory; - $factory->setContainer($container); - - return $factory; - }, - true - ); - - $container->alias(SessionManager::class, 'session.manager') - ->share( - 'session.manager', - function (Container $container) - { - if (!$container->has('session.handler')) - { - throw new DependencyResolutionException( - 'The "session.handler" service has not been created, make sure you have created the "session" service first.' - ); - } - - return new SessionManager($container->get('session.handler')); - }, - true - ); - - $container->alias(MetadataManager::class, 'session.metadata_manager') - ->share( - 'session.metadata_manager', - function (Container $container) - { - /* - * Normally we should inject the application as a dependency via $container->get() however there is not - * a 'app' or CMSApplicationInterface::class key for the primary application of the request so we need to - * rely on the application having been injected to the global Factory otherwise we cannot build the service - */ - if (!Factory::$application) - { - throw new DependencyResolutionException( - sprintf( - 'Creating the "session.metadata_manager" service requires %s::$application be initialised.', - Factory::class - ) - ); - } - - return new MetadataManager(Factory::$application, $container->get(DatabaseInterface::class)); - }, - true - ); - - $container->alias(MetadataManagerListener::class, 'session.event_listener.metadata_manager') - ->share( - 'session.event_listener.metadata_manager', - function (Container $container) - { - return new MetadataManagerListener($container->get(MetadataManager::class), $container->get('config')); - }, - true - ); - - $listener = new LazyServiceEventListener($container, 'session.event_listener.metadata_manager', 'onAfterSessionStart'); - - /** @var DispatcherInterface $dispatcher */ - $dispatcher = $container->get(DispatcherInterface::class); - $dispatcher->addListener(SessionEvents::START, $listener); + $container->alias(MetadataManager::class, MetadataManager::class) + ->share(MetadataManager::class, [$this, 'getMetadataManagerClassService'], true); } /** - * Build the root session service + * Get the session metadata manager service * - * @param StorageInterface $storage The session storage engine. - * @param CMSApplicationInterface $app The application instance. - * @param DispatcherInterface $dispatcher The event dispatcher. - * @param array $options The configured session options. + * @param Container $container The DI container. + * + * @return MetadataManager + */ + public function getMetadataManagerClassService(Container $container): MetadataManager + { + return new MetadataManager( + $container->get(DatabaseInterface::class) + ); + } + + /** + * Get the `admin.session` service + * + * @param Container $container The DI container. * * @return SessionInterface - * - * @since 4.0.0 + * @throws \Exception */ - private function buildSession( - StorageInterface $storage, - CMSApplicationInterface $app, - DispatcherInterface $dispatcher, - array $options - ): SessionInterface + public function getSessionClassService(Container $container): SessionInterface { - $input = $app->input; + /** @var \Joomla\Session\Session; $session */ + $session = new Session($container->get(SessionNativeStorage::class), $container->get(Dispatcher::class)); - if (method_exists($app, 'afterSessionStart')) + // Start session if not already started + if (empty($session->getId())) { - $dispatcher->addListener(SessionEvents::START, [$app, 'afterSessionStart'], Priority::HIGH); + $session->start(); } - $session = new \Joomla\CMS\Session\Session($storage, $dispatcher, $options); - return $session; } /** - * Registers the session handler as a service + * Get the Session Database Handler service * - * @param Container $container The container to register the service to. - * @param \SessionHandlerInterface $sessionHandler The session handler. + * @param Container $container The DI container. * - * @return void - * - * @since 4.0.0 + * @return HandlerInterface */ - private function registerSessionHandlerAsService(Container $container, \SessionHandlerInterface $sessionHandler): void + public function getSessionDatabaseHandlerClassService(Container $container): HandlerInterface { - // Alias the session handler to the core SessionHandlerInterface for improved autowiring and discoverability - $container->alias(\SessionHandlerInterface::class, 'session.handler') - ->share( - 'session.handler', - $sessionHandler, - true - ); + return new SessionDatabaseHandler($container->get(DatabaseInterface::class)); + } - // If the session handler implements the extended interface, register an alias for that as well - if ($sessionHandler instanceof HandlerInterface) - { - $container->alias(HandlerInterface::class, 'session.handler'); - } + /** + * Get the `admin.session` service + * + * @param Container $container The DI container. + * + * @return StorageInterface + */ + public function getSessionNativeStorageClassService(Container $container): StorageInterface + { + /** @var \Joomla\Registry\Registry $config */ + $config = $container->get('config'); + + // Generate a session name. (not secure enough) + $name = md5('octoleoAdmin'); + + // Calculate the session lifetime. + $lifetime = $config->get('lifetime') ? $config->get('lifetime') * 60 : 900; + + // Initialize the options for the Session object. + $options = [ + 'name' => $name, + 'expire' => $lifetime + ]; + + return new SessionNativeStorage($container->get(SessionDatabaseHandler::class), $options); } } diff --git a/week-03/project/libraries/src/Service/SiteApplicationProvider.php b/week-03/project/libraries/src/Service/SiteApplicationProvider.php index 648b1bf..01008e6 100644 --- a/week-03/project/libraries/src/Service/SiteApplicationProvider.php +++ b/week-03/project/libraries/src/Service/SiteApplicationProvider.php @@ -1,65 +1,43 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\Service; +namespace Octoleo\CMS\Service; use Joomla\Application\AbstractWebApplication; use Joomla\Application\Controller\ContainerControllerResolver; use Joomla\Application\Controller\ControllerResolverInterface; use Joomla\Application\Web\WebClient; -use Joomla\Console\Application as ConsoleApplication; -use Joomla\Console\Loader\ContainerLoader; -use Joomla\Console\Loader\LoaderInterface; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; -use Joomla\Event\Command\DebugEventDispatcherCommand; use Joomla\Event\DispatcherInterface; -use Joomla\FrameworkWebsite\Command\GenerateSriCommand; -use Joomla\FrameworkWebsite\Command\Package\SyncCommand as PackageSyncCommand; -use Joomla\FrameworkWebsite\Command\Packagist\DownloadsCommand; -use Joomla\FrameworkWebsite\Command\Packagist\SyncCommand as PackagistSyncCommand; -use Joomla\FrameworkWebsite\Command\Twig\ResetCacheCommand; -use Joomla\FrameworkWebsite\Command\UpdateCommand; -use Joomla\FrameworkWebsite\Controller\Api\PackageControllerGet; -use Joomla\FrameworkWebsite\Controller\Api\StatusControllerGet; -use Joomla\FrameworkWebsite\Controller\HomepageController; -use Joomla\FrameworkWebsite\Controller\PackageController; -use Joomla\FrameworkWebsite\Controller\PageController; -use Joomla\FrameworkWebsite\Controller\StatusController; -use Joomla\FrameworkWebsite\Controller\WrongCmsController; -use Joomla\FrameworkWebsite\Helper; -use Joomla\FrameworkWebsite\Helper\PackagistHelper; -use Joomla\FrameworkWebsite\Model\PackageModel; -use Joomla\FrameworkWebsite\Model\ReleaseModel; -use Joomla\FrameworkWebsite\View\Package\PackageHtmlView; -use Joomla\FrameworkWebsite\View\Package\PackageJsonView; -use Joomla\FrameworkWebsite\View\Status\StatusHtmlView; -use Joomla\FrameworkWebsite\View\Status\StatusJsonView; -use Joomla\FrameworkWebsite\WebApplication; -use Joomla\Http\Http; + +use Octoleo\CMS\Controller\HomepageController; +use Octoleo\CMS\Controller\WrongCmsController; +use Octoleo\CMS\Controller\PageController; +use Octoleo\CMS\Model\PageModel; +use Octoleo\CMS\View\Page\PageHtmlView; +use Octoleo\CMS\Application\SiteApplication; + use Joomla\Input\Input; -use Joomla\Registry\Registry; use Joomla\Renderer\RendererInterface; -use Joomla\Renderer\TwigRenderer; -use Joomla\Router\Command\DebugRouterCommand; use Joomla\Router\Route; use Joomla\Router\Router; use Joomla\Router\RouterInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Output\ConsoleOutput; -use TheIconic\Tracking\GoogleAnalytics\Analytics; /** * Application service provider + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Service/ApplicationProvider.php */ -class ApplicationProvider implements ServiceProviderInterface +class SiteApplicationProvider implements ServiceProviderInterface { /** * Registers the service provider with a DI container. @@ -74,34 +52,18 @@ class ApplicationProvider implements ServiceProviderInterface * Application Classes */ - $container->share(ConsoleApplication::class, [$this, 'getConsoleApplicationService'], true); - // This service cannot be protected as it is decorated when the debug bar is available - $container->alias(WebApplication::class, AbstractWebApplication::class) - ->share(AbstractWebApplication::class, [$this, 'getWebApplicationClassService']); + $container->alias(SiteApplication::class, AbstractWebApplication::class) + ->share(AbstractWebApplication::class, [$this, 'getSiteApplicationClassService']); /* * Application Helpers and Dependencies */ - $container->alias(Analytics::class, 'analytics') - ->share('analytics', [$this, 'getAnalyticsService'], true); - - $container->alias(ContainerLoader::class, LoaderInterface::class) - ->share(LoaderInterface::class, [$this, 'getCommandLoaderService'], true); - // This service cannot be protected as it is decorated when the debug bar is available $container->alias(ContainerControllerResolver::class, ControllerResolverInterface::class) ->share(ControllerResolverInterface::class, [$this, 'getControllerResolverService']); - $container->alias(Helper::class, 'application.helper') - ->share('application.helper', [$this, 'getApplicationHelperService'], true); - - $container->alias(PackagistHelper::class, 'application.helper.packagist') - ->share('application.helper.packagist', [$this, 'getApplicationHelperPackagistService'], true); - - $container->share('application.packages', [$this, 'getApplicationPackagesService'], true); - $container->share(WebClient::class, [$this, 'getWebClientService'], true); // This service cannot be protected as it is decorated when the debug bar is available @@ -111,118 +73,27 @@ class ApplicationProvider implements ServiceProviderInterface $container->share(Input::class, [$this, 'getInputClassService'], true); - /* - * Console Commands - */ - - $container->share(DebugEventDispatcherCommand::class, [$this, 'getDebugEventDispatcherCommandService'], true); - $container->share(DebugRouterCommand::class, [$this, 'getDebugRouterCommandService'], true); - $container->share(DownloadsCommand::class, [$this, 'getDownloadsCommandService'], true); - $container->share(GenerateSriCommand::class, [$this, 'getGenerateSriCommandService'], true); - $container->share(PackageSyncCommand::class, [$this, 'getPackageSyncCommandService'], true); - $container->share(PackagistSyncCommand::class, [$this, 'getPackagistSyncCommandService'], true); - $container->share(ResetCacheCommand::class, [$this, 'getResetCacheCommandService'], true); - $container->share(UpdateCommand::class, [$this, 'getUpdateCommandService'], true); - /* * MVC Layer */ // Controllers - $container->alias(PackageControllerGet::class, 'controller.api.package') - ->share('controller.api.package', [$this, 'getControllerApiPackageService'], true); - - $container->alias(StatusControllerGet::class, 'controller.api.status') - ->share('controller.api.status', [$this, 'getControllerApiStatusService'], true); - $container->alias(HomepageController::class, 'controller.homepage') ->share('controller.homepage', [$this, 'getControllerHomepageService'], true); - $container->alias(PackageController::class, 'controller.package') - ->share('controller.package', [$this, 'getControllerPackageService'], true); - $container->alias(PageController::class, 'controller.page') ->share('controller.page', [$this, 'getControllerPageService'], true); - $container->alias(StatusController::class, 'controller.status') - ->share('controller.status', [$this, 'getControllerStatusService'], true); - $container->alias(WrongCmsController::class, 'controller.wrong.cms') ->share('controller.wrong.cms', [$this, 'getControllerWrongCmsService'], true); // Models - $container->alias(PackageModel::class, 'model.package') - ->share('model.package', [$this, 'getModelPackageService'], true); - - $container->alias(ReleaseModel::class, 'model.release') - ->share('model.release', [$this, 'getModelReleaseService'], true); + $container->alias(PageModel::class, 'model.page') + ->share('model.page', [$this, 'getModelPageService'], true); // Views - $container->alias(PackageHtmlView::class, 'view.package.html') - ->share('view.package.html', [$this, 'getViewPackageHtmlService'], true); - - $container->alias(PackageJsonView::class, 'view.package.json') - ->share('view.package.json', [$this, 'getViewPackageJsonService'], true); - - $container->alias(StatusHtmlView::class, 'view.status.html') - ->share('view.status.html', [$this, 'getViewStatusHtmlService'], true); - - $container->alias(StatusJsonView::class, 'view.status.json') - ->share('view.status.json', [$this, 'getViewStatusJsonService'], true); - } - - /** - * Get the Analytics class service - * - * @param Container $container The DI container. - * - * @return Analytics - */ - public function getAnalyticsService(Container $container) - { - return new Analytics(true); - } - - /** - * Get the `application.helper` service - * - * @param Container $container The DI container. - * - * @return Helper - */ - public function getApplicationHelperService(Container $container): Helper - { - $helper = new Helper; - $helper->setPackages($container->get('application.packages')); - - return $helper; - } - - /** - * Get the `application.helper.packagist` service - * - * @param Container $container The DI container. - * - * @return PackagistHelper - */ - public function getApplicationHelperPackagistService(Container $container): PackagistHelper - { - $helper = new PackagistHelper($container->get(Http::class), $container->get(DatabaseInterface::class)); - $helper->setPackages($container->get('application.packages')); - - return $helper; - } - - /** - * Get the `application.packages` service - * - * @param Container $container The DI container. - * - * @return Registry - */ - public function getApplicationPackagesService(Container $container): Registry - { - return (new Registry)->loadFile(JPATH_ROOT . '/packages.yml', 'YAML'); + $container->alias(PageHtmlView::class, 'view.page.html') + ->share('view.page.html', [$this, 'getViewPageHtmlService'], true); } /** @@ -239,16 +110,6 @@ class ApplicationProvider implements ServiceProviderInterface /* * CMS Admin Panels */ - $router->get( - '/administrator', - WrongCmsController::class - ); - - $router->get( - '/administrator/*', - WrongCmsController::class - ); - $router->get( '/wp-admin', WrongCmsController::class @@ -270,8 +131,8 @@ class ApplicationProvider implements ServiceProviderInterface $router->addRoute(new Route(['GET', 'HEAD'], '/', HomepageController::class)); $router->get( - '/status', - StatusController::class + '/:view', + PageController::class ); $router->get( @@ -280,118 +141,13 @@ class ApplicationProvider implements ServiceProviderInterface ); $router->get( - '/status/:package', - PackageController::class - ); - - /* - * API routes - */ - $router->get( - '/api/v1/packages', - StatusControllerGet::class, - [], - [ - '_format' => 'json', - ] - ); - - $router->get( - '/api/v1/packages/:package', - PackageControllerGet::class, - [], - [ - '_format' => 'json', - ] + '/:view/:details', + PageController::class ); return $router; } - /** - * Get the LoaderInterface service - * - * @param Container $container The DI container. - * - * @return LoaderInterface - */ - public function getCommandLoaderService(Container $container): LoaderInterface - { - $mapping = [ - DebugEventDispatcherCommand::getDefaultName() => DebugEventDispatcherCommand::class, - DebugRouterCommand::getDefaultName() => DebugRouterCommand::class, - DownloadsCommand::getDefaultName() => DownloadsCommand::class, - PackageSyncCommand::getDefaultName() => PackageSyncCommand::class, - PackagistSyncCommand::getDefaultName() => PackagistSyncCommand::class, - GenerateSriCommand::getDefaultName() => GenerateSriCommand::class, - ResetCacheCommand::getDefaultName() => ResetCacheCommand::class, - UpdateCommand::getDefaultName() => UpdateCommand::class, - ]; - - return new ContainerLoader($container, $mapping); - } - - /** - * Get the ConsoleApplication service - * - * @param Container $container The DI container. - * - * @return ConsoleApplication - */ - public function getConsoleApplicationService(Container $container): ConsoleApplication - { - $application = new ConsoleApplication(new ArgvInput, new ConsoleOutput, $container->get('config')); - - $application->setCommandLoader($container->get(LoaderInterface::class)); - $application->setDispatcher($container->get(DispatcherInterface::class)); - $application->setLogger($container->get(LoggerInterface::class)); - $application->setName('Joomla! Framework Website'); - - return $application; - } - - /** - * Get the `controller.api.package` service - * - * @param Container $container The DI container. - * - * @return PackageControllerGet - */ - public function getControllerApiPackageService(Container $container): PackageControllerGet - { - $controller = new PackageControllerGet( - $container->get(PackageJsonView::class), - $container->get(Analytics::class), - $container->get(Input::class), - $container->get(WebApplication::class) - ); - - $controller->setLogger($container->get(LoggerInterface::class)); - - return $controller; - } - - /** - * Get the `controller.api.status` service - * - * @param Container $container The DI container. - * - * @return StatusControllerGet - */ - public function getControllerApiStatusService(Container $container): StatusControllerGet - { - $controller = new StatusControllerGet( - $container->get(StatusJsonView::class), - $container->get(Analytics::class), - $container->get(Input::class), - $container->get(WebApplication::class) - ); - - $controller->setLogger($container->get(LoggerInterface::class)); - - return $controller; - } - /** * Get the `controller.homepage` service * @@ -404,23 +160,7 @@ class ApplicationProvider implements ServiceProviderInterface return new HomepageController( $container->get(RendererInterface::class), $container->get(Input::class), - $container->get(WebApplication::class) - ); - } - - /** - * Get the `controller.package` service - * - * @param Container $container The DI container. - * - * @return PackageController - */ - public function getControllerPackageService(Container $container): PackageController - { - return new PackageController( - $container->get(PackageHtmlView::class), - $container->get(Input::class), - $container->get(WebApplication::class) + $container->get(SiteApplication::class) ); } @@ -434,37 +174,9 @@ class ApplicationProvider implements ServiceProviderInterface public function getControllerPageService(Container $container): PageController { return new PageController( - $container->get(RendererInterface::class), + $container->get(PageHtmlView::class), $container->get(Input::class), - $container->get(WebApplication::class) - ); - } - - /** - * Get the controller resolver service - * - * @param Container $container The DI container. - * - * @return ControllerResolverInterface - */ - public function getControllerResolverService(Container $container): ControllerResolverInterface - { - return new ContainerControllerResolver($container); - } - - /** - * Get the `controller.status` service - * - * @param Container $container The DI container. - * - * @return StatusController - */ - public function getControllerStatusService(Container $container): StatusController - { - return new StatusController( - $container->get(StatusHtmlView::class), - $container->get(Input::class), - $container->get(WebApplication::class) + $container->get(SiteApplication::class) ); } @@ -479,64 +191,10 @@ class ApplicationProvider implements ServiceProviderInterface { return new WrongCmsController( $container->get(Input::class), - $container->get(WebApplication::class) + $container->get(SiteApplication::class) ); } - /** - * Get the DebugEventDispatcherCommand service - * - * @param Container $container The DI container. - * - * @return DebugEventDispatcherCommand - */ - public function getDebugEventDispatcherCommandService(Container $container): DebugEventDispatcherCommand - { - return new DebugEventDispatcherCommand( - $container->get(DispatcherInterface::class) - ); - } - - /** - * Get the DebugRouterCommand service - * - * @param Container $container The DI container. - * - * @return DebugRouterCommand - */ - public function getDebugRouterCommandService(Container $container): DebugRouterCommand - { - return new DebugRouterCommand( - $container->get(Router::class) - ); - } - - /** - * Get the DownloadsCommand service - * - * @param Container $container The DI container. - * - * @return DownloadsCommand - */ - public function getDownloadsCommandService(Container $container): DownloadsCommand - { - return new DownloadsCommand( - $container->get(PackagistHelper::class) - ); - } - - /** - * Get the GenerateSriCommand service - * - * @param Container $container The DI container. - * - * @return GenerateSriCommand - */ - public function getGenerateSriCommandService(Container $container): GenerateSriCommand - { - return new GenerateSriCommand; - } - /** * Get the Input class service * @@ -550,156 +208,15 @@ class ApplicationProvider implements ServiceProviderInterface } /** - * Get the `model.package` service + * Get the `model.page` service * * @param Container $container The DI container. * - * @return PackageModel + * @return PageModel */ - public function getModelPackageService(Container $container): PackageModel + public function getModelPageService(Container $container): PageModel { - return new PackageModel($container->get(DatabaseInterface::class)); - } - - /** - * Get the `model.release` service - * - * @param Container $container The DI container. - * - * @return ReleaseModel - */ - public function getModelReleaseService(Container $container): ReleaseModel - { - return new ReleaseModel($container->get(DatabaseInterface::class)); - } - - /** - * Get the PackageSyncCommand service - * - * @param Container $container The DI container. - * - * @return PackageSyncCommand - */ - public function getPackageSyncCommandService(Container $container): PackageSyncCommand - { - return new PackageSyncCommand( - $container->get(Helper::class), - $container->get(PackageModel::class) - ); - } - - /** - * Get the PackagistSyncCommand service - * - * @param Container $container The DI container. - * - * @return PackagistSyncCommand - */ - public function getPackagistSyncCommandService(Container $container): PackagistSyncCommand - { - return new PackagistSyncCommand( - $container->get(Http::class), - $container->get(PackageModel::class), - $container->get(ReleaseModel::class) - ); - } - - /** - * Get the ResetCacheCommand service - * - * @param Container $container The DI container. - * - * @return ResetCacheCommand - */ - public function getResetCacheCommandService(Container $container): ResetCacheCommand - { - return new ResetCacheCommand( - $container->get(TwigRenderer::class), - $container->get('config') - ); - } - - /** - * Get the UpdateCommand service - * - * @param Container $container The DI container. - * - * @return UpdateCommand - */ - public function getUpdateCommandService(Container $container): UpdateCommand - { - return new UpdateCommand; - } - - /** - * Get the `view.package.html` service - * - * @param Container $container The DI container. - * - * @return PackageHtmlView - */ - public function getViewPackageHtmlService(Container $container): PackageHtmlView - { - $view = new PackageHtmlView( - $container->get('model.package'), - $container->get('model.release'), - $container->get(Helper::class), - $container->get('renderer') - ); - - $view->setLayout('package.twig'); - - return $view; - } - - /** - * Get the `view.package.json` service - * - * @param Container $container The DI container. - * - * @return PackageJsonView - */ - public function getViewPackageJsonService(Container $container): PackageJsonView - { - return new PackageJsonView( - $container->get('model.package'), - $container->get('model.release') - ); - } - - /** - * Get the `view.status.html` service - * - * @param Container $container The DI container. - * - * @return StatusHtmlView - */ - public function getViewStatusHtmlService(Container $container): StatusHtmlView - { - $view = new StatusHtmlView( - $container->get('model.package'), - $container->get('model.release'), - $container->get('renderer') - ); - - $view->setLayout('status.twig'); - - return $view; - } - - /** - * Get the `view.status.json` service - * - * @param Container $container The DI container. - * - * @return StatusJsonView - */ - public function getViewStatusJsonService(Container $container): StatusJsonView - { - return new StatusJsonView( - $container->get('model.package'), - $container->get('model.release') - ); + return new PageModel($container->get(DatabaseInterface::class)); } /** @@ -707,11 +224,11 @@ class ApplicationProvider implements ServiceProviderInterface * * @param Container $container The DI container. * - * @return WebApplication + * @return SiteApplication */ - public function getWebApplicationClassService(Container $container): WebApplication + public function getSiteApplicationClassService(Container $container): SiteApplication { - $application = new WebApplication( + $application = new SiteApplication( $container->get(ControllerResolverInterface::class), $container->get(RouterInterface::class), $container->get(Input::class), @@ -728,6 +245,37 @@ class ApplicationProvider implements ServiceProviderInterface return $application; } + /** + * Get the controller resolver service + * + * @param Container $container The DI container. + * + * @return ControllerResolverInterface + */ + public function getControllerResolverService(Container $container): ControllerResolverInterface + { + return new ContainerControllerResolver($container); + } + + /** + * Get the `view.page.html` service + * + * @param Container $container The DI container. + * + * @return PageHtmlView + */ + public function getViewPageHtmlService(Container $container): PageHtmlView + { + $view = new PageHtmlView( + $container->get('model.page'), + $container->get('renderer') + ); + + $view->setLayout('page.twig'); + + return $view; + } + /** * Get the web client service * diff --git a/week-03/project/libraries/src/Service/TemplatingProvider.php b/week-03/project/libraries/src/Service/TemplatingProvider.php index a474465..608681c 100644 --- a/week-03/project/libraries/src/Service/TemplatingProvider.php +++ b/week-03/project/libraries/src/Service/TemplatingProvider.php @@ -6,15 +6,15 @@ * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later */ -namespace Joomla\FrameworkWebsite\Service; +namespace Octoleo\CMS\Service; use Joomla\Application\AbstractApplication; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; -use Joomla\FrameworkWebsite\Asset\MixPathPackage; -use Joomla\FrameworkWebsite\Renderer\ApplicationContext; -use Joomla\FrameworkWebsite\Renderer\FrameworkExtension; -use Joomla\FrameworkWebsite\Renderer\FrameworkTwigRuntime; +use Octoleo\CMS\Asset\MixPathPackage; +use Octoleo\CMS\Renderer\ApplicationContext; +use Octoleo\CMS\Renderer\FrameworkExtension; +use Octoleo\CMS\Renderer\FrameworkTwigRuntime; use Joomla\Preload\PreloadManager; use Joomla\Renderer\RendererInterface; use Joomla\Renderer\TwigRenderer; @@ -35,6 +35,7 @@ use Twig\RuntimeLoader\ContainerRuntimeLoader; /** * Templating service provider + * source: https://github.com/joomla/framework.joomla.org/blob/master/src/Service/TemplatingProvider.php */ class TemplatingProvider implements ServiceProviderInterface { @@ -113,7 +114,7 @@ class TemplatingProvider implements ServiceProviderInterface $mixStrategy = new MixPathPackage( $defaultPackage, $mediaPath, - new JsonManifestVersionStrategy(JPATH_ROOT . '/www/media/mix-manifest.json'), + new JsonManifestVersionStrategy(LPATH_ROOT . '/media/mix-manifest.json'), $context ); @@ -156,7 +157,7 @@ class TemplatingProvider implements ServiceProviderInterface if ($debug === false && $cacheEnabled !== false) { - return new FilesystemCache(JPATH_ROOT . '/' . $cachePath); + return new FilesystemCache(LPATH_ROOT . '/' . $cachePath); } return new NullCache; @@ -242,7 +243,7 @@ class TemplatingProvider implements ServiceProviderInterface */ public function getTwigLoaderService(Container $container): \Twig_LoaderInterface { - return new FilesystemLoader([JPATH_TEMPLATES]); + return new FilesystemLoader([LPATH_TEMPLATES]); } /** @@ -269,7 +270,7 @@ class TemplatingProvider implements ServiceProviderInterface return new FrameworkTwigRuntime( $container->get(AbstractApplication::class), $container->get(PreloadManager::class), - JPATH_ROOT . '/www/media/sri-manifest.json' + LPATH_ROOT . '/media/sri-manifest.json' ); } @@ -308,4 +309,4 @@ class TemplatingProvider implements ServiceProviderInterface $container->tag('twig.extension', $twigExtensions); } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/Service/UserProvider.php b/week-03/project/libraries/src/Service/UserProvider.php index a05b4ef..c6affef 100644 --- a/week-03/project/libraries/src/Service/UserProvider.php +++ b/week-03/project/libraries/src/Service/UserProvider.php @@ -1,27 +1,31 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\Service\Provider; +namespace Octoleo\CMS\Service; -\defined('JPATH_PLATFORM') or die; - -use Joomla\CMS\User\UserFactory; -use Joomla\CMS\User\UserFactoryInterface; +use Joomla\Authentication\AuthenticationStrategyInterface; +use Joomla\Authentication\Strategies\DatabaseStrategy; +use Joomla\Input\Input; +use Octoleo\CMS\User\UserFactory; +use Octoleo\CMS\User\UserFactoryInterface; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; /** - * Service provider for the user dependency - * - * @since 4.0.0 - */ -class User implements ServiceProviderInterface +* Service provider for the user dependency +* +* @since 1.0.0 +* source: https://github.com/joomla/joomla-cms/blob/4.2-dev/libraries/src/Service/Provider/User.php +*/ +class UserProvider implements ServiceProviderInterface { /** * Registers the service provider with a DI container. @@ -36,13 +40,40 @@ class User implements ServiceProviderInterface { $container->alias('user.factory', UserFactoryInterface::class) ->alias(UserFactory::class, UserFactoryInterface::class) - ->share( - UserFactoryInterface::class, - function (Container $container) - { - return new UserFactory($container->get(DatabaseInterface::class)); - }, - true - ); + ->share(UserFactoryInterface::class, [$this, 'getUserFactoryService'], true); + + $container->alias(DatabaseStrategy::class, AuthenticationStrategyInterface::class) + ->share(AuthenticationStrategyInterface::class, [$this, 'getAuthenticationStrategyService'], true); + } + + /** + * Get the UserFactoryInterface class service + * + * @param Container $container The DI container. + * + * @return UserFactoryInterface + * @throws \Exception + */ + public function getUserFactoryService(Container $container): UserFactoryInterface + { + return new UserFactory( + $container->get(DatabaseInterface::class), + $container->get(AuthenticationStrategyInterface::class) + ); + } + + /** + * Get the AuthenticationStrategyInterface class service + * + * @param Container $container The DI container. + * + * @return AuthenticationStrategyInterface + */ + public function getAuthenticationStrategyService(Container $container): AuthenticationStrategyInterface + { + return new DatabaseStrategy( + $container->get(Input::class), + $container->get(DatabaseInterface::class) + ); } } diff --git a/week-03/project/libraries/src/Session/MetadataManager.php b/week-03/project/libraries/src/Session/MetadataManager.php index 4c7b620..691fe29 100644 --- a/week-03/project/libraries/src/Session/MetadataManager.php +++ b/week-03/project/libraries/src/Session/MetadataManager.php @@ -6,13 +6,9 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\Session; +namespace Octoleo\CMS\Session; -\defined('JPATH_PLATFORM') or die; - -use Joomla\Application\AbstractApplication; -use Joomla\CMS\Application\CMSApplication; -use Joomla\CMS\User\User; +use Octoleo\CMS\User\User; use Joomla\Database\DatabaseInterface; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; @@ -53,14 +49,6 @@ final class MetadataManager */ private static $sessionRecordUnknown = -1; - /** - * Application object. - * - * @var AbstractApplication - * @since 3.8.6 - */ - private $app; - /** * Database driver. * @@ -72,14 +60,12 @@ final class MetadataManager /** * MetadataManager constructor. * - * @param AbstractApplication $app Application object. * @param DatabaseInterface $db Database driver. * * @since 3.8.6 */ - public function __construct(AbstractApplication $app, DatabaseInterface $db) + public function __construct(DatabaseInterface $db) { - $this->app = $app; $this->db = $db; } @@ -166,6 +152,29 @@ final class MetadataManager } } + /** + * Get session record exists + * + * @param string $sessionId The session ID to check + * + * @return mixed on success value for record presence + * + * @since 1.0.0 + */ + public function getSessionRecord(string $sessionId) + { + $query = $this->db->getQuery(true) + ->select('*') + ->from($this->db->quoteName('#__session')) + ->where($this->db->quoteName('session_id') . ' = :session_id') + ->bind(':session_id', $sessionId) + ->setLimit(1); + + $this->db->setQuery($query); + + return $this->db->loadObject(); + } + /** * Check if the session record exists * @@ -238,9 +247,9 @@ final class MetadataManager // Bind query values $sessionId = $session->getId(); - $userIsGuest = $user->guest; - $userId = $user->id; - $username = $user->username === null ? '' : $user->username; + $userIsGuest = $user->get('guest', 0); + $userId = $user->get('id', 0); + $username = $user->get('username', ''); $query->bind(':session_id', $sessionId) ->bind(':guest', $userIsGuest, ParameterType::INTEGER) @@ -248,16 +257,6 @@ final class MetadataManager ->bind(':user_id', $userId, ParameterType::INTEGER) ->bind(':username', $username); - if ($this->app instanceof CMSApplication && !$this->app->get('shared_session', false)) - { - $clientId = $this->app->getClientId(); - - $columns[] = $this->db->quoteName('client_id'); - $values[] = ':client_id'; - - $query->bind(':client_id', $clientId, ParameterType::INTEGER); - } - $query->insert($this->db->quoteName('#__session')) ->columns($columns) ->values(implode(', ', $values)); @@ -299,9 +298,9 @@ final class MetadataManager // Bind query values $sessionId = $session->getId(); - $userIsGuest = $user->guest; - $userId = $user->id; - $username = $user->username === null ? '' : $user->username; + $userIsGuest = $user->get('guest', 0); + $userId = $user->get('id', 0); + $username = $user->get('username', ''); $query->bind(':session_id', $sessionId) ->bind(':guest', $userIsGuest, ParameterType::INTEGER) @@ -309,15 +308,6 @@ final class MetadataManager ->bind(':user_id', $userId, ParameterType::INTEGER) ->bind(':username', $username); - if ($this->app instanceof CMSApplication && !$this->app->get('shared_session', false)) - { - $clientId = $this->app->getClientId(); - - $setValues[] = $this->db->quoteName('client_id') . ' = :client_id'; - - $query->bind(':client_id', $clientId, ParameterType::INTEGER); - } - $query->update($this->db->quoteName('#__session')) ->set($setValues) ->where($this->db->quoteName('session_id') . ' = :session_id'); @@ -333,4 +323,4 @@ final class MetadataManager // This failure isn't critical, we can go on without the metadata } } -} +} \ No newline at end of file diff --git a/week-03/project/libraries/src/String/PunycodeHelper.php b/week-03/project/libraries/src/String/PunycodeHelper.php index f839afe..5ece7c7 100644 --- a/week-03/project/libraries/src/String/PunycodeHelper.php +++ b/week-03/project/libraries/src/String/PunycodeHelper.php @@ -6,9 +6,7 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\String; - -\defined('JPATH_PLATFORM') or die; +namespace Octoleo\CMS\String; use Algo26\IdnaConvert\ToIdn; use Algo26\IdnaConvert\ToUnicode; diff --git a/week-03/project/libraries/src/User/User.php b/week-03/project/libraries/src/User/User.php index 85e0e83..cb91d0d 100644 --- a/week-03/project/libraries/src/User/User.php +++ b/week-03/project/libraries/src/User/User.php @@ -1,934 +1,76 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\User; +namespace Octoleo\CMS\User; -\defined('JPATH_PLATFORM') or die; - -use Joomla\CMS\Access\Access; -use Joomla\CMS\Factory; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Log\Log; -use Joomla\CMS\Object\CMSObject; -use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Table\Table; use Joomla\Registry\Registry; -use Joomla\Utilities\ArrayHelper; +use Joomla\Database\DatabaseInterface; +use Octoleo\CMS\Factory; /** * User class. Handles all application interaction with a user * - * @since 1.7.0 + * @since 1.0.0 */ -class User extends CMSObject +class User extends Registry { - /** - * A cached switch for if this user has root access rights. - * - * @var boolean - * @since 1.7.0 - */ - protected $isRoot = null; - - /** - * Unique id - * - * @var integer - * @since 1.7.0 - */ - public $id = null; - - /** - * The user's real name (or nickname) - * - * @var string - * @since 1.7.0 - */ - public $name = null; - - /** - * The login name - * - * @var string - * @since 1.7.0 - */ - public $username = null; - - /** - * The email - * - * @var string - * @since 1.7.0 - */ - public $email = null; - - /** - * MD5 encrypted password - * - * @var string - * @since 1.7.0 - */ - public $password = null; - - /** - * Clear password, only available when a new password is set for a user - * - * @var string - * @since 1.7.0 - */ - public $password_clear = ''; - - /** - * Block status - * - * @var integer - * @since 1.7.0 - */ - public $block = null; - - /** - * Should this user receive system email - * - * @var integer - * @since 1.7.0 - */ - public $sendEmail = null; - - /** - * Date the user was registered - * - * @var string - * @since 1.7.0 - */ - public $registerDate = null; - - /** - * Date of last visit - * - * @var string - * @since 1.7.0 - */ - public $lastvisitDate = null; - - /** - * Activation hash - * - * @var string - * @since 1.7.0 - */ - public $activation = null; - - /** - * User parameters - * - * @var Registry - * @since 1.7.0 - */ - public $params = null; - - /** - * Associative array of user names => group ids - * - * @var array - * @since 1.7.0 - */ - public $groups = array(); - - /** - * Guest status - * - * @var integer - * @since 1.7.0 - */ - public $guest = null; - - /** - * Last Reset Time - * - * @var string - * @since 3.0.1 - */ - public $lastResetTime = null; - - /** - * Count since last Reset Time - * - * @var integer - * @since 3.0.1 - */ - public $resetCount = null; - - /** - * Flag to require the user's password be reset - * - * @var integer - * @since 3.2 - */ - public $requireReset = null; - - /** - * User parameters - * - * @var Registry - * @since 1.7.0 - */ - protected $_params = null; - - /** - * Authorised access groups - * - * @var array - * @since 1.7.0 - */ - protected $_authGroups = null; - - /** - * Authorised access levels - * - * @var array - * @since 1.7.0 - */ - protected $_authLevels = null; - - /** - * Authorised access actions - * - * @var array - * @since 1.7.0 - */ - protected $_authActions = null; - - /** - * Error message - * - * @var string - * @since 1.7.0 - */ - protected $_errorMsg = null; - - /** - * @var array User instances container. - * @since 1.7.3 - */ - protected static $instances = array(); - /** * Constructor activating the default information of the language * * @param integer $identifier The primary key of the user to load (optional). * - * @since 1.7.0 + * @throws \Exception + * @since 1.1.0 */ public function __construct($identifier = 0) { - // Create the user parameters object - $this->_params = new Registry; - // Load the user if it exists if (!empty($identifier)) { - $this->load($identifier); + $data = $this->load($identifier); + // not a guest + $data->guest = 0; } else { - // Initialise - $this->id = 0; - $this->sendEmail = 0; - $this->aid = 0; - $this->guest = 1; + // Initialise guest + $data = (object) ['id' => 0, 'sendEmail' => 0, 'aid' => 0, 'guest' => 1]; } - } - - /** - * Returns the global User object, only creating it if it doesn't already exist. - * - * @param integer $identifier The primary key of the user to load (optional). - * - * @return User The User object. - * - * @since 1.7.0 - * @deprecated 5.0 Load the user service from the dependency injection container or via $app->getIdentity() - */ - public static function getInstance($identifier = 0) - { - @trigger_error( - sprintf( - '%1$s() is deprecated. Load the user from the dependency injection container or via %2$s::getApplication()->getIdentity().', - __METHOD__, - __CLASS__ - ), - E_USER_DEPRECATED - ); - - // Find the user id - if (!is_numeric($identifier)) - { - return Factory::getContainer()->get(UserFactoryInterface::class)->loadUserByUsername($identifier); - } - else - { - $id = $identifier; - } - - // If the $id is zero, just return an empty User. - // Note: don't cache this user because it'll have a new ID on save! - if ($id === 0) - { - return Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById($id); - } - - // Check if the user ID is already cached. - if (empty(self::$instances[$id])) - { - self::$instances[$id] = Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById($id); - } - - return self::$instances[$id]; - } - - /** - * Method to get a parameter value - * - * @param string $key Parameter key - * @param mixed $default Parameter default value - * - * @return mixed The value or the default if it did not exist - * - * @since 1.7.0 - */ - public function getParam($key, $default = null) - { - return $this->_params->get($key, $default); - } - - /** - * Method to set a parameter - * - * @param string $key Parameter key - * @param mixed $value Parameter value - * - * @return mixed Set parameter value - * - * @since 1.7.0 - */ - public function setParam($key, $value) - { - return $this->_params->set($key, $value); - } - - /** - * Method to set a default parameter if it does not exist - * - * @param string $key Parameter key - * @param mixed $value Parameter value - * - * @return mixed Set parameter value - * - * @since 1.7.0 - */ - public function defParam($key, $value) - { - return $this->_params->def($key, $value); - } - - /** - * Method to check User object authorisation against an access control - * object and optionally an access extension object - * - * @param string $action The name of the action to check for permission. - * @param string $assetname The name of the asset on which to perform the action. - * - * @return boolean True if authorised - * - * @since 1.7.0 - */ - public function authorise($action, $assetname = null) - { - // Make sure we only check for core.admin once during the run. - if ($this->isRoot === null) - { - $this->isRoot = false; - - // Check for the configuration file failsafe. - $rootUser = Factory::getApplication()->get('root_user'); - - // The root_user variable can be a numeric user ID or a username. - if (is_numeric($rootUser) && $this->id > 0 && $this->id == $rootUser) - { - $this->isRoot = true; - } - elseif ($this->username && $this->username == $rootUser) - { - $this->isRoot = true; - } - elseif ($this->id > 0) - { - // Get all groups against which the user is mapped. - $identities = $this->getAuthorisedGroups(); - array_unshift($identities, $this->id * -1); - - if (Access::getAssetRules(1)->allow('core.admin', $identities)) - { - $this->isRoot = true; - - return true; - } - } - } - - return $this->isRoot ? true : (bool) Access::check($this->id, $action, $assetname); - } - - /** - * Method to return a list of all categories that a user has permission for a given action - * - * @param string $component The component from which to retrieve the categories - * @param string $action The name of the section within the component from which to retrieve the actions. - * - * @return array List of categories that this group can do this action to (empty array if none). Categories must be published. - * - * @since 1.7.0 - */ - public function getAuthorisedCategories($component, $action) - { - // Brute force method: get all published category rows for the component and check each one - // @todo: Modify the way permissions are stored in the db to allow for faster implementation and better scaling - $db = Factory::getDbo(); - - $subQuery = $db->getQuery(true) - ->select($db->quoteName(['id', 'asset_id'])) - ->from($db->quoteName('#__categories')) - ->where( - [ - $db->quoteName('extension') . ' = :component', - $db->quoteName('published') . ' = 1', - ] - ); - - $query = $db->getQuery(true) - ->select($db->quoteName(['c.id', 'a.name'])) - ->from('(' . $subQuery . ') AS ' . $db->quoteName('c')) - ->join('INNER', $db->quoteName('#__assets', 'a'), $db->quoteName('c.asset_id') . ' = ' . $db->quoteName('a.id')) - ->bind(':component', $component); - $db->setQuery($query); - $allCategories = $db->loadObjectList('id'); - $allowedCategories = array(); - - foreach ($allCategories as $category) - { - if ($this->authorise($action, $category->name)) - { - $allowedCategories[] = (int) $category->id; - } - } - - return $allowedCategories; - } - - /** - * Gets an array of the authorised access levels for the user - * - * @return array - * - * @since 1.7.0 - */ - public function getAuthorisedViewLevels() - { - if ($this->_authLevels === null) - { - $this->_authLevels = array(); - } - - if (empty($this->_authLevels)) - { - $this->_authLevels = Access::getAuthorisedViewLevels($this->id); - } - - return $this->_authLevels; - } - - /** - * Gets an array of the authorised user groups - * - * @return array - * - * @since 1.7.0 - */ - public function getAuthorisedGroups() - { - if ($this->_authGroups === null) - { - $this->_authGroups = array(); - } - - if (empty($this->_authGroups)) - { - $this->_authGroups = Access::getGroupsByUser($this->id); - } - - return $this->_authGroups; - } - - /** - * Clears the access rights cache of this user - * - * @return void - * - * @since 3.4.0 - */ - public function clearAccessRights() - { - $this->_authLevels = null; - $this->_authGroups = null; - $this->isRoot = null; - Access::clearStatics(); - } - - /** - * Pass through method to the table for setting the last visit date - * - * @param integer $timestamp The timestamp, defaults to 'now'. - * - * @return boolean True on success. - * - * @since 1.7.0 - */ - public function setLastVisit($timestamp = null) - { - // Create the user table object - /** @var \Joomla\CMS\Table\User $table */ - $table = $this->getTable(); - $table->load($this->id); - - return $table->setLastVisit($timestamp); - } - - /** - * Method to get the user timezone. - * - * If the user didn't set a timezone, it will return the server timezone - * - * @return \DateTimeZone - * - * @since 3.7.0 - */ - public function getTimezone() - { - $timezone = $this->getParam('timezone', Factory::getApplication()->get('offset', 'GMT')); - - return new \DateTimeZone($timezone); - } - - /** - * Method to get the user parameters - * - * @param object $params The user parameters object - * - * @return void - * - * @since 1.7.0 - */ - public function setParameters($params) - { - $this->_params = $params; - } - - /** - * Method to get the user table object - * - * This function uses a static variable to store the table name of the user table to - * instantiate. You can call this function statically to set the table name if - * needed. - * - * @param string $type The user table name to be used - * @param string $prefix The user table prefix to be used - * - * @return Table The user table object - * - * @note At 4.0 this method will no longer be static - * @since 1.7.0 - */ - public static function getTable($type = null, $prefix = 'JTable') - { - static $tabletype; - - // Set the default tabletype; - if (!isset($tabletype)) - { - $tabletype['name'] = 'user'; - $tabletype['prefix'] = 'JTable'; - } - - // Set a custom table type is defined - if (isset($type)) - { - $tabletype['name'] = $type; - $tabletype['prefix'] = $prefix; - } - - // Create the user table object - return Table::getInstance($tabletype['name'], $tabletype['prefix']); - } - - /** - * Method to bind an associative array of data to a user object - * - * @param array &$array The associative array to bind to the object - * - * @return boolean True on success - * - * @since 1.7.0 - */ - public function bind(&$array) - { - // Let's check to see if the user is new or not - if (empty($this->id)) - { - // Check the password and create the crypted password - if (empty($array['password'])) - { - $array['password'] = UserHelper::genRandomPassword(32); - $array['password2'] = $array['password']; - } - - // Not all controllers check the password, although they should. - // Hence this code is required: - if (isset($array['password2']) && $array['password'] != $array['password2']) - { - Factory::getApplication()->enqueueMessage(Text::_('JLIB_USER_ERROR_PASSWORD_NOT_MATCH'), 'error'); - - return false; - } - - $this->password_clear = ArrayHelper::getValue($array, 'password', '', 'string'); - - $array['password'] = UserHelper::hashPassword($array['password']); - - // Set the registration timestamp - $this->set('registerDate', Factory::getDate()->toSql()); - } - else - { - // Updating an existing user - if (!empty($array['password'])) - { - if ($array['password'] != $array['password2']) - { - $this->setError(Text::_('JLIB_USER_ERROR_PASSWORD_NOT_MATCH')); - - return false; - } - - $this->password_clear = ArrayHelper::getValue($array, 'password', '', 'string'); - - // Check if the user is reusing the current password if required to reset their password - if ($this->requireReset == 1 && UserHelper::verifyPassword($this->password_clear, $this->password)) - { - $this->setError(Text::_('JLIB_USER_ERROR_CANNOT_REUSE_PASSWORD')); - - return false; - } - - $array['password'] = UserHelper::hashPassword($array['password']); - - // Reset the change password flag - $array['requireReset'] = 0; - } - else - { - $array['password'] = $this->password; - } - - // Prevent updating internal fields - unset($array['registerDate']); - unset($array['lastvisitDate']); - unset($array['lastResetTime']); - unset($array['resetCount']); - } - - if (\array_key_exists('params', $array)) - { - $this->_params->loadArray($array['params']); - - if (\is_array($array['params'])) - { - $params = (string) $this->_params; - } - else - { - $params = $array['params']; - } - - $this->params = $params; - } - - // Bind the array - if (!$this->setProperties($array)) - { - $this->setError(Text::_('JLIB_USER_ERROR_BIND_ARRAY')); - - return false; - } - - // Make sure its an integer - $this->id = (int) $this->id; - - return true; - } - - /** - * Method to save the User object to the database - * - * @param boolean $updateOnly Save the object only if not a new user - * Currently only used in the user reset password method. - * - * @return boolean True on success - * - * @since 1.7.0 - * @throws \RuntimeException - */ - public function save($updateOnly = false) - { - // Create the user table object - $table = $this->getTable(); - $this->params = (string) $this->_params; - $table->bind($this->getProperties()); - - // Allow an exception to be thrown. - try - { - // Check and store the object. - if (!$table->check()) - { - $this->setError($table->getError()); - - return false; - } - - // If user is made a Super Admin group and user is NOT a Super Admin - - // @todo ACL - this needs to be acl checked - - $my = Factory::getUser(); - - // Are we creating a new user - $isNew = empty($this->id); - - // If we aren't allowed to create new users return - if ($isNew && $updateOnly) - { - return true; - } - - // Get the old user - $oldUser = new User($this->id); - - // Access Checks - - // The only mandatory check is that only Super Admins can operate on other Super Admin accounts. - // To add additional business rules, use a user plugin and throw an Exception with onUserBeforeSave. - - // Check if I am a Super Admin - $iAmSuperAdmin = $my->authorise('core.admin'); - - $iAmRehashingSuperadmin = false; - - if (($my->id == 0 && !$isNew) && $this->id == $oldUser->id && $oldUser->authorise('core.admin') && $oldUser->password != $this->password) - { - $iAmRehashingSuperadmin = true; - } - - // Check if we are using a CLI application - $isCli = false; - - if (Factory::getApplication()->isCli()) - { - $isCli = true; - } - - // We are only worried about edits to this account if I am not a Super Admin. - if ($iAmSuperAdmin != true && $iAmRehashingSuperadmin != true && $isCli != true) - { - // I am not a Super Admin, and this one is, so fail. - if (!$isNew && Access::check($this->id, 'core.admin')) - { - throw new \RuntimeException('User not Super Administrator'); - } - - if ($this->groups != null) - { - // I am not a Super Admin and I'm trying to make one. - foreach ($this->groups as $groupId) - { - if (Access::checkGroup($groupId, 'core.admin')) - { - throw new \RuntimeException('User not Super Administrator'); - } - } - } - } - - // Fire the onUserBeforeSave event. - PluginHelper::importPlugin('user'); - - $result = Factory::getApplication()->triggerEvent('onUserBeforeSave', array($oldUser->getProperties(), $isNew, $this->getProperties())); - - if (\in_array(false, $result, true)) - { - // Plugin will have to raise its own error or throw an exception. - return false; - } - - // Store the user data in the database - $result = $table->store(); - - // Set the id for the User object in case we created a new user. - if (empty($this->id)) - { - $this->id = $table->get('id'); - } - - if ($my->id == $table->id) - { - $registry = new Registry($table->params); - $my->setParameters($registry); - } - - // Fire the onUserAfterSave event - Factory::getApplication()->triggerEvent('onUserAfterSave', array($this->getProperties(), $isNew, $result, $this->getError())); - } - catch (\Exception $e) - { - $this->setError($e->getMessage()); - - return false; - } - - return $result; - } - - /** - * Method to delete the User object from the database - * - * @return boolean True on success - * - * @since 1.7.0 - */ - public function delete() - { - PluginHelper::importPlugin('user'); - - // Trigger the onUserBeforeDelete event - Factory::getApplication()->triggerEvent('onUserBeforeDelete', array($this->getProperties())); - - // Create the user table object - $table = $this->getTable(); - - if (!$result = $table->delete($this->id)) - { - $this->setError($table->getError()); - } - - // Trigger the onUserAfterDelete event - Factory::getApplication()->triggerEvent('onUserAfterDelete', array($this->getProperties(), $result, $this->getError())); - - return $result; + // set the data + parent::__construct($data); } /** * Method to load a User object by user id number * - * @param mixed $id The user id of the user to load + * @param int $id The user id of the user to load * - * @return boolean True on success + * @return Object on success * - * @since 1.7.0 + * @throws \Exception + * @since 1.0.0 */ - public function load($id) + protected function load( int $id): object { - // Create the user table object - $table = $this->getTable(); + // Get the database + $db = Factory::getContainer()->get(DatabaseInterface::class); - // Load the UserModel object based on the user id or throw a warning. - if (!$table->load($id)) - { - // Reset to guest user - $this->guest = 1; - - Log::add(Text::sprintf('JLIB_USER_ERROR_UNABLE_TO_LOAD_USER', $id), Log::WARNING, 'jerror'); - - return false; - } - - /* - * Set the user parameters using the default XML file. We might want to - * extend this in the future to allow for the ability to have custom - * user parameters, but for right now we'll leave it how it is. - */ - - if ($table->params) - { - $this->_params->loadString($table->params); - } - - // Assuming all is well at this point let's bind the data - $this->setProperties($table->getProperties()); - - // The user is no longer a guest - if ($this->id != 0) - { - $this->guest = 0; - } - else - { - $this->guest = 1; - } - - return true; - } - - /** - * Method to allow serialize the object with minimal properties. - * - * @return array The names of the properties to include in serialization. - * - * @since 3.6.0 - */ - public function __sleep() - { - return array('id'); - } - - /** - * Method to recover the full object on unserialize. - * - * @return void - * - * @since 3.6.0 - */ - public function __wakeup() - { // Initialise some variables - $this->_params = new Registry; + $query = $db->getQuery(true) + ->select('*') + ->from($db->quoteName('#__users')) + ->where($db->quoteName('id') . ' = :id') + ->bind(':id', $id) + ->setLimit(1); + $db->setQuery($query); - // Load the user if it exists - if (!empty($this->id) && $this->load($this->id)) - { - // Push user into cached instances. - self::$instances[$this->id] = $this; - } - else - { - // Initialise - $this->id = 0; - $this->sendEmail = 0; - $this->aid = 0; - $this->guest = 1; - } + return $db->loadObject(); } } diff --git a/week-03/project/libraries/src/User/UserFactory.php b/week-03/project/libraries/src/User/UserFactory.php index fd5cb27..63043e8 100644 --- a/week-03/project/libraries/src/User/UserFactory.php +++ b/week-03/project/libraries/src/User/UserFactory.php @@ -1,21 +1,31 @@ + * @created 9th April 2022 + * @author Llewellyn van der Merwe + * @git WEBD-325-45 * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\User; - -\defined('_JEXEC') or die; +namespace Octoleo\CMS\User; +use Joomla\Authentication\AuthenticationStrategyInterface; use Joomla\Database\DatabaseInterface; +use Joomla\Authentication\Password\BCryptHandler; +use Joomla\Filter\InputFilter as InputFilterAlias; +use Joomla\String\StringHelper; +use Octoleo\CMS\Application\AdminApplication; +use Octoleo\CMS\Date\Date; +use Octoleo\CMS\Factory; +use Octoleo\CMS\Filter\InputFilter; +use Octoleo\CMS\Session\MetadataManager; /** * Default factory for creating User objects * - * @since 4.0.0 + * @since 1.0.0 + * source: https://github.com/joomla/joomla-cms/blob/4.2-dev/libraries/src/User/UserFactory.php */ class UserFactory implements UserFactoryInterface { @@ -26,14 +36,47 @@ class UserFactory implements UserFactoryInterface */ private $db; + /** + * @var AuthenticationStrategyInterface + */ + private $authentication; + + /** + * @var InputFilter + */ + private $inputFilter; + + /** + * @var string[] + */ + private $userFilter = [ + 'name' => 'STRING', + 'username' => 'USERNAME', + 'email' => 'STRING', + 'password' => 'RAW', + 'password2' => 'RAW' + ]; + /** + * @var BCryptHandler + */ + private $secure; + /** * UserFactory constructor. * - * @param DatabaseInterface $db The database + * @param DatabaseInterface|null $db The database + * @param AuthenticationStrategyInterface|null $authentication + * + * @throws \Exception */ - public function __construct(DatabaseInterface $db) + public function __construct( + DatabaseInterface $db = null, + AuthenticationStrategyInterface $authentication = null, + BCryptHandler $secure = null) { - $this->db = $db; + $this->db = ($db) ?: Factory::getApplication()->get(DatabaseInterface::class); + $this->authentication = ($authentication) ?: Factory::getApplication()->get(AuthenticationStrategyInterface::class); + $this->secure = ($secure) ?: new BCryptHandler(); } /** @@ -43,7 +86,8 @@ class UserFactory implements UserFactoryInterface * * @return User * - * @since 4.0.0 + * @throws \Exception + * @since 1.0.0 */ public function loadUserById(int $id): User { @@ -57,7 +101,8 @@ class UserFactory implements UserFactoryInterface * * @return User * - * @since 4.0.0 + * @throws \Exception + * @since 1.0.0 */ public function loadUserByUsername(string $username): User { @@ -72,4 +117,365 @@ class UserFactory implements UserFactoryInterface return $this->loadUserById((int) $this->db->loadResult()); } + + /** + * Check if user is active + * + * @return bool + * @throws \Exception + */ + public function active(): bool + { + /** @var \Octoleo\CMS\Application\AdminApplication $application */ + $application = Factory::getApplication(); + + $session = $application->getSession(); + + // Grab the current session ID + $sessionId = $session->getId(); + + /** @var \Octoleo\CMS\Session\MetadataManager $manager */ + $manager = Factory::getContainer()->get(MetadataManager::class); + + $active = $manager->getSessionRecord($sessionId); + + // if no active session is found... + if (!$active) + { + return false; + } + + // if user above 0 the active + if ($active->guest == 0 && $active->userid > 0) + { + return true; + } + + // Purge the session + $query = $this->db->getQuery(true) + ->delete($this->db->quoteName('#__session')) + ->where($this->db->quoteName('session_id') . ' = :sessionid') + ->bind(':sessionid', $sessionId); + try + { + $this->db->setQuery($query)->execute(); + } + catch (\RuntimeException $e) + { + // The old session is already invalidated, don't let this block logging in + } + + // destroy session + $session->destroy(); + + // very basic for now.... + return false; + } + + /** + * Check if a user exist based on give key value pair + * + * @param string $value + * @param string $key + * + * @return false|mixed on success return user ID + */ + public function exist(string $value, string $key = 'username') + { + try + { + $id = $this->db->setQuery( + $this->db->getQuery(true) + ->select($this->db->quoteName('id')) + ->from($this->db->quoteName('#__users')) + ->where($this->db->quoteName($key) . ' = ?') + ->bind(1, $value) + )->loadResult(); + } + catch (\RuntimeException $exception) + { + return false; + } + + if ($id > 0) + { + return $id; + } + return false; + } + + /** + * Attempt to authenticate the username and password pair. + * + * @return string|boolean A string containing a username if authentication is successful, false otherwise. + * + * @since 1.1.0 + */ + public function authenticate() + { + return $this->authentication->authenticate(); + } + + /** + * Attempt to login user + * + * @return boolean true on success + * + * @throws \Exception + * @since 1.0.0 + */ + public function login(): bool + { + /** @var \Octoleo\CMS\Application\AdminApplication $application */ + $application = Factory::getApplication(); + + if (($username = $this->authenticate()) !== false) + { + $user = $this->loadUserByUsername($username); + + // If loadUserByUsername returned an error, then pass it back. + if ($user instanceof \Exception) + { + $application->enqueueMessage('Login failure', 'Error'); + + return false; + } + + // If loadUserByUsername returned an error, then pass it back. + if ($user->get('block', true)) + { + $application->enqueueMessage('Login failure, user is blocked.', 'Warning'); + + return false; + } + + return $this->setUserSession($application, $user->toArray()); + } + // set authentication failure message + $application->enqueueMessage('Login failure, please try again.', 'Warning'); + + return false; + } + + /** + * Logout user + * + * @return bool + * @throws \Exception + */ + public function logout(): bool + { + /** @var \Octoleo\CMS\Application\AdminApplication $application */ + $application = Factory::getApplication(); + + $session = $application->getSession(); + + // Grab the current session ID + $sessionId = $session->getId(); + + // Purge the session + $query = $this->db->getQuery(true) + ->delete($this->db->quoteName('#__session')) + ->where($this->db->quoteName('session_id') . ' = :sessionid') + ->bind(':sessionid', $sessionId); + try + { + $this->db->setQuery($query)->execute(); + } + catch (\RuntimeException $e) + { + // The old session is already invalidated, don't let this block logging in + } + + // destroy session + $session->destroy(); + + // very basic for now.... + return true; + } + + /** + * Attempt to great user + * + * @param string|null $name + * @param string|null $username + * @param string|null $email + * @param string|null $password + * @param string|null $password2 + * + * @return boolean true on success + * + * @throws \Exception + * @since 1.0.0 + */ + public function create( + string $name = null, + string $username = null, + string $email = null, + string $password = null, + string $password2 = null): bool + { + /** @var \Octoleo\CMS\Application\AdminApplication $application */ + $application = Factory::getApplication(); + + /** @var \Joomla\Input\Input $input */ + $input = $application->getInput(); + + $user = []; + $user['name'] = ($name) ?: $input->getString('name', ''); + $user['username'] = ($username) ?: $input->getString('username', ''); + $user['email'] = ($email) ?: $input->getString('email', ''); + $user['password'] = ($password) ?: $input->getString('password', ''); + $user['password2'] = ($password2) ?: $input->getString('password2', ''); + + // check if username exist + if (!empty($user['username']) && $this->exist($user['username'])) + { + $application->enqueueMessage('Username already exist, try another username.', 'Warning'); + + return false; + } + // check if email exist + if (!empty($user['email']) && $this->exist($user['email'], 'email')) + { + $application->enqueueMessage('Email already exist, try another email.', 'Warning'); + + return false; + } + + // load our filter + $this->inputFilter = InputFilter::getInstance( + [], + [], + InputFilterAlias::ONLY_BLOCK_DEFINED_TAGS, + InputFilterAlias::ONLY_BLOCK_DEFINED_ATTRIBUTES + ); + + // check that we have all the values set + $valid = true; + foreach ($user as $key => $detail) + { + // check if its empty + if (empty($detail)) + { + $valid = false; + $application->enqueueMessage($key . ' is required', 'error'); + } + // check if its valid + if (!$this->valid($key, $detail)) + { + $valid = false; + $application->enqueueMessage($key . ' is not valid', 'error'); + } + } + + // check passwords TODO: check that we have a valid email + if (isset($user['password2']) && $user['password'] != $user['password2']) + { + $valid = false; + $application->enqueueMessage('Passwords do not match', 'error'); + } + unset ($user['password2']); + + // continue only if valid + if ($valid) + { + // hash the password + $user['password'] = $this->secure->hashPassword($user['password']); + + // set the registration date + $user['registerDate'] = (new Date())->toSql(); + + // set other defaults for now + $user['sendEmail'] = 1; + $user['block'] = 0; + $user['params'] = ''; + + $insert = (object) $user; + + try + { + // Insert the user + $result = $this->db->insertObject('#__users', $insert, 'id'); + } + catch (\RuntimeException $exception) + { + throw new \RuntimeException($exception->getMessage(), 404); + + return false; + } + + // only set session if success + if ($result) + { + $user['id'] = $this->db->insertid(); + return $this->setUserSession($application, $user); + } + } + return false; + } + + /** + * Attempt validate user input (BASIC) + * + * @param string $key + * @param string $detail + * + * @return bool + */ + private function valid(string $key, string $detail): bool + { + if (isset($this->userFilter[$key])) + { + $valid = $this->inputFilter->clean($detail, $this->userFilter[$key]); + + if (StringHelper::strcmp($valid, $detail) == 0) + { + return true; + } + } + return false; + } + + /** + * @param AdminApplication $application + * @param array $user + * + * @return bool + * @throws \Exception + */ + private function setUserSession(AdminApplication $application, array $user): bool + { + $session = $application->getSession(); + + // Grab the current session ID + $oldSessionId = $session->getId(); + + // Fork the session + $session->fork(); + + // Register the needed session variables + $session->set('user', $user); + + // Purge the old session + $query = $this->db->getQuery(true) + ->delete($this->db->quoteName('#__session')) + ->where($this->db->quoteName('session_id') . ' = :sessionid') + ->bind(':sessionid', $oldSessionId); + try + { + $this->db->setQuery($query)->execute(); + } + catch (\RuntimeException $e) + { + // The old session is already invalidated, don't let this block logging in + } + + /** @var \Octoleo\CMS\Session\MetadataManager $manager */ + $manager = Factory::getContainer()->get(MetadataManager::class); + + $manager->createOrUpdateRecord($session, $this->loadUserById($user['id'])); + + return true; + } } diff --git a/week-03/project/libraries/src/User/UserFactoryInterface.php b/week-03/project/libraries/src/User/UserFactoryInterface.php index a9a1816..3e20246 100644 --- a/week-03/project/libraries/src/User/UserFactoryInterface.php +++ b/week-03/project/libraries/src/User/UserFactoryInterface.php @@ -6,14 +6,12 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\CMS\User; - -\defined('_JEXEC') or die; +namespace Octoleo\CMS\User; /** * Interface defining a factory which can create User objects * - * @since 4.0.0 + * @since 1.0.0 */ interface UserFactoryInterface { @@ -24,7 +22,7 @@ interface UserFactoryInterface * * @return User * - * @since 4.0.0 + * @since 1.0.0 */ public function loadUserById(int $id): User; @@ -35,7 +33,16 @@ interface UserFactoryInterface * * @return User * - * @since 4.0.0 + * @since 1.0.0 */ public function loadUserByUsername(string $username): User; + + /** + * Attempt to authenticate the username and password pair. + * + * @return string|boolean A string containing a username if authentication is successful, false otherwise. + * + * @since 1.1.0 + */ + public function authenticate(); } diff --git a/week-03/project/libraries/src/View/Admin/DashboardHtmlView.php b/week-03/project/libraries/src/View/Admin/DashboardHtmlView.php index a04088a..89ddb30 100644 --- a/week-03/project/libraries/src/View/Admin/DashboardHtmlView.php +++ b/week-03/project/libraries/src/View/Admin/DashboardHtmlView.php @@ -1,67 +1,49 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\View\Package; +namespace Octoleo\CMS\View\Admin; -use Joomla\FrameworkWebsite\Helper; -use Joomla\FrameworkWebsite\Model\PackageModel; -use Joomla\FrameworkWebsite\Model\ReleaseModel; +use Octoleo\CMS\Model\DashboardModel; use Joomla\Renderer\RendererInterface; use Joomla\View\HtmlView; /** - * Package HTML view class for the application + * Dashboard HTML view class for the application */ -class PackageHtmlView extends HtmlView +class DashboardHtmlView extends HtmlView { /** - * Helper object + * The id of item/user/menu * - * @var Helper + * @var int */ - private $helper; + private $id; /** - * The active package + * The page model object. * - * @var string + * @var DashboardModel */ - private $package = ''; - - /** - * The package model object. - * - * @var PackageModel - */ - private $packageModel; - - /** - * The release model object. - * - * @var ReleaseModel - */ - private $releaseModel; + private $dashboardModel; /** * Instantiate the view. * - * @param PackageModel $packageModel The package model object. - * @param ReleaseModel $releaseModel The release model object. - * @param Helper $helper Helper object. + * @param DashboardModel $dashboardModel The page model object. * @param RendererInterface $renderer The renderer object. */ - public function __construct(PackageModel $packageModel, ReleaseModel $releaseModel, Helper $helper, RendererInterface $renderer) + public function __construct(DashboardModel $dashboardModel, RendererInterface $renderer) { parent::__construct($renderer); - $this->helper = $helper; - $this->packageModel = $packageModel; - $this->releaseModel = $releaseModel; + $this->dashboardModel = $dashboardModel; } /** @@ -71,27 +53,31 @@ class PackageHtmlView extends HtmlView */ public function render() { - $package = $this->packageModel->getPackage($this->package); - - $this->setData( - [ - 'releases' => $this->releaseModel->getPackageHistory($package), - 'package' => $package, - ] - ); - + $this->setData(['page' => $this->id]); return parent::render(); } /** - * Set the active package + * Set the active dashboard * - * @param string $package The active package name + * @param string $name The active page name * * @return void */ - public function setPackage(string $package): void + public function setActiveDashboard(string $name): void { - $this->package = $package; + $this->setLayout($this->dashboardModel->getDashboard($name)); + } + + /** + * Set the active page details + * + * @param int $id The selected item/user/menu + * + * @return void + */ + public function setActiveId(int $id): void + { + $this->id = $id; } } diff --git a/week-03/project/libraries/src/View/Page/PageHtmlView.php b/week-03/project/libraries/src/View/Page/PageHtmlView.php index a04088a..78dd647 100644 --- a/week-03/project/libraries/src/View/Page/PageHtmlView.php +++ b/week-03/project/libraries/src/View/Page/PageHtmlView.php @@ -1,67 +1,56 @@ + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -namespace Joomla\FrameworkWebsite\View\Package; +namespace Octoleo\CMS\View\Page; -use Joomla\FrameworkWebsite\Helper; -use Joomla\FrameworkWebsite\Model\PackageModel; -use Joomla\FrameworkWebsite\Model\ReleaseModel; +use Octoleo\CMS\Model\PageModel; use Joomla\Renderer\RendererInterface; use Joomla\View\HtmlView; /** - * Package HTML view class for the application + * Page HTML view class for the application */ -class PackageHtmlView extends HtmlView +class PageHtmlView extends HtmlView { /** - * Helper object - * - * @var Helper - */ - private $helper; - - /** - * The active package + * The active page * * @var string */ - private $package = ''; + private $page = ''; /** - * The package model object. + * The active page details * - * @var PackageModel + * @var string */ - private $packageModel; + private $details; /** - * The release model object. + * The page model object. * - * @var ReleaseModel + * @var PageModel */ - private $releaseModel; + private $pageModel; /** * Instantiate the view. * - * @param PackageModel $packageModel The package model object. - * @param ReleaseModel $releaseModel The release model object. - * @param Helper $helper Helper object. + * @param PageModel $pageModel The page model object. * @param RendererInterface $renderer The renderer object. */ - public function __construct(PackageModel $packageModel, ReleaseModel $releaseModel, Helper $helper, RendererInterface $renderer) + public function __construct(PageModel $pageModel, RendererInterface $renderer) { parent::__construct($renderer); - $this->helper = $helper; - $this->packageModel = $packageModel; - $this->releaseModel = $releaseModel; + $this->pageModel = $pageModel; } /** @@ -71,12 +60,10 @@ class PackageHtmlView extends HtmlView */ public function render() { - $package = $this->packageModel->getPackage($this->package); - $this->setData( [ - 'releases' => $this->releaseModel->getPackageHistory($package), - 'package' => $package, + 'page' => $this->pageModel->getPage($this->page), + 'details' => $this->pageModel->getDetails($this->details) ] ); @@ -84,14 +71,26 @@ class PackageHtmlView extends HtmlView } /** - * Set the active package + * Set the active page * - * @param string $package The active package name + * @param string $page The active page name * * @return void */ - public function setPackage(string $package): void + public function setPage(string $page): void { - $this->package = $package; + $this->page = $page; + } + + /** + * Set the active page details + * + * @param string $page The active page name + * + * @return void + */ + public function setDetails(string $details): void + { + $this->details = $details; } } diff --git a/week-03/project/logs/framework.log b/week-03/project/logs/framework.log new file mode 100644 index 0000000..e69de29 diff --git a/week-03/project/logs/index.html b/week-03/project/logs/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/week-03/project/logs/index.html @@ -0,0 +1 @@ + diff --git a/week-03/project/octoconfig.php.example b/week-03/project/octoconfig.php.example new file mode 100644 index 0000000..3f519f4 --- /dev/null +++ b/week-03/project/octoconfig.php.example @@ -0,0 +1,95 @@ + + * @git WEBD-325-45 + * @license GNU General Public License version 2 or later; see LICENSE.txt + * ------------------------------------------------------------------------- + * THIS SHOULD ONLY BE USED AS A LAST RESORT WHEN THE WEB INSTALLER FAILS + * + * If you are installing Octoleo! manually ie not using the web browser installer + * then rename this file to octoconfig.php eg + * + * UNIX -> mv octoconfig.php.example octoconfig.php + * Windows -> rename octoconfig.php.example octoconfig.php + * + * Now edit this file and configure the parameters for your site and + * database. + * + * Finally move this file to the root folder of your Octoleo installation eg + * + * UNIX -> mv octoconfig.php ../ + * Windows -> copy octoconfig.php ../ + * + * SOURCE: https://github.com/joomla/joomla-cms/blob/4.1-dev/installation/configuration.php-dist + * + */ +class LConfig +{ + public $sitename = 'Octoleo!'; // Name of Octoleo site + + /* Database Settings */ + public $dbtype = 'mysqli'; // Normally mysqli + public $host = 'localhost'; // This is normally set to localhost + public $user = ''; // Database username + public $password = ''; // Database password + public $db = ''; // Database name + public $dbprefix = 'llewellyn_'; // LEAVE THIS UNCHANGED FOR NOW + public $dbencryption = 0; + public $dbsslverifyservercert = false; + public $dbsslkey = ''; + public $dbsslcert = ''; + public $dbsslca = ''; + public $dbsslcipher = ''; + + /* Server Settings */ + public $secret = 'EiT9pmiqMycmQ6xx'; // Use something very secure. For example on linux the following command `cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-16} | head -n 1` + public $helpurl = 'https://help.octoleo.org/proxy?keyref=Help{major}{minor}:{keyref}&lang={langcode}'; + public $tmp_path = '/tmp'; // This path needs to be writable by Octoleo! + + /* Locale Settings */ + public $offset = 'UTC'; + + /* Session settings */ + public $lifetime = 15; // Session time + public $session_handler = 'database'; + public $session_filesystem_path = ''; + public $session_memcached_server_host = 'localhost'; + public $session_memcached_server_port = 11211; + public $session_metadata = true; + public $session_redis_persist = 1; + public $session_redis_server_auth = ''; + public $session_redis_server_db = 0; + public $session_redis_server_host = 'localhost'; + public $session_redis_server_port = 6379; + + /* Mail Settings */ + public $mailonline = true; + public $mailer = 'mail'; + public $mailfrom = ''; + public $fromname = ''; + public $massmailoff = false; + public $replyto = ''; + public $replytoname = ''; + public $sendmail = '/usr/sbin/sendmail'; + public $smtpauth = false; + public $smtpuser = ''; + public $smtppass = ''; + public $smtphost = 'localhost'; + public $smtpsecure = 'none'; + public $smtpport = 25; + + /* Meta Settings */ + public $MetaDesc = 'Octoleo! - the dynamic portal engine and content management system'; + public $MetaAuthor = true; + public $MetaVersion = false; + public $MetaRights = ''; + public $robots = ''; + public $sitename_pagetitles = 0; + + /* Cookie Settings */ + public $cookie_domain = ''; + public $cookie_path = ''; +} diff --git a/week-03/project/templates/admin/dashboard.twig b/week-03/project/templates/admin/dashboard.twig new file mode 100644 index 0000000..e88e51c --- /dev/null +++ b/week-03/project/templates/admin/dashboard.twig @@ -0,0 +1,20 @@ +{% extends "index.twig" %} + +{% block title %}Octoleo Dashboard{% endblock %} + +{% block content %} +
+

Octoleo CMS Dashboard

+
+
+ +
+
+ +
+
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/edit.twig b/week-03/project/templates/admin/edit.twig new file mode 100644 index 0000000..50a748d --- /dev/null +++ b/week-03/project/templates/admin/edit.twig @@ -0,0 +1,37 @@ +{% extends "index.twig" %} + +{% block title %}Edit{% endblock %} + +{% block content %} +
+
+
+ Legend +
+ +
+
+ +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/exception.twig b/week-03/project/templates/admin/exception.twig new file mode 100644 index 0000000..b5488d1 --- /dev/null +++ b/week-03/project/templates/admin/exception.twig @@ -0,0 +1,29 @@ +{% extends 'index.twig' %} + +{% block bodyNavigation %}{% endblock %} + +{% block title %}Octoleo Error{% endblock %} + +{% block content %} +
+ {% if exception.code in [404, 405] %} +

We Couldn't Find It

+

Sorry, we couldn't find the page matching your request. Try using the navigation to find what you were looking for?

+ {% else %} +

Ouch, That's an Error

+

Well this is embarrassing, seems there was an error processing this request. Perhaps try again? Or file an issue so we can address it.

+ {% endif %} + + {% if appDebug %} +

{{ exception.code|default(0) }} {{ exception|get_class }}

+

{{ exception.message|strip_root_path }}

+ + {% if exception.previous %} + {% set _previous = exception.previous %} +

Previous Exception

+

{{ exception.code|default(0) }} {{ exception|get_class }}

+

{{ exception.message|strip_root_path }}

+ {% endif %} + {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/footer.twig b/week-03/project/templates/admin/footer.twig new file mode 100644 index 0000000..3da6797 --- /dev/null +++ b/week-03/project/templates/admin/footer.twig @@ -0,0 +1,9 @@ +{% macro load_footer() %} +
+
+
+ Copyright © Generic Company. All Rights Reserved. | Octoleo CMS +
+
+
+{% endmacro %} \ No newline at end of file diff --git a/week-03/project/templates/admin/header.twig b/week-03/project/templates/admin/header.twig new file mode 100644 index 0000000..6761f39 --- /dev/null +++ b/week-03/project/templates/admin/header.twig @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + {% block title %}Octoleo! Framework, a framework for developing PHP applications{% endblock %} + + + + + + + + + + + + + + {% block metadata %}{% endblock %} + + + + + + + {% block headCSS %}{% endblock %} + {% block headJavaScript %}{% endblock %} + +{% block body %}{% endblock %} + \ No newline at end of file diff --git a/week-03/project/templates/admin/index.html b/week-03/project/templates/admin/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/week-03/project/templates/admin/index.html @@ -0,0 +1 @@ + diff --git a/week-03/project/templates/admin/index.twig b/week-03/project/templates/admin/index.twig new file mode 100644 index 0000000..e43c158 --- /dev/null +++ b/week-03/project/templates/admin/index.twig @@ -0,0 +1,13 @@ +{% extends "header.twig" %} + +{% block body %} + +{% block bodyNavigation %}{% import 'nav.twig' as macros %}{{ macros.load_admin_navbar() }}{% endblock %} +
+ {% block content %}{% endblock %} +
+{% block footerContent %}{% import 'footer.twig' as macros %}{{ macros.load_footer() }}{% endblock %} +{% block bodyJavaScript %}{% endblock %} +{{ url }} + +{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/items.twig b/week-03/project/templates/admin/items.twig new file mode 100644 index 0000000..3a35f38 --- /dev/null +++ b/week-03/project/templates/admin/items.twig @@ -0,0 +1,52 @@ +{% extends "index.twig" %} + +{% block title %}Items{% endblock %} + +{% block content %} +
+

Items

+ Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table HeadingTable HeadingTable Heading
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
+
+ +{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/login.twig b/week-03/project/templates/admin/login.twig new file mode 100644 index 0000000..ef797cc --- /dev/null +++ b/week-03/project/templates/admin/login.twig @@ -0,0 +1,18 @@ +{% extends "index.twig" %} + +{% block bodyNavigation %}{% endblock %} + +{% block content %} +
+
+

Login Here

+
+ + + + Create Account +
+
+
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/menus.twig b/week-03/project/templates/admin/menus.twig new file mode 100644 index 0000000..360699a --- /dev/null +++ b/week-03/project/templates/admin/menus.twig @@ -0,0 +1,50 @@ +{% extends "index.twig" %} + +{% block content %} +
+

Menus

+ Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table HeadingTable HeadingTable Heading
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
+
+ +{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/nav.twig b/week-03/project/templates/admin/nav.twig new file mode 100644 index 0000000..c5f4609 --- /dev/null +++ b/week-03/project/templates/admin/nav.twig @@ -0,0 +1,19 @@ +{% macro load_admin_navbar() %} + +{% endmacro %} + \ No newline at end of file diff --git a/week-03/project/templates/admin/signup.twig b/week-03/project/templates/admin/signup.twig new file mode 100644 index 0000000..11cff72 --- /dev/null +++ b/week-03/project/templates/admin/signup.twig @@ -0,0 +1,21 @@ +{% extends "index.twig" %} + +{% block bodyNavigation %}{% endblock %} + +{% block content %} +
+
+

Create Account

+
+ + + + + + + Login +
+
+
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/admin/users.twig b/week-03/project/templates/admin/users.twig new file mode 100644 index 0000000..770f5d5 --- /dev/null +++ b/week-03/project/templates/admin/users.twig @@ -0,0 +1,32 @@ +{% extends "index.twig" %} + +{% block title %}Users{% endblock %} + +{% block content %} +
+

Users

+ Create + + + + + + + + + + + + + + + + + + + + +
Table HeadingTable HeadingTable Heading
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
Table DataLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Edit
+
+ +{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/index.html b/week-03/project/templates/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/week-03/project/templates/index.html @@ -0,0 +1 @@ + diff --git a/week-03/project/templates/site/exception.twig b/week-03/project/templates/site/exception.twig new file mode 100644 index 0000000..fc9de64 --- /dev/null +++ b/week-03/project/templates/site/exception.twig @@ -0,0 +1,27 @@ +{% extends 'index.twig' %} + +{% block title %}Octoleo Error{% endblock %} + +{% block content %} +
+ {% if exception.code in [404, 405] %} +

We Couldn't Find It

+

Sorry, we couldn't find the page matching your request. Try using the navigation to find what you were looking for?

+ {% else %} +

Ouch, That's an Error

+

Well this is embarrassing, seems there was an error processing this request. Perhaps try again? Or file an issue so we can address it.

+ {% endif %} + + {% if appDebug %} +

{{ exception.code|default(0) }} {{ exception|get_class }}

+

{{ exception.message|strip_root_path }}

+ + {% if exception.previous %} + {% set _previous = exception.previous %} +

Previous Exception

+

{{ exception.code|default(0) }} {{ exception|get_class }}

+

{{ exception.message|strip_root_path }}

+ {% endif %} + {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/site/footer.twig b/week-03/project/templates/site/footer.twig new file mode 100644 index 0000000..3da6797 --- /dev/null +++ b/week-03/project/templates/site/footer.twig @@ -0,0 +1,9 @@ +{% macro load_footer() %} +
+
+
+ Copyright © Generic Company. All Rights Reserved. | Octoleo CMS +
+
+
+{% endmacro %} \ No newline at end of file diff --git a/week-03/project/templates/site/header.twig b/week-03/project/templates/site/header.twig new file mode 100644 index 0000000..6761f39 --- /dev/null +++ b/week-03/project/templates/site/header.twig @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + {% block title %}Octoleo! Framework, a framework for developing PHP applications{% endblock %} + + + + + + + + + + + + + + {% block metadata %}{% endblock %} + + + + + + + {% block headCSS %}{% endblock %} + {% block headJavaScript %}{% endblock %} + +{% block body %}{% endblock %} + \ No newline at end of file diff --git a/week-03/project/templates/site/homepage.twig b/week-03/project/templates/site/homepage.twig new file mode 100644 index 0000000..153f13c --- /dev/null +++ b/week-03/project/templates/site/homepage.twig @@ -0,0 +1,10 @@ +{% extends "index.twig" %} + +{% block content %} +
+
+

Welcome

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+
+
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/site/index.html b/week-03/project/templates/site/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/week-03/project/templates/site/index.html @@ -0,0 +1 @@ + diff --git a/week-03/project/templates/site/index.twig b/week-03/project/templates/site/index.twig new file mode 100644 index 0000000..207d374 --- /dev/null +++ b/week-03/project/templates/site/index.twig @@ -0,0 +1,12 @@ +{% extends "header.twig" %} + +{% block body %} + +{% block bodyNavigation %}{% import 'nav.twig' as macros %}{{ macros.load_site_navbar() }}{% endblock %} +
+ {% block content %}{% endblock %} +
+{% block footerContent %}{% import 'footer.twig' as macros %}{{ macros.load_footer() }}{% endblock %} +{% block bodyJavaScript %}{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/site/nav.twig b/week-03/project/templates/site/nav.twig new file mode 100644 index 0000000..38bee15 --- /dev/null +++ b/week-03/project/templates/site/nav.twig @@ -0,0 +1,28 @@ +{% macro load_site_navbar() %} + +{% endmacro %} + \ No newline at end of file diff --git a/week-03/project/templates/site/page.twig b/week-03/project/templates/site/page.twig new file mode 100644 index 0000000..92f6759 --- /dev/null +++ b/week-03/project/templates/site/page.twig @@ -0,0 +1,14 @@ +{% extends "index.twig" %} + +{% block content %} +
+
+

{{ page }}

+ {% if details == '' %} +

YOU ARE IN PAGES

+ {% else %} +

You are into {{ details }}

+ {% endif %} +
+
+{% endblock %} \ No newline at end of file diff --git a/week-03/project/templates/system/build_incomplete.html b/week-03/project/templates/system/build_incomplete.html new file mode 100644 index 0000000..48bd040 --- /dev/null +++ b/week-03/project/templates/system/build_incomplete.html @@ -0,0 +1,34 @@ + + + + + + + Octoleo: Environment Setup Incomplete + + + +
+
+
+

Environment Setup Incomplete

+

It looks like you are trying to run Octoleo! from our git repository. To do so requires you complete a couple of extra steps first.

+

+ 0. Make sure you have composer installed on your system. +
+ 1. In your terminal go to the root folder of your Octoleo website where you will find the composer.json file. +
+ 2. Run the following command composer install to install all PHP packages. +

+
+ +
+
+ + + diff --git a/week-03/project/templates/system/incompatible.html b/week-03/project/templates/system/incompatible.html new file mode 100644 index 0000000..fd33990 --- /dev/null +++ b/week-03/project/templates/system/incompatible.html @@ -0,0 +1,27 @@ + + + + + + + Octoleo: unsupported PHP version + + + +
+
+
+

Sorry, your PHP version is not supported

+

Your host needs to use PHP version {{phpversion}} or newer to run this version of Octoleo!

+
+ +
+
+ + + \ No newline at end of file diff --git a/week-03/project/templates/system/index.html b/week-03/project/templates/system/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/week-03/project/templates/system/index.html @@ -0,0 +1 @@ + diff --git a/week-03/project/templates/system/install_notice.html b/week-03/project/templates/system/install_notice.html new file mode 100644 index 0000000..d016616 --- /dev/null +++ b/week-03/project/templates/system/install_notice.html @@ -0,0 +1,36 @@ + + + + + + + Octoleo: Installation Instructions + + + +
+
+
+

Installation Instructions

+

You need to manually do the following few tasks.

+

+ 1. Import the SQL tables into your database found in /sql/install.sql +
+ 2. Copy the /octoconfig.php.example file to /octoconfig.php +
+ 3 .Update the /octoconfig.php to reflect your CMS details +
+ 4. Remove the installation folder from you root directory +

+
+ +
+
+ + + \ No newline at end of file diff --git a/week-03/project/tmp/index.html b/week-03/project/tmp/index.html new file mode 100644 index 0000000..2efb97f --- /dev/null +++ b/week-03/project/tmp/index.html @@ -0,0 +1 @@ +