├── .gitignore ├── _config.yml ├── src └── Magma │ ├── Router │ ├── Exception │ │ └── .gitkeep │ ├── RouterInterface.php │ ├── RouterFactory.php │ └── Router.php │ ├── Session │ ├── Exception │ │ └── .gitkeep │ ├── Storage │ │ ├── ArraySessionStorage.php │ │ ├── NativeSessionStorage.php │ │ ├── SessionStorageInterface.php │ │ └── AbstractSessionStorage.php │ ├── SessionManager.php │ ├── SessionFactory.php │ ├── SessionInterface.php │ └── Session.php │ ├── LiquidOrm │ ├── DataMapper │ │ ├── Exception │ │ │ └── .gitkeep │ │ ├── DataMapperInterface.php │ │ ├── DataMapperFactory.php │ │ ├── DataMapperEnvironmentConfiguration.php │ │ └── DataMapper.php │ ├── DataRepository │ │ ├── Exception │ │ │ └── .gitkeep │ │ ├── DataRepositoryFactory.php │ │ ├── DataRepositoryInterface.php │ │ └── DataRepository.php │ ├── EntityManager │ │ ├── Exception │ │ │ └── .gitkeep │ │ ├── EntityManagerInterface.php │ │ ├── EntityManager.php │ │ ├── EntityManagerFactory.php │ │ ├── CrudInterface.php │ │ └── Crud.php │ ├── QueryBuilder │ │ ├── Exception │ │ │ └── .gitkeep │ │ ├── QueryBuilderInterface.php │ │ ├── QueryBuilderFactory.php │ │ ├── AbstractQueryBuilder.php │ │ └── QueryBuilder.php │ └── LiquidOrmManager.php │ ├── Datatable │ ├── DatatableColumnInterface.php │ ├── AbstractDatatableColumn.php │ ├── DatatableInterface.php │ ├── AbstractDatatable.php │ └── Datatable.php │ ├── Application │ ├── Config.php │ └── Application.php │ ├── GlobalManager │ ├── Exception │ │ ├── GlobalManagerException.php │ │ └── GlobalManagerInvalidArgumentException.php │ ├── GlobalManagerInterface.php │ └── GlobalManager.php │ ├── Flash │ ├── FlashTypes.php │ ├── FlashInterface.php │ └── Flash.php │ ├── Twig │ └── TwigExtension.php │ ├── Abstracts │ └── AbstractBaseModel.php │ ├── DatabaseConnection │ ├── DatabaseConnectionInterface.php │ ├── Exception │ │ └── DatabaseConnectionException.php │ └── DatabaseConnection.php │ ├── Http │ ├── ResponseHandler.php │ └── RequestHandler.php │ ├── Base │ ├── Exception │ │ ├── BaseLengthException.php │ │ ├── BaseNoValueException.php │ │ ├── BaseException.php │ │ ├── BaseRuntimeException.php │ │ ├── BaseOverFlowException.php │ │ ├── BaseOutOfRangeException.php │ │ ├── BaseInvalidArgumentException.php │ │ ├── BaseLogicException.php │ │ ├── BaseOutOfBoundsException.php │ │ ├── BaseUnderFlowException.php │ │ ├── BaseBadFunctionCallException.php │ │ ├── BaseBadMethodCallException.php │ │ └── BaseUnexpectedValueException.php │ ├── BaseEntity.php │ ├── BaseModel.php │ ├── BaseView.php │ └── BaseController.php │ ├── Traits │ └── SystemTrait.php │ ├── Utility │ ├── Token.php │ ├── Paginator.php │ ├── Sortable.php │ └── Sanitizer.php │ ├── Yaml │ └── YamlConfig.php │ └── ErrorHandling │ └── ErrorHandling.php ├── Config ├── app.yaml ├── controller.yaml ├── routes.yaml ├── database.yaml ├── twig.yaml └── session.yaml ├── App ├── Templates │ └── client │ │ └── home │ │ └── index.html.twig ├── Controller │ ├── SecurityController.php │ ├── Admin │ │ └── UserController.php │ └── HomeController.php ├── Entity │ └── UserEntity.php ├── Model │ └── UserModel.php └── DataColumns │ └── UserColumns.php ├── README.md ├── dataFlow ├── MVC_process_GET.pdf ├── Presentation (2).pdf └── CopyOfMVCProcessPOST.pdf ├── index.php ├── composer.json ├── .htaccess └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-tactile -------------------------------------------------------------------------------- /src/Magma/Router/Exception/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Magma/Session/Exception/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataMapper/Exception/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataRepository/Exception/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/EntityManager/Exception/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/QueryBuilder/Exception/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Config/app.yaml: -------------------------------------------------------------------------------- 1 | pdo_driver: mysql 2 | seccret_key: 8541wedfef511 -------------------------------------------------------------------------------- /App/Templates/client/home/index.html.twig: -------------------------------------------------------------------------------- 1 | {{ table }} 2 | {{ pagination }} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MagmaCore 2 | # Project Abondon Please see MagmaSkeleton 3 | -------------------------------------------------------------------------------- /dataFlow/MVC_process_GET.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCodingWorkshop/MagmaCore/HEAD/dataFlow/MVC_process_GET.pdf -------------------------------------------------------------------------------- /dataFlow/Presentation (2).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCodingWorkshop/MagmaCore/HEAD/dataFlow/Presentation (2).pdf -------------------------------------------------------------------------------- /dataFlow/CopyOfMVCProcessPOST.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCodingWorkshop/MagmaCore/HEAD/dataFlow/CopyOfMVCProcessPOST.pdf -------------------------------------------------------------------------------- /src/Magma/Session/Storage/ArraySessionStorage.php: -------------------------------------------------------------------------------- 1 | message = $message; 23 | $this->code = $code; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/Magma/Base/Exception/BaseInvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | createFromGlobals(); 23 | if ($create) { 24 | return $create; 25 | } 26 | } 27 | } 28 | return false; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/Magma/Base/Exception/BaseLogicException.php: -------------------------------------------------------------------------------- 1 | crud = $crud; 25 | } 26 | 27 | /** 28 | * @inheritDoc 29 | */ 30 | public function getCrud() : Object 31 | { 32 | return $this->crud; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/Magma/Session/SessionManager.php: -------------------------------------------------------------------------------- 1 | create('magmacore', \Magma\Session\Storage\NativeSessionStorage::class, YamlConfig::file('session')); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/Magma/Base/Exception/BaseOutOfBoundsException.php: -------------------------------------------------------------------------------- 1 | routeParams['action']; 23 | } 24 | 25 | protected function editAction() 26 | { 27 | $user = new UserModel(); 28 | echo $this->routeParams['namespace'] . '/' . $this->routeParams['controller'] . '/' . $this->routeParams['id'] . '/' . $this->routeParams['action']; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | run() 22 | ->setSession() 23 | ->setRouteHandler(); 24 | -------------------------------------------------------------------------------- /src/Magma/Flash/Flash.php: -------------------------------------------------------------------------------- 1 | has(self::FLASH_KEY)) { 20 | $session->set(self::FLASH_KEY, []); 21 | } 22 | $session->setArray(self::FLASH_KEY, ['message' => $message, 'type' => $type]); 23 | } 24 | 25 | public static function get() 26 | { 27 | $session = GlobalManager::get('global_session'); 28 | $session->flush(self::FLASH_KEY); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/Magma/Base/Exception/BaseUnexpectedValueException.php: -------------------------------------------------------------------------------- 1 | token = $tokenValue; 26 | } else { 27 | $this->token = bin2hex(random_bytes($bytes)); 28 | } 29 | } 30 | 31 | /** 32 | * Get the token value 33 | * 34 | * @return string the token value 35 | * @throws Exception 36 | */ 37 | public function getValue() : string 38 | { 39 | return $this->token; 40 | } 41 | 42 | /** 43 | * Get the hashed token value 44 | * 45 | * @return string The hashed value 46 | * @throws Exception 47 | */ 48 | public function getHash() : string 49 | { 50 | return hash_hmac('sha256', $this->value, YamlConfig::file('app')['secret_key']); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /App/Controller/HomeController.php: -------------------------------------------------------------------------------- 1 | getRepo()->findWithSearchAndPaging((new RequestHandler())->handler(), $args); 28 | 29 | $tableData = (new Datatable())->create(UserColumns::class, $repository, $args)->setAttr(['table_id' => 'sexytable', 'table_class' => ['youtube-datatable']])->table(); 30 | 31 | $this->render('client/home/index.html.twig', [ 32 | 'table' => $tableData, 33 | 'pagination' => (new Datatable())->create(UserColumns::class, $repository, $args)->pagination() 34 | ]); 35 | } 36 | 37 | protected function before() 38 | {} 39 | 40 | protected function after() 41 | {} 42 | 43 | 44 | } -------------------------------------------------------------------------------- /src/Magma/Base/BaseEntity.php: -------------------------------------------------------------------------------- 1 | cleanData($dirtyData) as $key => $value) { 28 | $this->$key = $value; 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * Return the sanitize post data back to the main constructor 35 | * 36 | * @param array $dirtyData 37 | * @return array 38 | * @throws BaseInvalidArgumentException 39 | */ 40 | private function cleanData(array $dirtyData) : array 41 | { 42 | $cleanData = Sanitizer::clean($dirtyData); 43 | if ($cleanData) { 44 | return $cleanData; 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/QueryBuilder/QueryBuilderInterface.php: -------------------------------------------------------------------------------- 1 | repository = $factory->create(DataRepository::class); 38 | } 39 | 40 | /** 41 | * Get the data repository object based on the context model 42 | * which the repository is being executed from. 43 | * 44 | * @return DataRepository 45 | */ 46 | public function getRepo() : DataRepository 47 | { 48 | return $this->repository; 49 | } 50 | 51 | 52 | } -------------------------------------------------------------------------------- /src/Magma/Yaml/YamlConfig.php: -------------------------------------------------------------------------------- 1 | isFileExists($file); 39 | $parts = parse_url($file); 40 | $path = $parts['path']; 41 | if (strpos($path, $yamlFile) !== false) { 42 | return Yaml::parseFile($file); 43 | } 44 | } 45 | } 46 | 47 | /** 48 | * Load a yaml configuration into the yaml parser 49 | * 50 | * @param string $yamlFile 51 | * @return void 52 | */ 53 | public static function file(string $yamlFile) : array 54 | { 55 | return (array)(new YamlConfig)->getYaml($yamlFile); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /Config/twig.yaml: -------------------------------------------------------------------------------- 1 | # When set to true, the generated templates have a __toString() method that you can use to display the generated nodes (default to false). 2 | debug: false 3 | # The charset used by the templates. 4 | charset: utf-8 5 | # An absolute path where to store the compiled templates, or false to disable caching (which is the default). 6 | cache: '' 7 | # When developing with Twig, it’s useful to recompile the template whenever the source code changes. If you don’t provide a value for the auto_reload option, it will be determined automatically based on the debug value. 8 | auto_reload: true 9 | # If set to false, Twig will silently ignore invalid variables (variables and or attributes/methods that do not exist) and replace them with a null value. When set to true, Twig throws an exception instead (default to false). 10 | strict_variables: false 11 | # Sets the default auto-escaping strategy (name, html, js, css, url, html_attr, or a PHP callback that takes the template “filename” and returns the escaping strategy to use – the callback cannot be a function name to avoid collision with built-in escaping strategies); set it to false to disable auto-escaping. The name escaping strategy determines the escaping strategy to use for a template based on the template filename extension (this strategy does not incur any overhead at runtime as auto-escaping is done at compilation time.) 12 | autoescape: false 13 | # A flag that indicates which optimizations to apply (default to -1 – all optimizations are enabled; set it to 0 to disable). 14 | optimizations : -1 15 | # set a default extension to use with our view template files. This is not part of the twig configurations 16 | template_ext: 17 | - .html 18 | - .twig 19 | - .html.twig -------------------------------------------------------------------------------- /Config/session.yaml: -------------------------------------------------------------------------------- 1 | session_name: 'magmaCore__' #The unqiue session name 2 | lifetime: '0' #The lifetime of the cookie in seconds. 3 | path: '/' #The path where the information is stored. 4 | domain: '' #The domain the cookie belongs to. 5 | secure: false #The cookie should only be sent over secure connections 6 | httponly: true #The cookie can only be access through HTTP protocol. 7 | samesite: lax #Controls the cross-domain sending of the cookie. 8 | # - supports 'lax', 'strict', 'none', null 9 | 10 | #specifies the number of seconds after which data will be seen as 11 | #'garbage' and potentially cleaned up. 12 | gc_maxlifetime: '1800' 13 | #in conjunction with session.gc_divisor is used to manage probability 14 | #that the gc (garbage collection) routine is started. 15 | gc_probability: '1000' 16 | #coupled with session.gc_probability defines the probability that the gc (garbage collection) process is started on every session initialization. The probability is calculated by using gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that the GC process starts on each request. session.gc_divisor defaults to 100. 17 | gc_divisor: '100' 18 | #specifies whether the module will use cookies to store the session id on the client side. Defaults to 1 (enabled). 19 | use_cookies: '1' 20 | 21 | #driver: 22 | #file: 23 | #class: \Magma\Session\Storage\NativeSessionStorage 24 | #alias: native_storage 25 | #default: true 26 | #database: 27 | #class: \Magma\Session\Storage\PDOSessionStorage 28 | #alias: pdo_database 29 | #default: false 30 | #array: 31 | #class: \Magma\Session\Storage\ArraySessionStorage 32 | #alias: array_storage 33 | #default: false 34 | -------------------------------------------------------------------------------- /src/Magma/DatabaseConnection/DatabaseConnection.php: -------------------------------------------------------------------------------- 1 | credentials = $credentials; 32 | } 33 | 34 | /** 35 | * @inheritDoc 36 | * 37 | * @return PDO 38 | */ 39 | public function open() : PDO 40 | { 41 | try { 42 | $params = [ 43 | PDO::ATTR_EMULATE_PREPARES => false, 44 | PDO::ATTR_PERSISTENT => true, 45 | PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 46 | PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC 47 | ]; 48 | $this->dbh = new PDO( 49 | $this->credentials['dsn'], 50 | $this->credentials['username'], 51 | $this->credentials['password'], 52 | $params 53 | ); 54 | } catch(PDOException $expection) { 55 | throw new DatabaseConnectionException($expection->getMessage(), (int)$expection->getCode()); 56 | } 57 | 58 | return $this->dbh; 59 | } 60 | 61 | /** 62 | * @inheritDoc 63 | * 64 | * @return void 65 | */ 66 | public function close() : void 67 | { 68 | $this->dbh = null; 69 | } 70 | 71 | 72 | } -------------------------------------------------------------------------------- /src/Magma/GlobalManager/GlobalManager.php: -------------------------------------------------------------------------------- 1 | addExtension(new DebugExtension()); 39 | $twig->addExtension(new TwigExtension()); 40 | } 41 | return $twig->render($template, $context); 42 | } 43 | 44 | /** 45 | * echo the contents of a view template using Twig 46 | * 47 | * @param string $template The template file 48 | * @param array $context Associative array of data to display in the view (optional) 49 | * 50 | * @return string 51 | * @throws LoaderError 52 | * @throws RuntimeError 53 | * @throws SyntaxError 54 | * @throws Exception 55 | */ 56 | public function twigRender(string $template, array $context = []) 57 | { 58 | echo $this->getTemplate($template, $context); 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/EntityManager/EntityManagerFactory.php: -------------------------------------------------------------------------------- 1 | dataMapper = $dataMapper; 30 | $this->queryBuilder = $queryBuilder; 31 | } 32 | 33 | /** 34 | * Create the entityManager obejct and inject the dependency which is the crud object 35 | * 36 | * @param string $crudString 37 | * @param string $tableSchema 38 | * @param string $tableSchemaID 39 | * @param array $options 40 | * @return EntityManagerInterface 41 | * @throws BaseUnexpectedValueException 42 | */ 43 | public function create(string $crudString, string $tableSchema, string $tableSchemaID, array $options = []) : EntityManagerInterface 44 | { 45 | $crudObject = new $crudString($this->dataMapper, $this->queryBuilder, $tableSchema, $tableSchemaID, $options); 46 | if (!$crudObject instanceof CrudInterface) { 47 | throw new BaseUnexpectedValueException($crudString . ' is not a valid crud object.'); 48 | } 49 | return new EntityManager($crudObject); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/Magma/Utility/Paginator.php: -------------------------------------------------------------------------------- 1 | totalPages = ceil($totalRecords / $recordsPerPage); 32 | $data = [ 33 | 'options' => [ 34 | 'default' => 1, 35 | 'min_range' => 1, 36 | 'max_range' => $this->totalPages 37 | ] 38 | ]; 39 | $this->page = filter_var($page, FILTER_VALIDATE_INT, $data); 40 | // Calculate the starting record based on the page and number of records per page 41 | $this->offset = $recordsPerPage * ($this->page - 1); 42 | } 43 | 44 | /** 45 | * Get the starting record within the SQL Query 46 | * 47 | * @return int 48 | */ 49 | public function getOffset() : int 50 | { 51 | return (int)$this->offset; 52 | } 53 | 54 | /** 55 | * Gte the current page 56 | * 57 | * @return void 58 | */ 59 | public function getPage() : int 60 | { 61 | return (int)$this->page; 62 | } 63 | 64 | /** 65 | * Get the total number of pages 66 | * 67 | * @return int 68 | */ 69 | public function getTotalPages() : int 70 | { 71 | return (int)$this->totalPages; 72 | } 73 | 74 | 75 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataMapper/DataMapperInterface.php: -------------------------------------------------------------------------------- 1 | columns = $columns; 36 | } 37 | 38 | public function getColumn() : string 39 | { 40 | if (is_array($this->columns)) { 41 | $this->column = isset($_GET['column']) && in_array($_GET['column'], $this->columns) ? $_GET['column'] : $this->columns[0]; 42 | if ($this->column) { 43 | return $this->column; 44 | } 45 | } 46 | } 47 | 48 | public function getDirection() : string 49 | { 50 | $this->order = isset($_GET['order']) && strtolower($_GET['order']) == 'desc' ? 'DESC' : 'ASC'; 51 | if ($this->order) { 52 | return $this->order; 53 | } 54 | } 55 | 56 | public function sortDirection() : string 57 | { 58 | $this->direction = str_replace(array('ASC', 'DESC'), array('up', 'down'), $this->getDirection()); 59 | if ($this->direction) { 60 | return $this->direction; 61 | } 62 | } 63 | 64 | public function sortDescAsc() 65 | { 66 | if ($this->getDirection()) { 67 | return $this->getDirection() == 'ASC' ? 'desc' : 'asc'; 68 | } 69 | } 70 | 71 | public function getClass() : string 72 | { 73 | return $this->class; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataRepository/DataRepositoryFactory.php: -------------------------------------------------------------------------------- 1 | crudIdentifier = $crudIdentifier; 34 | $this->tableSchema = $tableSchema; 35 | $this->tableSchemaID = $tableSchemaID; 36 | } 37 | 38 | /** 39 | * Create the DataRepository Object 40 | * 41 | * @param string $dataRepositoryString 42 | * @return void 43 | * @throws BaseUnexpectedValueException 44 | */ 45 | public function create(string $dataRepositoryString) : DataRepositoryInterface 46 | { 47 | $entityManager = $this->initializeLiquidOrmManager(); 48 | $dataRepositoryObject = new $dataRepositoryString($entityManager); 49 | if (!$dataRepositoryObject instanceof DataRepositoryInterface) { 50 | throw new BaseUnexpectedValueException($dataRepositoryString . ' is not a valid repository object'); 51 | } 52 | return $dataRepositoryObject; 53 | } 54 | 55 | public function initializeLiquidOrmManager() 56 | { 57 | $environmentConfiguration = new DataMapperEnvironmentConfiguration(YamlConfig::file('database')); 58 | $ormManager = new LiquidOrmManager($environmentConfiguration, $this->tableSchema, $this->tableSchemaID); 59 | return $ormManager->initialize(); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/Magma/ErrorHandling/ErrorHandling.php: -------------------------------------------------------------------------------- 1 | getCode(); 37 | if ($code !=404) { 38 | $code = 500; 39 | } 40 | http_response_code($code); 41 | 42 | $error = true; 43 | if ($error) { 44 | //echo "
"; 45 | echo "

Fatal Error

"; 46 | echo "

Uncaught exception: " . get_class($exception) . "

"; 47 | echo "

Message: " . $exception->getMessage() . "

"; 48 | echo "

Stack trace: " . $exception->getTraceAsString() . "

"; 49 | echo "

Thrown in " . $exception->getFile() . " on line " . $exception->getLine() . "

"; 50 | //echo "
"; 51 | } else { 52 | $errorLog = LOG_DIR . "/" . date("Y-m-d H:is") . ".txt"; 53 | ini_set('error_log', $errorLog); 54 | $message = "Uncaught exception: " . get_class($exception); 55 | $message .= "with message " . $exception->getMessage(); 56 | $message .= "\nStack trace: " . $exception->getTraceAsString(); 57 | $message .= "\nThrown in " . $exception->getFile() . " on line " . $exception->getLine(); 58 | 59 | error_log($message); 60 | 61 | echo (new BaseView)->getTemplate("error/{$code}.html.twig", ["error_message" => $message]); 62 | } 63 | } 64 | 65 | 66 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataMapper/DataMapperFactory.php: -------------------------------------------------------------------------------- 1 | getDatabaseCredentials('mysql'); 25 | $databaseConnectionObject = new $databaseConnectionString($credentials); 26 | if (!$databaseConnectionObject instanceof DatabaseConnectionInterface) { 27 | throw new DataMapperException($databaseConnectionString . ' is not a valid database connection object'); 28 | } 29 | return new DataMapper($databaseConnectionObject); 30 | }*/ 31 | 32 | /** 33 | * Creates the data mapper object and inject the dependency for this object. We are also 34 | * creating the DatabaseConnection Object 35 | * $dataMapperEnvironmentConfiguration get instantiated in the DataRepositoryFactory 36 | * 37 | * @param string $databaseConnectionString 38 | * @param Object $dataMapperEnvironmentConfiguration 39 | * @return DataMapperInterface 40 | * @throws BaseUnexpectedValueException 41 | */ 42 | public function create(string $databaseConnectionString, Object $dataMapperEnvironmentConfiguration) : DataMapperInterface 43 | { 44 | // Create databaseConnection Object and pass the database credentials in 45 | $credentials = $dataMapperEnvironmentConfiguration->getDatabaseCredentials(YamlConfig::file('app')['pdo_driver']); 46 | $databaseConnectionObject = new $databaseConnectionString($credentials); 47 | if (!$databaseConnectionObject instanceof DatabaseConnectionInterface) { 48 | throw new BaseUnexpectedValueException($databaseConnectionString . ' is not a valid database connection object'); 49 | } 50 | return new DataMapper($databaseConnectionObject); 51 | } 52 | 53 | 54 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/QueryBuilder/AbstractQueryBuilder.php: -------------------------------------------------------------------------------- 1 | [], 19 | 'selectors' => [], 20 | 'replace' => false, 21 | 'distinct' => false, 22 | 'from' => [], 23 | 'where' => null, 24 | 'and' => [], 25 | 'or' => [], 26 | 'orderby' => [], 27 | 'fields' => [], 28 | 'primary_key' => '', 29 | 'table' => '', 30 | 'type' => '', 31 | 'raw' => '', 32 | 33 | 'table_join' => '', 34 | 'join_key' => '', 35 | 'join' => [] 36 | ]; 37 | 38 | /** @var array */ 39 | protected const QUERY_TYPES = ['insert', 'select', 'update', 'delete', 'raw', 'search', 'join']; 40 | 41 | /** 42 | * Main class constructor 43 | * 44 | * @return void 45 | */ 46 | public function __construct() 47 | {} 48 | 49 | protected function orderByQuery() 50 | { 51 | // Append the orderby statement if set 52 | if (isset($this->key["extras"]["orderby"]) && $this->key["extras"]["orderby"] != "") { 53 | $this->sqlQuery .= " ORDER BY " . $this->key["extras"]["orderby"] . " "; 54 | } 55 | } 56 | 57 | protected function queryOffset() 58 | { 59 | // Append the limit and offset statement for adding pagination to the query 60 | if (isset($this->key["params"]["limit"]) && $this->key["params"]["offset"] != -1) { 61 | $this->sqlQuery .= " LIMIT :offset, :limit"; 62 | } 63 | 64 | } 65 | 66 | protected function isQueryTypeValid(string $type) : bool 67 | { 68 | if (in_array($type, self::QUERY_TYPES)) { 69 | return true; 70 | } 71 | return false; 72 | } 73 | 74 | /** 75 | * Checks whether a key is set. returns true or false if not set 76 | * 77 | * @param string $key 78 | * @return bool 79 | */ 80 | protected function has(string $key): bool 81 | { 82 | return isset($this->key[$key]); 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/LiquidOrmManager.php: -------------------------------------------------------------------------------- 1 | environmentConfiguration = $environmentConfiguration; 40 | $this->tableSchema = $tableSchema; 41 | $this->tableSchemaID = $tableSchemaID; 42 | $this->options = $options; 43 | } 44 | 45 | /** 46 | * initialize method which glues all the components together and inject the necessary dependency within the 47 | * respective object 48 | * 49 | * @return Object 50 | */ 51 | public function initialize() : Object 52 | { 53 | $dataMapperFactory = new DataMapperFactory(); 54 | $dataMapper = $dataMapperFactory->create(DatabaseConnection::class, $this->environmentConfiguration); 55 | if ($dataMapper) { 56 | $queryBuilderFactory = new QueryBuilderFactory(); 57 | $queryBuilder = $queryBuilderFactory->create(QueryBuilder::class); 58 | if ($queryBuilder) { 59 | $entityManagerFactory = new EntityManagerFactory($dataMapper, $queryBuilder); 60 | return $entityManagerFactory->create(Crud::class, $this->tableSchema, $this->tableSchemaID, $this->options); 61 | } 62 | } 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/Magma/Utility/Sanitizer.php: -------------------------------------------------------------------------------- 1 | 0) { 27 | foreach ($dirtyData as $key => $value) { 28 | if (!isset($key)) { 29 | throw new BaseInvalidArgumentException('Invalid key'); 30 | } 31 | if (!is_array($value)) { 32 | $value = trim(stripslashes($value)); 33 | } 34 | 35 | switch ($value) { 36 | case is_int($value) : 37 | $input[$key] = isset($value) ? filter_var($value, FILTER_SANITIZE_NUMBER_INT) : ''; 38 | break; 39 | case is_string($value) : 40 | $input[$key] = isset($value) ? filter_var($value, FILTER_SANITIZE_STRING) : ''; 41 | break; 42 | case is_array($value) : 43 | if (count($value) > 0) { 44 | foreach ($value as $arrKey => $arrValue) { 45 | if (isset($arrKey) && $arrKey !='') { 46 | if (is_int($arrValue)) { 47 | $input[$arrKey] = isset($arrValue) ? filter_var($arrValue, FILTER_SANITIZE_NUMBER_INT) : ''; 48 | } else { 49 | $input[$arrKey] = isset($arrValue) ? filter_var($value, FILTER_SANITIZE_STRING) : ''; 50 | } 51 | } 52 | } 53 | } 54 | break; 55 | } 56 | } 57 | if (isset($input) && $input !='') { 58 | return $input; 59 | } 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /src/Magma/Router/RouterFactory.php: -------------------------------------------------------------------------------- 1 | routes.yaml has your defined routes and your passing the correct $_SERVER variable ie "QUERY_STRING".'); 33 | } 34 | $this->dispatcedUrl = $dispatcedUrl; 35 | $this->routes = $routes; 36 | } 37 | 38 | /** 39 | * Instantiate the router object and checks whether the object 40 | * implements the correct interface else throw an exception. 41 | * 42 | * @param string $routerString 43 | * @return self 44 | */ 45 | public function create(string $routerString) : self 46 | { 47 | $this->router = new $routerString(); 48 | if (!$this->router instanceof RouterInterface) { 49 | throw new BaseUnexpectedValueException($routerString . ' is not a valid Router object'); 50 | } 51 | return $this; 52 | 53 | } 54 | 55 | /** 56 | * Undocumented function 57 | * 58 | * @return void 59 | */ 60 | public function buildRoutes() 61 | { 62 | if (is_array($this->routes) && !empty($this->routes)) { 63 | $args = []; 64 | foreach ($this->routes as $key => $route) { 65 | if (isset($route['namespace']) && $route['namespace'] !='') { 66 | $args = ['namespace' => $route['namespace']]; 67 | } elseif(isset($route['controller']) && $route['controller'] !='') { 68 | $args = ['controller' => $route['controller'], 'action' => $route['action']]; 69 | } 70 | if (isset($key)) { 71 | $this->router->add($key, $args); 72 | } 73 | } 74 | $this->router->dispatch($this->dispatcedUrl); 75 | } 76 | return false; 77 | 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /src/Magma/Session/SessionInterface.php: -------------------------------------------------------------------------------- 1 | hasSession($key)) { 54 | return $_SESSION[$key]; 55 | } 56 | return $default; 57 | } 58 | 59 | /** 60 | * @inheritdoc 61 | * 62 | * @param string $key 63 | * @return void 64 | */ 65 | public function deleteSession(string $key) : void 66 | { 67 | if ($this->hasSession($key)) { 68 | unset($_SESSION[$key]); 69 | } 70 | } 71 | 72 | /** 73 | * @inheritdoc 74 | * 75 | * @return void 76 | */ 77 | public function invalidate() : void 78 | { 79 | $_SESSION = array(); 80 | if (ini_get('session.use_cookies')) { 81 | $params = session_get_cookie_params(); 82 | setCookie($this->getSessionName(), '', time() - $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']); 83 | } 84 | session_unset(); 85 | session_destroy(); 86 | } 87 | 88 | /** 89 | * @inheritdoc 90 | * 91 | * @param string $key 92 | * @param [type] $default 93 | * @return void 94 | */ 95 | public function flush(string $key, $default = null) 96 | { 97 | if ($this->hasSession($key)) { 98 | $value = $_SESSION[$key]; 99 | $this->deleteSession($key); 100 | return $value; 101 | } 102 | return $default; 103 | 104 | } 105 | 106 | /** 107 | * @inheritdoc 108 | * 109 | * @param string $key 110 | * @return boolean 111 | */ 112 | public function hasSession(string $key) : bool 113 | { 114 | return isset($_SESSION[$key]); 115 | } 116 | 117 | 118 | } -------------------------------------------------------------------------------- /App/DataColumns/UserColumns.php: -------------------------------------------------------------------------------- 1 | 'id', 17 | 'dt_row' => 'ID', 18 | 'class' => 'id-class', 19 | 'show_column' => true, 20 | 'sortable' => false, 21 | 'formatter' => '' 22 | ], 23 | [ 24 | 'db_row' => 'firstname', 25 | 'dt_row' => 'Firstname', 26 | 'class' => '', 27 | 'show_column' => true, 28 | 'sortable' => true, 29 | 'formatter' => '' 30 | ], 31 | [ 32 | 'db_row' => 'lastname', 33 | 'dt_row' => 'Lastname', 34 | 'class' => '', 35 | 'show_column' => true, 36 | 'sortable' => false, 37 | 'formatter' => '' 38 | ], 39 | [ 40 | 'db_row' => 'email', 41 | 'dt_row' => 'Email Address', 42 | 'class' => '', 43 | 'show_column' => true, 44 | 'sortable' => true, 45 | 'formatter' => '' 46 | ], 47 | [ 48 | 'db_row' => 'status', 49 | 'dt_row' => 'Status', 50 | 'class' => '', 51 | 'show_column' => true, 52 | 'sortable' => false, 53 | 'formatter' => '' 54 | ], 55 | [ 56 | 'db_row' => 'created_at', 57 | 'dt_row' => 'Published', 58 | 'class' => '', 59 | 'show_column' => true, 60 | 'sortable' => false, 61 | 'formatter' => '' 62 | ], 63 | [ 64 | 'db_row' => 'modified_at', 65 | 'dt_row' => 'Modified', 66 | 'class' => '', 67 | 'show_column' => true, 68 | 'sortable' => false, 69 | 'formatter' => '' 70 | ], 71 | [ 72 | 'db_row' => 'gravatar', 73 | 'dt_row' => 'Thumbnail', 74 | 'class' => '', 75 | 'show_column' => false, 76 | 'sortable' => false, 77 | 'formatter' => '' 78 | ], 79 | [ 80 | 'db_row' => 'ip', 81 | 'dt_row' => 'IP Address', 82 | 'class' => '', 83 | 'show_column' => false, 84 | 'sortable' => false, 85 | 'formatter' => '' 86 | ], 87 | [ 88 | 'db_row' => '', 89 | 'dt_row' => 'Action', 90 | 'class' => '', 91 | 'show_column' => true, 92 | 'sortable' => false, 93 | 'formatter' => '' 94 | ], 95 | 96 | ]; 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /src/Magma/Datatable/AbstractDatatable.php: -------------------------------------------------------------------------------- 1 | '', 15 | 'orderby' => '', 16 | 'table_class' => ['uk-table'], 17 | 'table_id' => 'datatable', 18 | 'show_table_thead' => true, 19 | 'show_table_tfoot' => false, 20 | 'before' => '
', 21 | 'after' => '
' 22 | ]; 23 | 24 | protected const COLUMNS_PARTS = [ 25 | 'db_row' => '', 26 | 'dt_row' => '', 27 | 'class' => '', 28 | 'show_column' => true, 29 | 'sortable' => false, 30 | 'formatter' => '' 31 | ]; 32 | 33 | protected array $attr = []; 34 | 35 | public function __construct() 36 | { 37 | $this->attr = self::TABLE_PROPERTIES; 38 | foreach ($this->attr as $key => $value) { 39 | if (!$this->validAttributes($key, $value)) { 40 | $this->validAttributes($key, $value); 41 | } 42 | } 43 | } 44 | 45 | public function setAttr($attributes = []) : self 46 | { 47 | if (is_array($attributes) && count($attributes) > 0) { 48 | $propKeys = array_keys(self::TABLE_PROPERTIES); 49 | foreach ($attributes as $key => $value) { 50 | if (!in_array($key, $propKeys)) { 51 | throw new BaseInvalidArgumentException('Invalid property key set.'); 52 | } 53 | $this->validAttributes($key, $value); 54 | $this->attr[$key] = $value; 55 | } 56 | } 57 | return $this; 58 | } 59 | 60 | protected function validAttributes(string $key, $value) : void 61 | { 62 | if (empty($key)) { 63 | throw new BaseInvalidArgumentException('Inavlid or empty attribute key. Ensure the key is present and of the correct data type ' . $value); 64 | } 65 | switch ($key) { 66 | case 'status' : 67 | case 'orderby' : 68 | case 'table_id' : 69 | case 'before' : 70 | case 'after' : 71 | if (!is_string($value)) { 72 | throw new BaseInvalidArgumentException('Invalid argument type ' . $value . ' should be a string'); 73 | } 74 | break; 75 | case 'show_table_thead' : 76 | case 'show_table_tfoot' : 77 | if (!is_bool($value)) { 78 | throw new BaseInvalidArgumentException('Invalid argument type ' . $value . ' should be a boolean'); 79 | } 80 | break; 81 | case 'table_class' : 82 | if (!is_array($value)) { 83 | throw new BaseInvalidArgumentException('Invalid argument type ' . $value . ' should be a array'); 84 | } 85 | break; 86 | } 87 | $this->attr[$key] = $value; 88 | } 89 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataMapper/DataMapperEnvironmentConfiguration.php: -------------------------------------------------------------------------------- 1 | credentials = $credentials; 27 | } 28 | 29 | /*private function __isCredentialsValid(string $driver) : void 30 | { 31 | if (empty($driver) && !is_string($driver)) { 32 | throw new DataMapperInvalidArgumentException('Invalid argument. This is either missing or off the invalid data type.'); 33 | } 34 | if (!is_array($this->credentials)) { 35 | throw new DataMapperInvalidArgumentException('Invalid credentials'); 36 | } 37 | if (!in_array($driver, array_keys($this->credentials[$driver]))) { 38 | throw new DataMapperInvalidArgumentException('Invalid or unsupport database driver.'); 39 | } 40 | }*/ 41 | 42 | /** 43 | * Checks credentials for validity 44 | * 45 | * @param string $driver 46 | * @return void 47 | */ 48 | private function isCredentialsValid(string $driver) : void 49 | { 50 | if (empty($driver) || !is_array($this->credentials)) { 51 | throw new BaseInvalidArgumentException('Core Error: You have either not specify the default database driver or the database.yaml is returning null or empty.'); 52 | } 53 | } 54 | 55 | 56 | /*public function __getDatabaseCredentials(string $driver) : array 57 | { 58 | $connectionArray = []; 59 | $this->isCredentialsValid($driver); 60 | foreach ($this->credentials as $credential) { 61 | if (array_key_exists($driver, $credential)) { 62 | $connectionArray = $credential[$driver]; 63 | } 64 | } 65 | return $connectionArray; 66 | }*/ 67 | /** 68 | * Get the user defined database connection array 69 | * 70 | * @param string $driver 71 | * @return array 72 | * @throws BaseInvalidArgumentException 73 | */ 74 | public function getDatabaseCredentials(string $driver) : array 75 | { 76 | $connectionArray = []; 77 | $this->isCredentialsValid($driver); 78 | foreach ($this->credentials as $credential) { 79 | if (!array_key_exists($driver, $credential)) { 80 | throw new BaseInvalidArgumentException('Core Error: Your selected database driver is not supported. Please see the database.yaml file for all support driver. Or specify a supported driver from your app.yaml configuration file'); 81 | } else { 82 | $connectionArray = $credential[$driver]; 83 | } 84 | } 85 | return $connectionArray; 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/Magma/Application/Application.php: -------------------------------------------------------------------------------- 1 | appRoot = $appRoot; 28 | } 29 | 30 | /** 31 | * Execute at application level 32 | * 33 | * @return self 34 | */ 35 | public function run() : self 36 | { 37 | $this->constants(); 38 | if (version_compare($phpVersion = PHP_VERSION, $coreVersion = Config::MAGMA_MIN_VERSION, '<')) { 39 | die(sprintf('You are runninig PHP %s, but the core framework requires at least PHP %s', $phpVersion, $coreVersion)); 40 | } 41 | $this->environment(); 42 | $this->errorHandler(); 43 | return $this; 44 | } 45 | 46 | /** 47 | * Define framework and application directory constants 48 | * 49 | * @return void 50 | */ 51 | private function constants() : void 52 | { 53 | defined('DS') or define('DS', '/'); 54 | defined('APP_ROOT') or define('APP_ROOT', $this->appRoot); 55 | defined('CONFIG_PATH') or define('CONFIG_PATH', APP_ROOT . DS . 'Config'); 56 | defined('TEMPLATE_PATH') or define('TEMPLATE_PATH', APP_ROOT . DS . 'App/'); 57 | defined('LOG_DIR') or define('LOG_DIR', APP_ROOT . DS . 'tmp/log'); 58 | 59 | } 60 | 61 | /** 62 | * Set default framework and application settings 63 | * 64 | * @return void 65 | */ 66 | private function environment() 67 | { 68 | ini_set('default_charset', 'UTF-8'); 69 | } 70 | 71 | /** 72 | * Convert PHP errors to exception and set a custom exception 73 | * handler. Which allows us to take control or error handling 74 | * so we can display errors in a customizable way 75 | * 76 | * @return void 77 | */ 78 | private function errorHandler() : void 79 | { 80 | error_reporting(E_ALL | E_STRICT); 81 | set_error_handler('Magma\ErrorHandling\ErrorHandling::errorHandler'); 82 | set_exception_handler('Magma\ErrorHandling\ErrorHandling::exceptionHandler'); 83 | } 84 | 85 | public function setSession() 86 | { 87 | SystemTrait::sessionInit(true); 88 | return $this; 89 | } 90 | 91 | /** 92 | * Undocumented function 93 | * 94 | * @param string $url 95 | * @param array $routes 96 | * @return self 97 | */ 98 | public function setRouteHandler(string $url = null, array $routes = []) : self 99 | { 100 | $url = ($url) ? $url : $_SERVER['QUERY_STRING']; 101 | $routes = ($routes) ? $routes : YamlConfig::file('routes'); 102 | 103 | $factory = new RouterFactory($url, $routes); 104 | $factory->create(\Magma\Router\Router::class)->buildRoutes(); 105 | return $this; 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | # Determine the RewriteBase automatically and set it as environment variable. 2 | # If you are using Apache aliases to do mass virtual hosting or installed the 3 | # project in a subdirectory, the base path will be prepended to allow proper 4 | # resolution of the index.php file and to redirect to the correct URI. It will 5 | # work in environments without path prefix as well, providing a safe, one-size 6 | # fits all solution. But as you do not need it in this case, you can comment 7 | # the following 2 lines to eliminate the overhead. 8 | 9 | # By default, Apache does not evaluate symbolic links if you did not enable this 10 | # feature in your server configuration. Uncomment the following line if you 11 | # install assets as symlinks or if you experience problems related to symlinks 12 | # when compiling LESS/Sass/CoffeScript assets. 13 | # Options FollowSymlinks 14 | 15 | # Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve 16 | # to the front controller "/index.php" but be rewritten to "/index.php/index". 17 | # Remove the question mark from the request but maintain the query string 18 | RewriteEngine On 19 | RewriteBase / 20 | 21 | ## Begin - X-Forwarded-Proto 22 | # In some hosted or load balanced environments, SSL negotiation happens upstream. 23 | # In order for Lava-Studio to recognize the connection as secure, you need to uncomment 24 | # the following lines. 25 | # 26 | # RewriteCond %{HTTP:X-Forwarded-Proto} https 27 | # RewriteRule .* - [E=HTTPS:on] 28 | # 29 | ## End - X-Forwarded-Proto 30 | 31 | ## Begin - Index 32 | # If the requested filename exists, simply serve it. 33 | # We only want to let Apache serve files and not directories. 34 | # Rewrite all other queries to the front controller. 35 | # If the requested path and file is not /index.php and the request 36 | # has not already been internally rewritten to the index.php script 37 | # RewriteCond %{REQUEST_URI} !^/index\.php 38 | RewriteCond %{REQUEST_FILENAME} !-f 39 | RewriteCond %{REQUEST_FILENAME} !-d 40 | RewriteCond %{REQUEST_FILENAME} !-l 41 | RewriteRule ^(.*)$ index.php?$1 [L,QSA] 42 | ## End - Index 43 | 44 | ## Begin - Security 45 | # Block all direct access for these folders 46 | RewriteRule ^(\.git|bin|tmp|storage|webserver-configs|tests)/(.*) error [F] 47 | # Block access to specific file types for these system folders 48 | RewriteRule ^(core|vendor)/(.*)\.(txt|xml|md|html|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F] 49 | # Block access to specific file types for these user folders 50 | RewriteRule ^(public)/(.*)\.(txt|md|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F] 51 | # Block all direct access to .md files: 52 | RewriteRule \.md$ error [F] 53 | # Block all direct access to files and folders beginning with a dot 54 | RewriteRule (^|/)\.(?!well-known) - [F] 55 | # Block access to specific files in the root folder 56 | RewriteRule ^(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$ error [F] 57 | ## End - Security 58 | 59 | 60 | 61 | # Begin - Prevent Browsing and Set Default Resources 62 | Options -Indexes 63 | DirectoryIndex index.php index.html index.htm 64 | # End - Prevent Browsing and Set Default Resources 65 | -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/EntityManager/CrudInterface.php: -------------------------------------------------------------------------------- 1 | options = $options; 26 | 27 | $this->iniSet(); 28 | // Destroy any existing sessions started with session.auto_start 29 | if ($this->isSessionStarted()) { 30 | session_unset(); 31 | session_destroy(); 32 | } 33 | $this->start(); 34 | } 35 | 36 | /** 37 | * Set the name of the session 38 | * 39 | * @param string $sessionName 40 | * @return void 41 | */ 42 | public function setSessionName(string $sessionName) : void 43 | { 44 | session_name($sessionName); 45 | } 46 | 47 | /** 48 | * Return the current session name 49 | * 50 | * @return string 51 | */ 52 | public function getSessionName() : string 53 | { 54 | return session_name(); 55 | } 56 | 57 | /** 58 | * Set the name of the session ID 59 | * 60 | * @param $sessionID 61 | * @return void 62 | */ 63 | public function setSessionID(string $sessionID) : void 64 | { 65 | session_id($sessionID); 66 | } 67 | 68 | /** 69 | * Return the current session ID 70 | * 71 | * @return string 72 | */ 73 | public function getSessionID() 74 | { 75 | return session_id(); 76 | } 77 | 78 | public function iniSet() 79 | { 80 | ini_set('session.gc_maxlifetime', $this->options['gc_maxlifetime']); 81 | ini_set('session.gc_divisor', $this->options['gc_divisor']); 82 | ini_set('session.gc_probability', $this->options['gc_probability']); 83 | ini_set('session.lifetime', $this->options['lifetime']); 84 | ini_set('session.use_cookies', $this->options['use_cookies']); 85 | } 86 | 87 | /** 88 | * Prevent session within the cli. Even though we can't run sessions within 89 | * the command line. also we checking we have a session id and its not empty 90 | * else return false 91 | * 92 | * @return bool 93 | */ 94 | public function isSessionStarted() 95 | { 96 | return php_sapi_name() !== 'cli' ? $this->getSessionID() !=='' : false; 97 | } 98 | 99 | /** 100 | * Start our session if we haven't already have a php session 101 | * 102 | * @return void 103 | */ 104 | public function startSession() 105 | { 106 | if (session_status() == PHP_SESSION_NONE) 107 | session_start(); 108 | } 109 | 110 | /** 111 | * Define our session_set_cookie_params method via the $this->options parameters which 112 | * will be define within our core config directory 113 | * 114 | * @return void 115 | */ 116 | public function start() : void 117 | { 118 | $this->setSessionName($this->options['session_name']); 119 | $domain = (isset($this->options['domain']) ? $this->options['domain'] : isset($_SERVER['SERVER_NAME'])); 120 | $secure = (isset($this->options['secure']) ? $this->options['secure'] : isset($_SERVER['HTTPS'])); 121 | 122 | session_set_cookie_params($this->options['lifetime'], $this->options['path'], $domain, $secure, $this->options['httponly']); 123 | 124 | $this->startSession(); 125 | } 126 | 127 | 128 | } -------------------------------------------------------------------------------- /src/Magma/Base/BaseController.php: -------------------------------------------------------------------------------- 1 | routeParams = $routeParams; 31 | $this->twig = new BaseView(); 32 | } 33 | 34 | /** 35 | * Renders a view template from sub controller classes 36 | * 37 | * @param string $template 38 | * @param array $context 39 | * @return Response 40 | */ 41 | public function render(string $template, array $context = []) 42 | { 43 | if ($this->twig === null) { 44 | throw new BaseLogicException('You cannot use the render method if the twig bundle is not available.'); 45 | } 46 | return $this->twig->twigRender($template, $context); 47 | } 48 | 49 | /** 50 | * Magic method called when a non-existent or inaccessible method is 51 | * called on an object of this class. Used to execute before and after 52 | * filter methods on action methods. Action methods need to be named 53 | * with an "Action" suffix, e.g. indexAction, showAction etc. 54 | * 55 | * @param $name 56 | * @param $arguments 57 | * @throws BaseBadMethodCallException 58 | * @return void 59 | */ 60 | public function __call($name, $arguments) : void 61 | { 62 | $method = $name . 'Action'; 63 | if (method_exists($this, $method)) { 64 | if ($this->before() !== false) { 65 | call_user_func_array([$this, $method], $arguments); 66 | $this->after(); 67 | } 68 | } else { 69 | throw new BaseBadMethodCallException('Method ' . $method . ' does not exist in ' . get_class($this)); 70 | } 71 | } 72 | 73 | /** 74 | * Before method which is called before a controller method 75 | * 76 | * @return void 77 | */ 78 | protected function before() 79 | {} 80 | 81 | /** 82 | * After method which is called after a controller method 83 | * 84 | * @return void 85 | */ 86 | protected function after() 87 | {} 88 | 89 | /** 90 | * Method for allowing child controller class to dependency inject other objects 91 | * @param array $args 92 | * @return Object 93 | * @throws BaseInvalidArgumentException 94 | * @throws ReflectionException 95 | */ 96 | public function create(array $args) 97 | { 98 | if (!is_array($args)) { 99 | throw new BaseInvalidArgumentException('Invalid argument'); 100 | } 101 | $args = func_get_args(); 102 | if ($args) { 103 | $output = ''; 104 | foreach ($args as $arg) { 105 | foreach ($arg as $key => $class) { 106 | if (strpos($class, $arg[$key]) !== false) { 107 | if ($class) { 108 | $output = ($key === 'dataColumns' || $key === 'column') ? $this->$key = $class : $this->$key = $this->getReflection($class); 109 | } 110 | } 111 | } 112 | } 113 | return $output; 114 | } 115 | } 116 | 117 | /** 118 | * simple Dependency injection 119 | * @param $className 120 | * @return object 121 | * @throws ReflectionException 122 | */ 123 | public function getReflection($className) 124 | { 125 | try{ 126 | $reflector = new \ReflectionClass($className); 127 | $constructor = $reflector->getConstructor(); 128 | if (!$constructor) return $reflector->newInstance(); 129 | 130 | $dependencies = []; 131 | $params = $constructor->getParameters(); 132 | foreach ($params as $param) { 133 | $paramType = $param->getClass(); 134 | if ($paramType) { 135 | $dependencies[] = $this->getReflection($paramType->name); 136 | } 137 | } 138 | return $reflector->newInstanceArgs($dependencies); 139 | } catch (\ReflectionException $e) { 140 | throw $e; 141 | } 142 | } 143 | 144 | } -------------------------------------------------------------------------------- /src/Magma/Router/Router.php: -------------------------------------------------------------------------------- 1 | [a-z-]+)', $route); 43 | 44 | // Convert variables with custom regular expressions e.g. {id:\d+} 45 | $route = preg_replace('/\{([a-z]+):([^\}]+)\}/', '(?P<\1>\2)', $route); 46 | 47 | // Add start and end delimiters, and case insensitive flag 48 | $route = '/^' . $route . '$/i'; 49 | 50 | $this->routes[$route] = $params; 51 | } 52 | 53 | /** 54 | * @inheritDoc 55 | */ 56 | public function dispatch(string $url) : void 57 | { 58 | $url = $this->formatQueryString($url); 59 | if ($this->match($url)) { 60 | $controllerString = $this->params['controller'] . $this->controllerSuffix; 61 | $controllerString = $this->transformUpperCamelCase($controllerString); 62 | $controllerString = $this->getNamespace($controllerString) . $controllerString; 63 | 64 | if (class_exists($controllerString)) { 65 | $controllerObject = new $controllerString($this->params); 66 | $action = $this->params['action']; 67 | $action = $this->transformCamelCase($action); 68 | 69 | if (\is_callable([$controllerObject, $action])) { 70 | $controllerObject->$action(); 71 | } else { 72 | throw new BaseBadMethodCallException('Invalid method'); 73 | } 74 | } else { 75 | throw new BaseBadFunctionCallException('Controller class does not exist'); 76 | } 77 | } else { 78 | throw new BaseInvalidArgumentException('404 ERROR no page found'); 79 | } 80 | } 81 | 82 | public function transformUpperCamelCase(string $string) : string 83 | { 84 | return str_replace(' ', '', ucwords(str_replace('-', ' ', $string))); 85 | } 86 | 87 | public function transformCamelCase(string $string) : string 88 | { 89 | return \lcfirst($this->transformUpperCamelCase($string)); 90 | } 91 | 92 | /** 93 | * Match the route to the routes in the routing table, setting the $this->params property 94 | * if a route is found 95 | * 96 | * @param string $url 97 | * @return bool 98 | */ 99 | private function match(string $url) : bool 100 | { 101 | foreach ($this->routes as $route => $params) { 102 | if (preg_match($route, $url, $matches)) { 103 | foreach ($matches as $key => $param) { 104 | if (is_string($key)) { 105 | $params[$key] = $param; 106 | } 107 | } 108 | $this->params = $params; 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | /** 116 | * Get the namespace for the controller class. the namespace difined within the route parameters 117 | * only if it was added. 118 | * 119 | * @param string $string 120 | * @return string 121 | */ 122 | public function getNamespace(string $string) : string 123 | { 124 | $namespace = 'App\Controller\\'; 125 | if (array_key_exists('namespace', $this->params)) { 126 | $namespace .= $this->params['namespace'] . '\\'; 127 | } 128 | return $namespace; 129 | } 130 | 131 | /** 132 | */ 133 | protected function formatQueryString($url) 134 | { 135 | if ($url != '') { 136 | $parts = explode('&', $url, 2); 137 | 138 | if (strpos($parts[0], '=') === false) { 139 | $url = $parts[0]; 140 | } else { 141 | $url = ''; 142 | } 143 | } 144 | 145 | return rtrim($url, '/'); 146 | } 147 | 148 | public function getRoutes() 149 | { 150 | return $this->routes; 151 | } 152 | 153 | 154 | } -------------------------------------------------------------------------------- /src/Magma/Session/Session.php: -------------------------------------------------------------------------------- 1 | isSessionKeyValid($sessionName) === false) { 35 | throw new BaseInvalidArgumentException($sessionName . ' is not a valid session name'); 36 | } 37 | 38 | $this->sessionName = $sessionName; 39 | $this->storage = $storage; 40 | } 41 | 42 | /** 43 | * @inheritdoc 44 | * 45 | * @param string $key 46 | * @param mixed $value 47 | * @return void 48 | * @throws BaseException 49 | */ 50 | public function set(string $key, $value) : void 51 | { 52 | $this->ensureSessionKeyIsValid($key); 53 | try{ 54 | $this->storage->SetSession($key, $value); 55 | } catch(Throwable $throwable) { 56 | throw new BaseException('An exception was thrown in retrieving the key from the session storage. ' . $throwable); 57 | } 58 | 59 | } 60 | 61 | /** 62 | * @inheritdoc 63 | * 64 | * @param string $key 65 | * @param mixed $value 66 | * @return void 67 | * @throws BaseException 68 | */ 69 | public function setArray(string $key, $value) : void 70 | { 71 | $this->ensureSessionKeyIsValid($key); 72 | try{ 73 | $this->storage->setArraySession($key, $value); 74 | }catch(Throwable $throwable) { 75 | throw new BaseException('An exception was thrown in retrieving the key from the session storage. ' . $throwable); 76 | } 77 | 78 | } 79 | 80 | /** 81 | * @inheritdoc 82 | * 83 | * @param string $key 84 | * @param mixed $default 85 | * @return void 86 | * @throws BaseException 87 | */ 88 | public function get(string $key, $default = null) 89 | { 90 | try{ 91 | return $this->storage->getSession($key, $default); 92 | } catch(Throwable $throwable) { 93 | throw $throwable; 94 | } 95 | } 96 | 97 | /** 98 | * @inheritdoc 99 | * 100 | * @param string $key 101 | * @return boolean 102 | * @throws BaseException 103 | */ 104 | public function delete(string $key) : bool 105 | { 106 | $this->ensureSessionKeyIsValid($key); 107 | try{ 108 | $this->storage->deleteSession($key); 109 | }catch(Throwable $throwable) { 110 | throw $throwable; 111 | } 112 | return true; 113 | } 114 | 115 | /** 116 | * @inheritdoc 117 | * 118 | * @return void 119 | */ 120 | public function invalidate() : void 121 | { 122 | $this->storage->invalidate(); 123 | } 124 | 125 | /** 126 | * @inheritdoc 127 | * 128 | * @param string $key 129 | * @param [type] $value 130 | * @return void 131 | * @throws BaseException 132 | */ 133 | public function flush(string $key, $value = null) 134 | { 135 | $this->ensureSessionKeyIsValid($key); 136 | try{ 137 | $this->storage->flush($key, $value); 138 | }catch(Throwable $throwable) { 139 | throw $throwable; 140 | } 141 | } 142 | 143 | /** 144 | * @inheritdoc 145 | * 146 | * @param string $key 147 | * @return boolean 148 | * @throws SessiopnInvalidArgumentException 149 | */ 150 | public function has(string $key) : bool 151 | { 152 | $this->ensureSessionKeyIsValid($key); 153 | return $this->storage->hasSession($key); 154 | } 155 | 156 | /** 157 | * Checks whether our session key is valid according the defined regular expression 158 | * 159 | * @param string $key 160 | * @return boolean 161 | */ 162 | protected function isSessionKeyValid(string $key) : bool 163 | { 164 | return (preg_match(self::SESSION_PATTERN, $key) === 1); 165 | } 166 | 167 | /** 168 | * Checks whether we have session key 169 | * 170 | * @param string $key 171 | * @return void 172 | */ 173 | protected function ensureSessionKeyIsvalid(string $key) : void 174 | { 175 | if ($this->isSessionKeyValid($key) === false) { 176 | throw new BaseInvalidArgumentException($key . ' is not a valid session key'); 177 | } 178 | } 179 | 180 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/QueryBuilder/QueryBuilder.php: -------------------------------------------------------------------------------- 1 | key = $arg; 30 | return $this; 31 | } 32 | 33 | public function insertQuery() : string 34 | { 35 | if ($this->isQueryTypeValid('insert')) { 36 | if (is_array($this->key['fields']) && count($this->key['fields']) > 0) { 37 | $index = array_keys($this->key['fields']); 38 | $value = array(implode(', ', $index), ":" . implode(', :', $index)); 39 | $this->sqlQuery = "INSERT INTO {$this->key['table']} ({$value[0]}) VALUES({$value[1]})"; 40 | return $this->sqlQuery; 41 | } 42 | } 43 | return false; 44 | } 45 | 46 | public function selectQuery() : string 47 | { 48 | if ($this->isQueryTypeValid('select')) { 49 | $selectors = (!empty($this->key['selectors'])) ? implode(", ", $this->key['selectors']) : '*'; 50 | if (isset($this->key['aggregate']) && $this->key['aggregate']) { 51 | $this->sqlQuery = "SELECT {$this->key['aggregate']}({$this->key['aggregate_field']}) FROM {$this->key['table']}"; 52 | } else { 53 | $this->sqlQuery = "SELECT {$selectors} FROM {$this->key['table']}"; 54 | } 55 | $this->sqlQuery = $this->hasConditions(); 56 | return $this->sqlQuery; 57 | 58 | } 59 | return false; 60 | } 61 | 62 | public function updateQuery() : string 63 | { 64 | if ($this->isQueryTypeValid('update')) { 65 | if (is_array($this->key['fields']) && count($this->key['fields']) > 0) { 66 | $values = ''; 67 | foreach ($this->key['fields'] as $field) { 68 | if ($field !== $this->key['primary_key']) { 69 | $values .= $field . " = :" . $field . ", "; 70 | } 71 | } 72 | $values = substr_replace($values, '', -2); 73 | if (count($this->key['fields']) > 0) { 74 | $this->sqlQuery = "UPDATE {$this->key['table']} SET {$values} WHERE {$this->key['primary_key']} = :{$this->key['primary_key']} LIMIT 1"; 75 | if (isset($this->key['primary_key']) && $this->key['primary_key'] === '0') { 76 | unset($this->key['primary_key']); 77 | $this->sqlQuery = "UPDATE {$this->key['table']} SET {$values}"; 78 | } 79 | } 80 | return $this->sqlQuery; 81 | } 82 | } 83 | return false; 84 | } 85 | 86 | public function deleteQuery() : string 87 | { 88 | if ($this->isQueryTypeValid('delete')) { 89 | $index = array_keys($this->key['conditions']); 90 | $this->sqlQuery = "DELETE FROM {$this->key['table']} WHERE {$index[0]} = :{$index[0]} LIMIT 1"; 91 | $bulkDelete = array_values($this->key['fields']); 92 | if (is_array($bulkDelete) && count($bulkDelete) > 1) { 93 | for ($i = 0; $i < count($bulkDelete); $i++) { 94 | $this->sqlQuery = "DELETE FROM {$this->key['table']} WHERE {$index[0]} = :{$index[0]}"; 95 | } 96 | } 97 | 98 | return $this->sqlQuery; 99 | } 100 | return false; 101 | } 102 | 103 | public function searchQuery() : string 104 | { 105 | if ($this->isQueryTypeValid('search ')) { 106 | if (is_array($this->key['selectors']) && $this->key['selectors'] != '') { 107 | $this->sqlQuery = "SELECT * FROM {$this->key['table']} WHERE "; 108 | if ($this->has('selectors')) { 109 | $values = []; 110 | foreach ($this->key['selectors'] as $selector) { 111 | $values[] = $selector . " LIKE " . "{$selector}"; 112 | } 113 | if (count($this->key['selectors']) >= 1) { 114 | $this->sqlQuery .= implode(" OR ", $values); 115 | } 116 | } 117 | //$this->sqlQuery .= $this->orderByQuery(); 118 | //$this->sqlQuery .= $this->queryOffset(); 119 | } 120 | return $this->sqlQuery; 121 | } 122 | return false; 123 | } 124 | 125 | public function rawQuery(): string 126 | { 127 | if ($this->isQueryTypeValid('raw')) { 128 | $this->sqlQuery = $this->key['raw']; 129 | 130 | return $this->sqlQuery; 131 | } 132 | return false; 133 | } 134 | 135 | private function hasConditions() 136 | { 137 | if (isset($this->key['conditions']) && $this->key['conditions'] !='') { 138 | if (is_array($this->key['conditions'])) { 139 | $sort = []; 140 | foreach (array_keys($this->key['conditions']) as $where) { 141 | if (isset($where) && $where !='') { 142 | $sort[] = $where . " = :" . $where; 143 | } 144 | } 145 | if (count($this->key['conditions']) > 0) { 146 | $this->sqlQuery .= " WHERE " . implode(" AND ", $sort); 147 | } 148 | } 149 | } else if (empty($this->key['conditions'])) { 150 | $this->sqlQuery = " WHERE 1"; 151 | } 152 | $this->sqlQuery .= $this->orderByQuery(); 153 | $this->sqlQuery .= $this->queryOffset(); 154 | 155 | return $this->sqlQuery; 156 | } 157 | 158 | 159 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataMapper/DataMapper.php: -------------------------------------------------------------------------------- 1 | dbh = $dbh; 35 | } 36 | 37 | /** 38 | * Check the incoming $valis isn't empty else throw an exception 39 | * 40 | * @param mixed $value 41 | * @param string|null $errorMessage 42 | * @return void 43 | * @throws DataMapperException 44 | */ 45 | private function isEmpty($value, string $errorMessage = null) 46 | { 47 | if (empty($value)) { 48 | throw new BaseNoValueException($errorMessage); 49 | } 50 | } 51 | 52 | /** 53 | * Check the incoming argument $value is an array else throw an exception 54 | * 55 | * @param array $value 56 | * @return void 57 | * @throws BaseInvalidArgumentException 58 | */ 59 | private function isArray(array $value) 60 | { 61 | if (!is_array($value)) { 62 | throw new BaseInvalidArgumentException('Your argument needs to be an array'); 63 | } 64 | } 65 | 66 | /** 67 | * @inheritDoc 68 | */ 69 | public function prepare(string $sqlQuery) : self 70 | { 71 | $this->isEmpty($sqlQuery); 72 | $this->statement = $this->dbh->open()->prepare($sqlQuery); 73 | return $this; 74 | } 75 | 76 | /** 77 | * @inheritDoc 78 | * 79 | * @param [type] $value 80 | * @return void 81 | */ 82 | public function bind($value) 83 | { 84 | try { 85 | switch($value) { 86 | case is_bool($value) : 87 | case intval($value) : 88 | $dataType = PDO::PARAM_INT; 89 | break; 90 | case is_null($value) : 91 | $dataType = PDO::PARAM_NULL; 92 | break; 93 | default : 94 | $dataType = PDO::PARAM_STR; 95 | break; 96 | } 97 | return $dataType; 98 | } catch(BaseException $exception) { 99 | throw $exception; 100 | } 101 | } 102 | 103 | /** 104 | * @inheritDoc 105 | * 106 | * @param array $fields 107 | * @param boolean $isSearch 108 | * @return self 109 | */ 110 | public function bindParameters(array $fields, bool $isSearch = false) : self 111 | { 112 | $this->isArray($fields); 113 | if (is_array($fields)) { 114 | $type = ($isSearch === false) ? $this->bindValues($fields) : $this->bindSearchValues($fields); 115 | if ($type) { 116 | return $this; 117 | } 118 | } 119 | return false; 120 | } 121 | 122 | /** 123 | * Binds a value to a corresponding name or question mark placeholder in the SQL 124 | * statement that was used to prepare the statement 125 | * 126 | * @param array $fields 127 | * @return PDOStatement 128 | * @throws BaseInvalidArgumentException 129 | */ 130 | protected function bindValues(array $fields) : PDOStatement 131 | { 132 | $this->isArray($fields); // don't need 133 | foreach ($fields as $key => $value) { 134 | $this->statement->bindValue(':' . $key, $value, $this->bind($value)); 135 | } 136 | return $this->statement; 137 | } 138 | 139 | /** 140 | * Binds a value to a corresponding name or question mark placeholder 141 | * in the SQL statement that was used to prepare the statement. Similar to 142 | * above but optimised for search queries 143 | * 144 | * @param array $fields 145 | * @return mixed 146 | * @throws BaseInvalidArgumentException 147 | */ 148 | protected function bindSearchValues(array $fields) : PDOStatement 149 | { 150 | $this->isArray($fields); // don't need 151 | foreach ($fields as $key => $value) { 152 | $this->statement->bindValue(':' . $key, '%' . $value . '%', $this->bind($value)); 153 | } 154 | return $this->statement; 155 | } 156 | 157 | /** 158 | * @inheritDoc 159 | * 160 | * @return void 161 | */ 162 | public function execute() 163 | { 164 | if ($this->statement) 165 | return $this->statement->execute(); 166 | } 167 | /** 168 | * @inheritDoc 169 | * 170 | * @return integer 171 | */ 172 | public function numRows() : int 173 | { 174 | if ($this->statement) return $this->statement->rowCount(); 175 | } 176 | /** 177 | * @inheritDoc 178 | * 179 | * @return Object 180 | */ 181 | public function result() : Object 182 | { 183 | if ($this->statement) return $this->statement->fetch(PDO::FETCH_OBJ); 184 | } 185 | /** 186 | * @inheritDoc 187 | * 188 | * @return array 189 | */ 190 | public function results() : array 191 | { 192 | if ($this->statement) return $this->statement->fetchAll(); 193 | } 194 | 195 | /** 196 | * @inheritDoc 197 | */ 198 | public function column() 199 | { 200 | if ($this->statement) return $this->statement->fetchColumn(); 201 | } 202 | 203 | /** 204 | * @inheritDoc 205 | * 206 | * @return integer 207 | */ 208 | public function getLastId() : int 209 | { 210 | try { 211 | if ($this->dbh->open()) { 212 | $lastID = $this->dbh->open()->lastInsertId(); 213 | if (!empty($lastID)) { 214 | return intval($lastID); 215 | } 216 | } 217 | }catch(Throwable $throwable) { 218 | throw $throwable; 219 | } 220 | } 221 | 222 | /** 223 | * Returns the query condition merged with the query parameters 224 | * 225 | * @param array $conditions 226 | * @param array $parameters 227 | * @return array 228 | */ 229 | public function buildQueryParameters(array $conditions = [], array $parameters = []) : array 230 | { 231 | return (!empty($parameters) || (!empty($conditions)) ? array_merge($conditions, $parameters) : $parameters); 232 | } 233 | 234 | /** 235 | * Persist queries to database 236 | * 237 | * @param string $query 238 | * @param array $parameters 239 | * @return mixed 240 | * @throws Throwable 241 | */ 242 | public function persist(string $sqlQuery, array $parameters) 243 | { 244 | try { 245 | return $this->prepare($sqlQuery)->bindParameters($parameters)->execute(); 246 | } catch(Throwable $throwable){ 247 | throw $throwable; 248 | } 249 | } 250 | } -------------------------------------------------------------------------------- /src/Magma/Datatable/Datatable.php: -------------------------------------------------------------------------------- 1 | dataColumnObject = new $dataColumnString(); 29 | if (!$this->dataColumnObject instanceof DatatableColumnInterface) { 30 | throw new BaseUnexpectedValueException($dataColumnString . ' is not a valid data column object.'); 31 | } 32 | $this->dataColumns = $this->dataColumnObject->columns(); 33 | $this->sortController = $sortController; 34 | $this->getRepositoryParts($dataRepository); 35 | return $this; 36 | 37 | } 38 | 39 | private function getRepositoryParts(array $dataRepository) : void 40 | { 41 | list($this->dataOptions, $this->currentPage, $this->totalPages, $this->totalRecords, $this->direction, $this->sortDirection, $this->tdClass, $this->tableColumn, $this->tableOrder) = $dataRepository; 42 | } 43 | 44 | public function table() : ?string 45 | { 46 | extract($this->attr, EXTR_SKIP); 47 | $this->element .= $before; 48 | if (is_array($this->dataColumns) && count($this->dataColumns) > 0) { 49 | if (is_array($this->dataOptions) && $this->dataOptions !=null) { 50 | $this->element .= '' . "\n"; 51 | $this->element .= ($show_table_thead) ? $this->tableGridElements($status) : false; 52 | $this->element .= '' . "\n"; 53 | foreach ($this->dataOptions as $row) { 54 | $this->element .= '' . "\n"; 55 | foreach ($this->dataColumns as $column) { 56 | if (isset($column['show_column']) && $column['show_column'] != false) { 57 | $this->element .= '' . "\n"; 64 | } 65 | } 66 | $this->element .= '' . "\n"; 67 | } 68 | $this->element .= '' . "\n"; 69 | //$this->element .= ($show_table_tfoot) ? $this->tableGridElements($status, true) : ''; 70 | $this->element .= '
'; 58 | if (is_callable($column['formatter'])) { 59 | $this->element .= call_user_func_array($column['formatter'], [$row]); 60 | } else { 61 | $this->element .= (isset($row[$column['db_row']]) ? $row[$column['db_row']] : ''); 62 | } 63 | $this->element .= '
' . "\n"; 71 | } 72 | } 73 | $this->element .= $after; 74 | 75 | return $this->element; 76 | 77 | } 78 | 79 | protected function tableGridElements(string $status, bool $inFoot = false) : string 80 | { 81 | $element = sprintf('<%s>', ($inFoot) ? 'tfoot' : 'thead'); 82 | $element .= ''; 83 | foreach ($this->dataColumns as $column) { 84 | if (isset($column['show_column']) && $column['show_column'] != false) { 85 | $element .= ''; 86 | $element .= $this->tableSorting($column, $status); 87 | $element .= ''; 88 | } 89 | } 90 | $element .= ''; 91 | $element .= sprintf('', ($inFoot) ? 'tfoot' : 'thead'); 92 | 93 | return $element; 94 | } 95 | 96 | private function tableSorting(array $column, string $status) : string 97 | { 98 | $element = ''; 99 | if (isset($column['sortable']) && $column['sortable'] != false) { 100 | $element .= ''; 101 | $element .= $column['dt_row']; 102 | $element .= ''; 103 | $element .= ''; 104 | } else { 105 | $element .= $column['dt_row']; 106 | } 107 | return $element; 108 | } 109 | 110 | public function pagination() : string 111 | { 112 | extract($this->attr, EXTR_SKIP); 113 | 114 | $element = '
'; 115 | $element .= ''; 193 | $element .= '
'; 194 | 195 | return $element; 196 | } 197 | 198 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/EntityManager/Crud.php: -------------------------------------------------------------------------------- 1 | dataMapper = $dataMapper; 43 | $this->queryBuilder = $queryBuilder; 44 | $this->tableSchema = $tableSchema; 45 | $this->tableSchemaID = $tableSchemaID; 46 | $this->options = $options; 47 | } 48 | 49 | /** 50 | * @inheritdoc 51 | * 52 | * @return string 53 | */ 54 | public function getSchema() : string 55 | { 56 | return (string)$this->tableSchema; 57 | } 58 | 59 | /** 60 | * @inheritdoc 61 | * 62 | * @return string 63 | */ 64 | public function getSchemaID() : string 65 | { 66 | return (string)$this->tableSchemaID; 67 | } 68 | 69 | /** 70 | * @inheritdoc 71 | * 72 | * @return integer 73 | */ 74 | public function lastID() : int 75 | { 76 | return $this->dataMapper->getLastId(); 77 | } 78 | 79 | /** 80 | * @inheritdoc 81 | * 82 | * @param array $fields 83 | * @return boolean 84 | */ 85 | public function create(array $fields = []) : bool 86 | { 87 | try { 88 | $args = ['table' => $this->getSchema(), 'type' => 'insert', 'fields' => $fields]; 89 | $query = $this->queryBuilder->buildQuery($args)->insertQuery(); 90 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($fields)); 91 | if ($this->dataMapper->numRows() ==1) { 92 | return true; 93 | } 94 | } catch(Throwable $throwable) { 95 | throw $throwable; 96 | } 97 | } 98 | 99 | /** 100 | * @inheritdoc 101 | * 102 | * @param array $selectors 103 | * @param array $conditions 104 | * @param array $parameters 105 | * @param array $optional 106 | * @return array 107 | */ 108 | public function read(array $selectors = [], array $conditions = [], array $parameters = [], array $optional = []) : array 109 | { 110 | //try{ 111 | $args = ['table' => $this->getSchema(), 'type' => 'select', 'selectors' => $selectors, 'conditions' => $conditions, 'params' => $parameters, 'extras' => $optional]; 112 | $query = $this->queryBuilder->buildQuery($args)->selectQuery(); 113 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($conditions, $parameters)); 114 | if ($this->dataMapper->numRows() >= 0) { 115 | return $this->dataMapper->results(); 116 | } 117 | //} catch(Throwable $throwable) { 118 | //throw $throwable; 119 | //} 120 | } 121 | 122 | /** 123 | * @inheritdoc 124 | * 125 | * @param array $fields 126 | * @param string $primaryKey 127 | * @return boolean 128 | */ 129 | public function update(array $fields = [], string $primaryKey) : bool 130 | { 131 | try { 132 | $args = ['table' => $this->getSchema(), 'type' => 'update', 'fields' => $fields, 'primary_key' => $primaryKey]; 133 | $query = $this->queryBuilder->buildQuery($args)->updateQuery(); 134 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($fields)); 135 | if ($this->dataMapper->numRows() == 1) { 136 | return true; 137 | } 138 | }catch(Throwable $throwable) { 139 | throw $throwable; 140 | } 141 | } 142 | 143 | /** 144 | * @inheritdoc 145 | * 146 | * @param array $conditions 147 | * @return boolean 148 | */ 149 | public function delete(array $conditions = []) : bool 150 | { 151 | try { 152 | $args = ['table' => $this->getSchema(), 'type' => 'delete', 'conditions' => $conditions]; 153 | $query = $this->queryBuilder->buildQuery($args)->deleteQuery(); 154 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($conditions)); 155 | if ($this->dataMapper->numRows() == 1) { 156 | return true; 157 | } 158 | }catch(Throwable $throwable) { 159 | throw $throwable; 160 | } 161 | } 162 | 163 | /** 164 | * @inheritdoc 165 | * 166 | * @param array $selectors 167 | * @param array $conditions 168 | * @return array 169 | */ 170 | public function search(array $selectors = [], array $conditions = []) : array 171 | { 172 | try { 173 | $args = ['table' => $this->getSchema(), 'type' => 'search', 'selectors' => $selectors, 'conditions' => $conditions]; 174 | $query = $this->queryBuilder->buildQuery($args)->searchQuery(); 175 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($conditions)); 176 | if ($this->dataMapper->numRows() >= 0) { 177 | return $this->dataMapper->results(); 178 | } 179 | }catch(Throwable $throwable) { 180 | throw $throwable; 181 | } 182 | } 183 | 184 | /** 185 | * @inheritDoc 186 | * 187 | * @param array $selectors 188 | * @param array $conditions 189 | * @return Object|null 190 | */ 191 | public function get(array $selectors = [], array $conditions = []) : ?Object 192 | { 193 | $args = ['table' => $this->getSchema(), 'type' => 'select', 'selectors' => $selectors, 'conditions' => $conditions]; 194 | $query = $this->queryBuilder->buildQuery($args)->selectQuery(); 195 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($conditions)); 196 | if ($this->dataMapper->numRows() >= 0) { 197 | return $this->dataMapper->result(); 198 | } 199 | } 200 | 201 | /** 202 | * @inheritDoc 203 | * @throws Throwable 204 | */ 205 | public function aggregate(string $type, ?string $field = 'id', array $conditions = []) 206 | { 207 | $args = ['table' => $this->getSchema(), 'primary_key'=>$this->getSchemaID(), 208 | 'type' => 'select', 'aggregate' => $type, 'aggregate_field' => $field, 209 | 'conditions' => $conditions]; 210 | 211 | $query = $this->queryBuilder->buildQuery($args)->selectQuery(); 212 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($conditions)); 213 | if ($this->dataMapper->numRows() > 0) 214 | return $this->dataMapper->column(); 215 | } 216 | 217 | /** 218 | * @inheritDoc 219 | * @throws Throwable 220 | */ 221 | public function countRecords(array $conditions = [], ?string $field = 'id') : int 222 | { 223 | if ($this->getSchemaID() !='') { 224 | return empty($conditions) ? $this->aggregate('count', $this->getSchemaID()) : $this->aggregate('count', $this->getSchemaID(), $conditions); 225 | } 226 | } 227 | 228 | /** 229 | * @inheritDoc 230 | * 231 | * @param string $sqlQuery 232 | * @param array|null $conditions 233 | * @param string $resultType 234 | * @return void 235 | */ 236 | public function rawQuery(string $sqlQuery, ?array $conditions = [], string $resultType = 'column') 237 | { 238 | /*$args = ['table' => $this->getSchema(), 'type' => 'raw', 'conditions' => $conditions, 'raw' => $sqlQuery]; 239 | $query = $this->queryBuilder->buildQuery($args)->rawQuery(); 240 | $this->dataMapper->persist($query, $this->dataMapper->buildQueryParameters($conditions)); 241 | if ($this->dataMapper->numRows()) { 242 | if (!in_array($resultType, ['fetch', 'fetch_all', 'column'])) { 243 | throw new BaseInvalidArgumentException('Invalid 3rd argument. Your options are "fetch, fetch_all or column"'); 244 | } 245 | switch ($resultType) { 246 | case 'column' : 247 | //$data = $this->dataMapper->column(); not implemented yet! 248 | break; 249 | case 'fetch' : 250 | $data = $this->dataMapper->result(); 251 | break; 252 | case 'fetch_all' : 253 | $data = $this->dataMapper->results(); 254 | break; 255 | default : 256 | throw new BaseUnexpectedValueException('Please choose a return type for this method ie. "fetch, fetch_all or column."'); 257 | break; 258 | } 259 | if ($data) { 260 | return $data; 261 | } 262 | }*/ 263 | 264 | } 265 | 266 | 267 | } -------------------------------------------------------------------------------- /src/Magma/LiquidOrm/DataRepository/DataRepository.php: -------------------------------------------------------------------------------- 1 | em = $em; 22 | } 23 | 24 | /** 25 | * Checks whether the arguement is of the array type else throw an exception 26 | * 27 | * @param array $conditions 28 | * @return void 29 | */ 30 | private function isArray(array $conditions) : void 31 | { 32 | if (!is_array($conditions)) 33 | throw new BaseInvalidArgumentException('The argument supplied is not an array'); 34 | } 35 | 36 | /** 37 | * Checks whether the argument is set else throw an exception 38 | * 39 | * @param integer $id 40 | * @return void 41 | */ 42 | private function isEmpty(int $id) : void 43 | { 44 | if (empty($id)) 45 | throw new BaseInvalidArgumentException('Argument should not be empty'); 46 | } 47 | 48 | /** 49 | * @inheritDoc 50 | * 51 | * @param integer $id 52 | * @return array 53 | * @throws BaseInvalidArgumentException 54 | */ 55 | public function find(int $id) : array 56 | { 57 | $this->isEmpty($id); 58 | try{ 59 | return $this->findOneBy(['id' => $id]); 60 | }catch(Throwable $throwable) { 61 | throw $throwable; 62 | } 63 | } 64 | 65 | /** 66 | * @inheritDoc 67 | * 68 | * @return array 69 | */ 70 | public function findAll() : array 71 | { 72 | try{ 73 | return $this->findBy(); 74 | }catch(Throwable $throwable) { 75 | throw $throwable; 76 | } 77 | } 78 | 79 | /** 80 | * @inheritDoc 81 | * 82 | * @param array $selectors 83 | * @param array $conditions 84 | * @param array $parameters 85 | * @param array $optional 86 | * @return array 87 | */ 88 | public function findBy(array $selectors = [], array $conditions = [], array $parameters = [], array $optional = []) : array 89 | { 90 | try{ 91 | return $this->em->getCrud()->read($selectors, $conditions, $parameters, $optional); 92 | }catch(Throwable $throwable) { 93 | throw $throwable; 94 | } 95 | } 96 | 97 | /** 98 | * @inheritDoc 99 | * 100 | * @param array $conditions 101 | * @return array 102 | * @throws BaseInvalidArgumentException 103 | */ 104 | public function findOneBy(array $conditions) : array 105 | { 106 | $this->isArray($conditions); 107 | try{ 108 | return $this->em->getCrud()->read([], $conditions); 109 | }catch(Throwable $throwable) { 110 | throw $throwable; 111 | } 112 | } 113 | 114 | /** 115 | * @inheritDoc 116 | * 117 | * @param array $conditions 118 | * @param array $selectors 119 | * @return Object 120 | */ 121 | public function findObjectBy(array $conditions = [], array $selectors = []) : Object 122 | { 123 | $this->isArray($conditions); 124 | try{ 125 | return $this->em->getCrud()->get($selectors, $conditions); 126 | } catch(Throwable $throwable) { 127 | throw $throwable; 128 | } 129 | } 130 | 131 | /** 132 | * @inheritDoc 133 | * 134 | * @param array $selectors 135 | * @param array $conditions 136 | * @param array $parameters 137 | * @param array $optional 138 | * @return array 139 | * @throws BaseInvalidArgumentException 140 | */ 141 | public function findBySearch(array $selectors = [], array $conditions = [], array $parameters = [], array $optional = []) : array 142 | { 143 | $this->isArray($conditions); 144 | try{ 145 | return $this->em->getCrud()->search($selectors, $conditions, $parameters, $optional); 146 | }catch(Throwable $throwable) { 147 | throw $throwable; 148 | } 149 | } 150 | 151 | /** 152 | * @inheritDoc 153 | * 154 | * @param array $conditions 155 | * @return boolean 156 | * @throws BaseInvalidArgumentException 157 | */ 158 | public function findByIdAndDelete(array $conditions) : bool 159 | { 160 | $this->isArray($conditions); 161 | try{ 162 | $result = $this->findOneBy($conditions); 163 | if ($result !=null && count($result) > 0) { 164 | $delete = $this->em->getCrud()->delete($conditions); 165 | if ($delete) { 166 | return true; 167 | } 168 | } 169 | }catch(Throwable $throwable) { 170 | throw $throwable; 171 | } 172 | } 173 | 174 | /** 175 | * @inheritDoc 176 | * 177 | * @param array $fields 178 | * @param integer $id 179 | * @return boolean 180 | * @throws BaseInvalidArgumentException 181 | */ 182 | public function findByIdAndUpdate(array $fields = [], int $id) : bool 183 | { 184 | $this->isArray($fields); 185 | try{ 186 | $result = $this->findOneBy([$this->em->getCrud()->getSchemaID() => $id]); 187 | if ($result !=null && count($result) > 0) { 188 | $params = (!empty($fields)) ? array_merge([$this->em->getCrud()->getSchemaID() => $id], $fields) : $fields; 189 | $update = $this->em->getCrud()->update($params, $this->em->getCrud()->getSchemaID()); 190 | if ($update) { 191 | return true; 192 | } 193 | } 194 | }catch(Throwable $throwable) { 195 | throw $throwable; 196 | } 197 | } 198 | 199 | /** 200 | * @inheritDoc 201 | * 202 | * @param array $args 203 | * @param Object $request 204 | * @return array 205 | */ 206 | public function findWithSearchAndPaging(Object $request, array $args = []) : array 207 | { 208 | list($conditions, $totalRecords) = $this->getCurrentQueryStatus($request, $args); 209 | $sorting = new Sortable($args['sort_columns']); 210 | $paging = new Paginator($totalRecords, $args['records_per_page'], $request->query->getInt('page', 1)); 211 | 212 | $parameters = ['limit' => $args['records_per_page'], 'offset' => $paging->getOffset()]; 213 | $optional = ['orderby' => $sorting->getColumn() . ' ' . $sorting->getDirection()]; 214 | 215 | if ($request->query->getAlnum($args['filter_alias'])) { 216 | $searchRequest = $request->query->getAlnum($args['filter_alias']); 217 | if (is_array($args['filter_by'])) { 218 | for ($i=0; $i < count($args['filter_by']); $i++) { 219 | $searchConditions = [$args['filter_by'][$i] => $searchRequest]; 220 | } 221 | } 222 | $results = $this->findBySearch($args['filter_by'], $searchConditions); 223 | } else { 224 | $queryConditions = array_merge($args['additional_conditions'], $conditions); 225 | $results = $this->findBy($args['selectors'], $queryConditions, $parameters, $optional); 226 | } 227 | return [ 228 | $results, 229 | $paging->getPage(), 230 | $paging->getTotalPages(), 231 | $totalRecords, 232 | $sorting->sortDirection(), 233 | $sorting->sortDescAsc(), 234 | $sorting->getClass(), 235 | $sorting->getColumn(), 236 | $sorting->getDirection() 237 | ]; 238 | } 239 | 240 | private function getCurrentQueryStatus(Object $request, array $args) 241 | { 242 | $totalRecords = 0; 243 | $req = $request->query; 244 | $status = $req->getAlnum($args['query']); 245 | $searchResults = $req->getAlnum($args['filter_alias']); 246 | if ($searchResults) { 247 | for ($i=0; $i < count($args['filter_by']); $i++) { 248 | $conditions = [$args['filter_by'][$i] => $searchResults]; 249 | $totalRecords = $this->em->getCrud()->countRecords($conditions, $args['filter_by'][$i]); 250 | } 251 | } else if ($status) { 252 | $conditions = [$args['query'] => $status]; 253 | $totalRecords = $this->em->getCrud()->countRecords($conditions); 254 | } else { 255 | $conditions = []; 256 | $totalRecords = $this->em->getCrud()->countRecords($conditions); 257 | } 258 | return [ 259 | $conditions, 260 | $totalRecords 261 | ]; 262 | } 263 | 264 | 265 | /** 266 | * @inheritDoc 267 | * 268 | * @param integer $id 269 | * @param array $selectors 270 | * @return self 271 | */ 272 | public function findAndReturn(int $id, array $selectors = []) : self 273 | { 274 | if (empty($id) || $id === 0) { 275 | throw new BaseInvalidArgumentException('Please add a valid argument'); 276 | } 277 | try { 278 | $this->findAndReturn = $this->findObjectBy($selectors, ['id' => $id]); 279 | return $this; 280 | }catch(Throwable $throwable) { 281 | throw $throwable; 282 | } 283 | } 284 | 285 | /** 286 | * @inheritDoc 287 | * 288 | * @return Object|null 289 | * @throws LoaderError 290 | * @throws RuntimeError 291 | * @throws SyntaxError 292 | */ 293 | public function or404() 294 | { 295 | if ($this->findAndReturn !=null) { 296 | return $this->findAndReturn; 297 | } else { 298 | header('HTTP/1.1 404 not found'); 299 | $twig = new \Magma\Base\BaseView(); 300 | $twig->twigRender('error/404.html.twig'); 301 | exit; 302 | } 303 | } 304 | 305 | 306 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "817ebe3920444c7b37b87cb98af0fb31", 8 | "packages": [ 9 | { 10 | "name": "symfony/deprecation-contracts", 11 | "version": "v2.2.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/symfony/deprecation-contracts.git", 15 | "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", 20 | "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=7.1" 25 | }, 26 | "type": "library", 27 | "extra": { 28 | "branch-alias": { 29 | "dev-master": "2.2-dev" 30 | }, 31 | "thanks": { 32 | "name": "symfony/contracts", 33 | "url": "https://github.com/symfony/contracts" 34 | } 35 | }, 36 | "autoload": { 37 | "files": [ 38 | "function.php" 39 | ] 40 | }, 41 | "notification-url": "https://packagist.org/downloads/", 42 | "license": [ 43 | "MIT" 44 | ], 45 | "authors": [ 46 | { 47 | "name": "Nicolas Grekas", 48 | "email": "p@tchwork.com" 49 | }, 50 | { 51 | "name": "Symfony Community", 52 | "homepage": "https://symfony.com/contributors" 53 | } 54 | ], 55 | "description": "A generic function and convention to trigger deprecation notices", 56 | "homepage": "https://symfony.com", 57 | "support": { 58 | "source": "https://github.com/symfony/deprecation-contracts/tree/master" 59 | }, 60 | "funding": [ 61 | { 62 | "url": "https://symfony.com/sponsor", 63 | "type": "custom" 64 | }, 65 | { 66 | "url": "https://github.com/fabpot", 67 | "type": "github" 68 | }, 69 | { 70 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 71 | "type": "tidelift" 72 | } 73 | ], 74 | "time": "2020-09-07T11:33:47+00:00" 75 | }, 76 | { 77 | "name": "symfony/http-foundation", 78 | "version": "v5.2.0-RC2", 79 | "source": { 80 | "type": "git", 81 | "url": "https://github.com/symfony/http-foundation.git", 82 | "reference": "ba0aeb1f49a2e687446fb82b828e957dfd999fe1" 83 | }, 84 | "dist": { 85 | "type": "zip", 86 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ba0aeb1f49a2e687446fb82b828e957dfd999fe1", 87 | "reference": "ba0aeb1f49a2e687446fb82b828e957dfd999fe1", 88 | "shasum": "" 89 | }, 90 | "require": { 91 | "php": ">=7.2.5", 92 | "symfony/deprecation-contracts": "^2.1", 93 | "symfony/polyfill-mbstring": "~1.1", 94 | "symfony/polyfill-php80": "^1.15" 95 | }, 96 | "require-dev": { 97 | "predis/predis": "~1.0", 98 | "symfony/cache": "^4.4|^5.0", 99 | "symfony/expression-language": "^4.4|^5.0", 100 | "symfony/mime": "^4.4|^5.0" 101 | }, 102 | "suggest": { 103 | "symfony/mime": "To use the file extension guesser" 104 | }, 105 | "type": "library", 106 | "autoload": { 107 | "psr-4": { 108 | "Symfony\\Component\\HttpFoundation\\": "" 109 | }, 110 | "exclude-from-classmap": [ 111 | "/Tests/" 112 | ] 113 | }, 114 | "notification-url": "https://packagist.org/downloads/", 115 | "license": [ 116 | "MIT" 117 | ], 118 | "authors": [ 119 | { 120 | "name": "Fabien Potencier", 121 | "email": "fabien@symfony.com" 122 | }, 123 | { 124 | "name": "Symfony Community", 125 | "homepage": "https://symfony.com/contributors" 126 | } 127 | ], 128 | "description": "Symfony HttpFoundation Component", 129 | "homepage": "https://symfony.com", 130 | "support": { 131 | "source": "https://github.com/symfony/http-foundation/tree/v5.2.0-RC2" 132 | }, 133 | "funding": [ 134 | { 135 | "url": "https://symfony.com/sponsor", 136 | "type": "custom" 137 | }, 138 | { 139 | "url": "https://github.com/fabpot", 140 | "type": "github" 141 | }, 142 | { 143 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 144 | "type": "tidelift" 145 | } 146 | ], 147 | "time": "2020-11-20T17:25:36+00:00" 148 | }, 149 | { 150 | "name": "symfony/polyfill-ctype", 151 | "version": "v1.20.0", 152 | "source": { 153 | "type": "git", 154 | "url": "https://github.com/symfony/polyfill-ctype.git", 155 | "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41" 156 | }, 157 | "dist": { 158 | "type": "zip", 159 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41", 160 | "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41", 161 | "shasum": "" 162 | }, 163 | "require": { 164 | "php": ">=7.1" 165 | }, 166 | "suggest": { 167 | "ext-ctype": "For best performance" 168 | }, 169 | "type": "library", 170 | "extra": { 171 | "branch-alias": { 172 | "dev-main": "1.20-dev" 173 | }, 174 | "thanks": { 175 | "name": "symfony/polyfill", 176 | "url": "https://github.com/symfony/polyfill" 177 | } 178 | }, 179 | "autoload": { 180 | "psr-4": { 181 | "Symfony\\Polyfill\\Ctype\\": "" 182 | }, 183 | "files": [ 184 | "bootstrap.php" 185 | ] 186 | }, 187 | "notification-url": "https://packagist.org/downloads/", 188 | "license": [ 189 | "MIT" 190 | ], 191 | "authors": [ 192 | { 193 | "name": "Gert de Pagter", 194 | "email": "BackEndTea@gmail.com" 195 | }, 196 | { 197 | "name": "Symfony Community", 198 | "homepage": "https://symfony.com/contributors" 199 | } 200 | ], 201 | "description": "Symfony polyfill for ctype functions", 202 | "homepage": "https://symfony.com", 203 | "keywords": [ 204 | "compatibility", 205 | "ctype", 206 | "polyfill", 207 | "portable" 208 | ], 209 | "support": { 210 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.20.0" 211 | }, 212 | "funding": [ 213 | { 214 | "url": "https://symfony.com/sponsor", 215 | "type": "custom" 216 | }, 217 | { 218 | "url": "https://github.com/fabpot", 219 | "type": "github" 220 | }, 221 | { 222 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 223 | "type": "tidelift" 224 | } 225 | ], 226 | "time": "2020-10-23T14:02:19+00:00" 227 | }, 228 | { 229 | "name": "symfony/polyfill-mbstring", 230 | "version": "v1.20.0", 231 | "source": { 232 | "type": "git", 233 | "url": "https://github.com/symfony/polyfill-mbstring.git", 234 | "reference": "39d483bdf39be819deabf04ec872eb0b2410b531" 235 | }, 236 | "dist": { 237 | "type": "zip", 238 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/39d483bdf39be819deabf04ec872eb0b2410b531", 239 | "reference": "39d483bdf39be819deabf04ec872eb0b2410b531", 240 | "shasum": "" 241 | }, 242 | "require": { 243 | "php": ">=7.1" 244 | }, 245 | "suggest": { 246 | "ext-mbstring": "For best performance" 247 | }, 248 | "type": "library", 249 | "extra": { 250 | "branch-alias": { 251 | "dev-main": "1.20-dev" 252 | }, 253 | "thanks": { 254 | "name": "symfony/polyfill", 255 | "url": "https://github.com/symfony/polyfill" 256 | } 257 | }, 258 | "autoload": { 259 | "psr-4": { 260 | "Symfony\\Polyfill\\Mbstring\\": "" 261 | }, 262 | "files": [ 263 | "bootstrap.php" 264 | ] 265 | }, 266 | "notification-url": "https://packagist.org/downloads/", 267 | "license": [ 268 | "MIT" 269 | ], 270 | "authors": [ 271 | { 272 | "name": "Nicolas Grekas", 273 | "email": "p@tchwork.com" 274 | }, 275 | { 276 | "name": "Symfony Community", 277 | "homepage": "https://symfony.com/contributors" 278 | } 279 | ], 280 | "description": "Symfony polyfill for the Mbstring extension", 281 | "homepage": "https://symfony.com", 282 | "keywords": [ 283 | "compatibility", 284 | "mbstring", 285 | "polyfill", 286 | "portable", 287 | "shim" 288 | ], 289 | "support": { 290 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.20.0" 291 | }, 292 | "funding": [ 293 | { 294 | "url": "https://symfony.com/sponsor", 295 | "type": "custom" 296 | }, 297 | { 298 | "url": "https://github.com/fabpot", 299 | "type": "github" 300 | }, 301 | { 302 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 303 | "type": "tidelift" 304 | } 305 | ], 306 | "time": "2020-10-23T14:02:19+00:00" 307 | }, 308 | { 309 | "name": "symfony/polyfill-php80", 310 | "version": "v1.20.0", 311 | "source": { 312 | "type": "git", 313 | "url": "https://github.com/symfony/polyfill-php80.git", 314 | "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de" 315 | }, 316 | "dist": { 317 | "type": "zip", 318 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/e70aa8b064c5b72d3df2abd5ab1e90464ad009de", 319 | "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de", 320 | "shasum": "" 321 | }, 322 | "require": { 323 | "php": ">=7.1" 324 | }, 325 | "type": "library", 326 | "extra": { 327 | "branch-alias": { 328 | "dev-main": "1.20-dev" 329 | }, 330 | "thanks": { 331 | "name": "symfony/polyfill", 332 | "url": "https://github.com/symfony/polyfill" 333 | } 334 | }, 335 | "autoload": { 336 | "psr-4": { 337 | "Symfony\\Polyfill\\Php80\\": "" 338 | }, 339 | "files": [ 340 | "bootstrap.php" 341 | ], 342 | "classmap": [ 343 | "Resources/stubs" 344 | ] 345 | }, 346 | "notification-url": "https://packagist.org/downloads/", 347 | "license": [ 348 | "MIT" 349 | ], 350 | "authors": [ 351 | { 352 | "name": "Ion Bazan", 353 | "email": "ion.bazan@gmail.com" 354 | }, 355 | { 356 | "name": "Nicolas Grekas", 357 | "email": "p@tchwork.com" 358 | }, 359 | { 360 | "name": "Symfony Community", 361 | "homepage": "https://symfony.com/contributors" 362 | } 363 | ], 364 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 365 | "homepage": "https://symfony.com", 366 | "keywords": [ 367 | "compatibility", 368 | "polyfill", 369 | "portable", 370 | "shim" 371 | ], 372 | "support": { 373 | "source": "https://github.com/symfony/polyfill-php80/tree/v1.20.0" 374 | }, 375 | "funding": [ 376 | { 377 | "url": "https://symfony.com/sponsor", 378 | "type": "custom" 379 | }, 380 | { 381 | "url": "https://github.com/fabpot", 382 | "type": "github" 383 | }, 384 | { 385 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 386 | "type": "tidelift" 387 | } 388 | ], 389 | "time": "2020-10-23T14:02:19+00:00" 390 | }, 391 | { 392 | "name": "symfony/yaml", 393 | "version": "v5.2.0-RC2", 394 | "source": { 395 | "type": "git", 396 | "url": "https://github.com/symfony/yaml.git", 397 | "reference": "34b513f1bfb3677fc40aac34f8e4397eba4066ed" 398 | }, 399 | "dist": { 400 | "type": "zip", 401 | "url": "https://api.github.com/repos/symfony/yaml/zipball/34b513f1bfb3677fc40aac34f8e4397eba4066ed", 402 | "reference": "34b513f1bfb3677fc40aac34f8e4397eba4066ed", 403 | "shasum": "" 404 | }, 405 | "require": { 406 | "php": ">=7.2.5", 407 | "symfony/deprecation-contracts": "^2.1", 408 | "symfony/polyfill-ctype": "~1.8" 409 | }, 410 | "conflict": { 411 | "symfony/console": "<4.4" 412 | }, 413 | "require-dev": { 414 | "symfony/console": "^4.4|^5.0" 415 | }, 416 | "suggest": { 417 | "symfony/console": "For validating YAML files using the lint command" 418 | }, 419 | "bin": [ 420 | "Resources/bin/yaml-lint" 421 | ], 422 | "type": "library", 423 | "autoload": { 424 | "psr-4": { 425 | "Symfony\\Component\\Yaml\\": "" 426 | }, 427 | "exclude-from-classmap": [ 428 | "/Tests/" 429 | ] 430 | }, 431 | "notification-url": "https://packagist.org/downloads/", 432 | "license": [ 433 | "MIT" 434 | ], 435 | "authors": [ 436 | { 437 | "name": "Fabien Potencier", 438 | "email": "fabien@symfony.com" 439 | }, 440 | { 441 | "name": "Symfony Community", 442 | "homepage": "https://symfony.com/contributors" 443 | } 444 | ], 445 | "description": "Symfony Yaml Component", 446 | "homepage": "https://symfony.com", 447 | "support": { 448 | "source": "https://github.com/symfony/yaml/tree/v5.2.0-RC2" 449 | }, 450 | "funding": [ 451 | { 452 | "url": "https://symfony.com/sponsor", 453 | "type": "custom" 454 | }, 455 | { 456 | "url": "https://github.com/fabpot", 457 | "type": "github" 458 | }, 459 | { 460 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 461 | "type": "tidelift" 462 | } 463 | ], 464 | "time": "2020-11-15T22:55:04+00:00" 465 | }, 466 | { 467 | "name": "twig/twig", 468 | "version": "v3.1.1", 469 | "source": { 470 | "type": "git", 471 | "url": "https://github.com/twigphp/Twig.git", 472 | "reference": "b02fa41f3783a2616eccef7b92fbc2343ffed737" 473 | }, 474 | "dist": { 475 | "type": "zip", 476 | "url": "https://api.github.com/repos/twigphp/Twig/zipball/b02fa41f3783a2616eccef7b92fbc2343ffed737", 477 | "reference": "b02fa41f3783a2616eccef7b92fbc2343ffed737", 478 | "shasum": "" 479 | }, 480 | "require": { 481 | "php": ">=7.2.5", 482 | "symfony/polyfill-ctype": "^1.8", 483 | "symfony/polyfill-mbstring": "^1.3" 484 | }, 485 | "require-dev": { 486 | "psr/container": "^1.0", 487 | "symfony/phpunit-bridge": "^4.4.9|^5.0.9" 488 | }, 489 | "type": "library", 490 | "extra": { 491 | "branch-alias": { 492 | "dev-master": "3.1-dev" 493 | } 494 | }, 495 | "autoload": { 496 | "psr-4": { 497 | "Twig\\": "src/" 498 | } 499 | }, 500 | "notification-url": "https://packagist.org/downloads/", 501 | "license": [ 502 | "BSD-3-Clause" 503 | ], 504 | "authors": [ 505 | { 506 | "name": "Fabien Potencier", 507 | "email": "fabien@symfony.com", 508 | "homepage": "http://fabien.potencier.org", 509 | "role": "Lead Developer" 510 | }, 511 | { 512 | "name": "Twig Team", 513 | "role": "Contributors" 514 | }, 515 | { 516 | "name": "Armin Ronacher", 517 | "email": "armin.ronacher@active-4.com", 518 | "role": "Project Founder" 519 | } 520 | ], 521 | "description": "Twig, the flexible, fast, and secure template language for PHP", 522 | "homepage": "https://twig.symfony.com", 523 | "keywords": [ 524 | "templating" 525 | ], 526 | "support": { 527 | "issues": "https://github.com/twigphp/Twig/issues", 528 | "source": "https://github.com/twigphp/Twig/tree/v3.1.1" 529 | }, 530 | "funding": [ 531 | { 532 | "url": "https://github.com/fabpot", 533 | "type": "github" 534 | }, 535 | { 536 | "url": "https://tidelift.com/funding/github/packagist/twig/twig", 537 | "type": "tidelift" 538 | } 539 | ], 540 | "time": "2020-10-27T19:28:23+00:00" 541 | } 542 | ], 543 | "packages-dev": [], 544 | "aliases": [], 545 | "minimum-stability": "alpha", 546 | "stability-flags": { 547 | "symfony/http-foundation": 5, 548 | "symfony/yaml": 5 549 | }, 550 | "prefer-stable": false, 551 | "prefer-lowest": false, 552 | "platform": { 553 | "php": "7.4.12|^8.0", 554 | "ext-mbstring": "*", 555 | "ext-iconv": "*", 556 | "ext-pdo": "*", 557 | "ext-json": "*", 558 | "ext-curl": "*", 559 | "ext-simplexml": "*" 560 | }, 561 | "platform-dev": [], 562 | "plugin-api-version": "2.0.0" 563 | } 564 | --------------------------------------------------------------------------------