├── tests ├── resources │ ├── languages │ │ └── en.json │ └── config │ │ ├── config.json │ │ └── database.json ├── template │ └── cache │ │ └── mail │ │ └── test.php ├── unit │ ├── account │ │ ├── AuthTest.php │ │ └── UserTest.php │ ├── mailer │ │ └── MailerTest.php │ └── data │ │ ├── ConfigTest.php │ │ └── MySQLTest.php └── TestCase.php ├── project ├── public │ ├── assets │ │ ├── scss │ │ │ ├── advanced.scss │ │ │ └── application.scss │ │ ├── stylesheets │ │ │ └── application.min.css │ │ └── images │ │ │ ├── advanced.png │ │ │ └── favicon.png │ ├── index.php │ ├── .htaccess │ └── web.config ├── resources │ ├── config │ │ ├── database.json │ │ └── config.json │ └── languages │ │ ├── en.json │ │ └── es.json ├── template │ └── cache │ │ └── templates │ │ ├── footer.php │ │ ├── header.php │ │ └── index.php ├── Project.php └── controllers │ └── mainController.php ├── micro-advanced ├── resources │ ├── config │ │ ├── database.json │ │ └── config.json │ └── languages │ │ ├── en.json │ │ └── es.json ├── template │ ├── cache │ │ └── main │ │ │ └── index.php │ └── views │ │ └── main │ │ └── index.atpl ├── mailer │ ├── ReplyTo.php │ ├── Receipient.php │ ├── IPerson.php │ ├── Attachment.php │ └── Person.php ├── exceptions │ ├── UserException.php │ ├── FileException.php │ ├── ConfigException.php │ ├── RouterException.php │ ├── DatabaseException.php │ ├── ResponseException.php │ ├── MailerException.php │ ├── ProjectException.php │ ├── AdvancedException.php │ └── Exception.php ├── sql │ ├── query │ │ ├── join │ │ │ ├── FullJoin.php │ │ │ ├── LeftJoin.php │ │ │ ├── InnerJoin.php │ │ │ ├── RightJoin.php │ │ │ ├── IJoin.php │ │ │ └── Join.php │ │ ├── Drop.php │ │ ├── Truncate.php │ │ ├── IQuery.php │ │ ├── Delete.php │ │ ├── ShowColumns.php │ │ ├── DropColumns.php │ │ ├── Insert.php │ │ ├── Create.php │ │ ├── AddColumns.php │ │ ├── ModifyColumns.php │ │ ├── Query.php │ │ ├── Update.php │ │ └── Select.php │ ├── table │ │ ├── ITable.php │ │ └── Table.php │ └── ISQL.php ├── file │ ├── IFile.php │ ├── UploadFile.php │ ├── Directory.php │ └── File.php ├── session │ ├── IManager.php │ ├── SessionManager.php │ └── CookieManager.php ├── config │ ├── provider │ │ ├── JsonProvider.php │ │ ├── IProvider.php │ │ └── YamlProvider.php │ ├── IConfig.php │ └── Config.php ├── user │ ├── IUser.php │ ├── provider │ │ ├── IProvider.php │ │ └── MySQLProvider.php │ ├── auth │ │ ├── IAuth.php │ │ └── Auth.php │ ├── User.php │ ├── Guest.php │ └── UserFactory.php ├── http │ ├── Get.php │ ├── Post.php │ ├── router │ │ └── Router.php │ └── Response.php ├── utils │ ├── ExecutionTime.php │ ├── Convert.php │ └── DateTime.php ├── controllers │ └── Controller.php ├── language │ └── Language.php ├── Bootstrap.php └── project │ └── Project.php ├── .htaccess ├── .gitignore ├── phpunit.xml ├── composer.json ├── environment.php └── README.md /tests/resources/languages/en.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /project/public/assets/scss/advanced.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /project/resources/config/database.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /micro-advanced/resources/config/database.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /project/resources/languages/en.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /project/resources/languages/es.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /project/public/assets/scss/application.scss: -------------------------------------------------------------------------------- 1 | 2 | html, body{ 3 | height:100%; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /project/public/assets/stylesheets/application.min.css: -------------------------------------------------------------------------------- 1 | html,body{height:100%}/*# sourceMappingURL=application.min.css.map */ 2 | -------------------------------------------------------------------------------- /project/public/assets/images/advanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenzelCode/Advanced/HEAD/project/public/assets/images/advanced.png -------------------------------------------------------------------------------- /project/public/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenzelCode/Advanced/HEAD/project/public/assets/images/favicon.png -------------------------------------------------------------------------------- /tests/template/cache/mail/test.php: -------------------------------------------------------------------------------- 1 | New template created on file /Applications/XAMPP/xamppfiles/framework/tests/body/template/views/mail/test.tpl -------------------------------------------------------------------------------- /micro-advanced/resources/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": { 3 | "default": "en", 4 | "list": ["en", "es"] 5 | } 6 | } -------------------------------------------------------------------------------- /project/template/cache/templates/footer.php: -------------------------------------------------------------------------------- 1 | New template created on file /Users/denzelcode/Documents/Code/PHP/Advanced/project/template/views/templates/footer.atpl -------------------------------------------------------------------------------- /project/template/cache/templates/header.php: -------------------------------------------------------------------------------- 1 | New template created on file /Users/denzelcode/Documents/Code/PHP/Advanced/project/template/views/templates/header.atpl -------------------------------------------------------------------------------- /project/template/cache/templates/index.php: -------------------------------------------------------------------------------- 1 | New template created on file /Users/denzelcode/Documents/Code/PHP/Advanced/project/template/views/templates/index.atpl -------------------------------------------------------------------------------- /project/resources/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": { 3 | "name": "Advanced Framework", 4 | "cdn": "{@url}/assets" 5 | }, 6 | "sign_up": { 7 | "user": [] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | AddDefaultCharset UTF-8 2 | 3 | 4 | RewriteEngine On 5 | 6 | RewriteRule ^$ project/public/ [L] 7 | RewriteRule (.*) project/public/$1 [L] 8 | 9 | -------------------------------------------------------------------------------- /tests/resources/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "user": [] 4 | }, 5 | "database": { 6 | "host": "127.0.0.1", 7 | "port": 3306, 8 | "username": "root", 9 | "password": "", 10 | "database": "unittesting", 11 | "setup": true 12 | } 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # NodeJS 2 | /node_modules/* 3 | 4 | # /project/* 5 | /tests/resources/config/mailer.json 6 | 7 | # Common IDEs 8 | .idea/ 9 | nbproject/* 10 | 11 | # Windows image file caches 12 | Thumbs.db 13 | 14 | # Folder config file 15 | Desktop.ini 16 | 17 | # Mac crap 18 | .DS_Store 19 | /nbproject/private/ 20 | 21 | # Sphinx-doc 22 | /docs/build/ 23 | !/docs/requirements.txt 24 | 25 | # Composer 26 | vendor/* 27 | composer.lock 28 | 29 | # Travis files 30 | test_data/* 31 | 32 | # Doxygen 33 | Documentation/* 34 | 35 | # PHPUnit 36 | /.phpunit.result.cache 37 | 38 | # php-cs-fixer 39 | /.php_cs.cache 40 | -------------------------------------------------------------------------------- /micro-advanced/template/cache/main/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {@title} - {@name} 8 | 9 | 10 | 11 | {@name} 12 |

Advanced Framework

13 |

get('template.welcome.description') ?>

14 | 15 | -------------------------------------------------------------------------------- /micro-advanced/template/views/main/index.atpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {@title} - {@name} 8 | 9 | 10 | 11 | {@name} 12 |

Advanced Framework

13 |

{#= $advancedLanguage->get('template.welcome.description') #}

14 | 15 | -------------------------------------------------------------------------------- /tests/unit/account/AuthTest.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | # RewriteCond %{HTTP:Authorization} . 10 | # RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect trailing slashes if not a folder 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Handle router 18 | RewriteCond %{REQUEST_FILENAME} !-f 19 | RewriteCond %{REQUEST_FILENAME} !-d 20 | RewriteCond %{REQUEST_FILENAME} !-l 21 | RewriteRule ^ index.php [L] 22 | -------------------------------------------------------------------------------- /micro-advanced/exceptions/UserException.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | ./tests/unit 15 | 16 | 17 | 18 | ./tests/feature 19 | 20 | 21 | 22 | 23 | ./app 24 | 25 | 26 | -------------------------------------------------------------------------------- /project/Project.php: -------------------------------------------------------------------------------- 1 | table}"; 32 | 33 | return $query; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Truncate.php: -------------------------------------------------------------------------------- 1 | table}"; 32 | 33 | return $query; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /project/public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "denzelcode/advanced", 3 | "type": "project", 4 | "description": "Advanced microFramework - Create more by doing less", 5 | "keywords": [ 6 | "framework", 7 | "advanced", 8 | "micro", 9 | "microframework", 10 | "micro-advanced" 11 | ], 12 | "license": "LGPL-3.0", 13 | "authors": [ 14 | { 15 | "name": "Denzel Giraldo (Denzel Code)", 16 | "email": "denzelcodedev@gmail.com" 17 | } 18 | ], 19 | "autoload": { 20 | "psr-4": { 21 | "advanced\\": "micro-advanced/", 22 | "project\\": "project/" 23 | }, 24 | "exclude-from-classmap": [ 25 | "/samples" 26 | ] 27 | }, 28 | "autoload-dev": { 29 | "psr-4": { 30 | "tests\\": "tests/" 31 | } 32 | }, 33 | "require": { 34 | "php": "^7.2", 35 | "phpmailer/phpmailer": "^6.1", 36 | "symfony/yaml": "^5.1" 37 | }, 38 | "require-dev": { 39 | "phpunit/phpunit": "^9" 40 | }, 41 | "config": { 42 | "optimize-autoloader": true 43 | }, 44 | "archive": { 45 | "exclude": [ 46 | "/samples" 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /micro-advanced/session/IManager.php: -------------------------------------------------------------------------------- 1 | assertTrue($send); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /micro-advanced/mailer/Attachment.php: -------------------------------------------------------------------------------- 1 | path = $path; 38 | $this->name = $name; 39 | } 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getPath() : string { 45 | return $this->path; 46 | } 47 | 48 | /** 49 | * @return string 50 | */ 51 | public function getName() : string { 52 | return $this->name; 53 | } 54 | } -------------------------------------------------------------------------------- /micro-advanced/config/provider/JsonProvider.php: -------------------------------------------------------------------------------- 1 | name = $name; 40 | $this->mail = $mail; 41 | } 42 | 43 | /** 44 | * Get person name. 45 | * 46 | * @return string 47 | */ 48 | public function getName() : string { 49 | return $this->name; 50 | } 51 | 52 | /** 53 | * Get person mail. 54 | * 55 | * @return string 56 | */ 57 | public function getMail() : string { 58 | return $this->mail; 59 | } 60 | } -------------------------------------------------------------------------------- /micro-advanced/config/provider/IProvider.php: -------------------------------------------------------------------------------- 1 | createUser([ 38 | "username" => "dsdxzzx", 39 | "password" => Auth::hash("testing"), 40 | "mail" => "testing@example.com", 41 | "account_created" => time(), 42 | "ip_reg" => Request::getIp(), 43 | "ip_last" => Request::getIp(), 44 | "gender" => "M", 45 | "last_used" => time() 46 | ]); 47 | 48 | $this->assertTrue(true); 49 | } 50 | } -------------------------------------------------------------------------------- /tests/resources/config/database.json: -------------------------------------------------------------------------------- 1 | { 2 | "import": { 3 | "users": { 4 | "id": "int(11) PRIMARY KEY AUTO_INCREMENT", 5 | "username": "varchar(125)", 6 | "firstname": "varchar(255)", 7 | "lastname": "varchar(255)", 8 | "password": "varchar(255)", 9 | "mail": "varchar(255)", 10 | "rank": "int(11)", 11 | "country": "varchar(4)", 12 | "gender": "enum('M', 'F') DEFAULT 'M'", 13 | "account_created": "double(50, 0) DEFAULT 0", 14 | "last_used": "double(50, 0) DEFAULT 0", 15 | "last_online": "double(50, 0) DEFAULT 0", 16 | "last_password": "double(50, 0) DEFAULT 0", 17 | "online": "enum('0', '1') DEFAULT '0'", 18 | "ip_reg": "varchar(45) NOT NULL", 19 | "ip_last": "varchar(45) NOT NULL", 20 | "language": "varchar(255) DEFAULT 'en'", 21 | "connection_id": "text", 22 | "birth_date": "varchar(55)", 23 | "facebook_id": "text", 24 | "facebook_token": "text", 25 | "facebook_account": "boolean DEFAULT false" 26 | }, 27 | "ranks": { 28 | "id": "int(11) PRIMARY KEY AUTO_INCREMENT", 29 | "name": "text", 30 | "description": "text", 31 | "timestamp": "double(50, 0) DEFAULT 0" 32 | }, 33 | "tests": { 34 | "id": "int(11) PRIMARY KEY AUTO_INCREMENT", 35 | "result": "varchar(255)", 36 | "timestamp": "double(50, 0) DEFAULT 0" 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /micro-advanced/config/provider/YamlProvider.php: -------------------------------------------------------------------------------- 1 | $value) { 37 | $pop[$key] = $value; 38 | } 39 | 40 | return $pop; 41 | } 42 | 43 | /** 44 | * Get parameters. 45 | * 46 | * @return array 47 | */ 48 | public static function getParameters() : array { 49 | return self::$params; 50 | } 51 | 52 | /** 53 | * Populate data. 54 | * 55 | * @param boolean $common 56 | * @return void 57 | */ 58 | private static function populate() { 59 | $body = $_GET; 60 | 61 | foreach ($body as $key => $value) { 62 | self::$params[$key] = $value; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /micro-advanced/utils/ExecutionTime.php: -------------------------------------------------------------------------------- 1 | startTime = microtime(true); 44 | } 45 | 46 | /** 47 | * Stop counting process time. 48 | * 49 | * @return void 50 | */ 51 | public function end() : void { 52 | $this->endTime = microtime(true); 53 | } 54 | 55 | /** 56 | * Print execution time. 57 | * 58 | * @return void 59 | */ 60 | public function print() : void { 61 | print($this); 62 | } 63 | 64 | /** 65 | * @return string 66 | */ 67 | public function __toString() : string { 68 | return Bootstrap::getMainLanguage()->get("execution_time", null, $this->endTime - $this->startTime); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /micro-advanced/user/auth/IAuth.php: -------------------------------------------------------------------------------- 1 | $value) { 38 | $pop[$key] = $value; 39 | } 40 | 41 | return $pop; 42 | } 43 | 44 | /** 45 | * Get parameters. 46 | * 47 | * @return array 48 | */ 49 | public static function getParameters() : array { 50 | return self::$params; 51 | } 52 | 53 | /** 54 | * Populate data. 55 | * 56 | * @param boolean $common 57 | * @return void 58 | */ 59 | private static function populate(bool $common = true) { 60 | $body = file_get_contents('php://input'); 61 | 62 | $body = json_decode($body, true); 63 | 64 | if ($common) $body = $_POST; 65 | 66 | foreach ($body as $key => $value) { 67 | self::$params[$key] = $value; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /project/controllers/mainController.php: -------------------------------------------------------------------------------- 1 | = 1000000000000) { 33 | $num = substr($number, 1, -11); 34 | $sec = strlen($num) - 1; 35 | if ($num[$sec] > 0) $num = "." . $num[$sec]; else $num = null; 36 | $return = number_format(substr($number, 0, -12)) . $num . "B"; 37 | } else if ($number >= 1000000000) { 38 | $num = substr($number, 1, -8); 39 | $sec = strlen($num) - 1; 40 | if ($num[$sec] > 0) $num = "." . $num[$sec]; else $num = null; 41 | $return = number_format(substr($number, 0, -9)) . $num . "k M"; 42 | } else if ($number >= 1000000) { 43 | $num = substr($number, 1, -5); 44 | $sec = strlen($num) - 1; 45 | if ($num[$sec] > 0) $num = "." . $num[$sec]; else $num = null; 46 | $return = number_format(substr($number, 0, -6)) . $num . "M"; 47 | } else if ($number >= 1000) { 48 | $num = substr($number, 1, -2); 49 | $sec = strlen($num) - 1; 50 | if ($num[$sec] > 0) $num = "." . $num[$sec]; else $num = null; 51 | $return = number_format(substr($number, 0, -3)) . $num . "k"; 52 | } else $return = number_format($number); 53 | 54 | return $return; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/unit/data/ConfigTest.php: -------------------------------------------------------------------------------- 1 | [], 30 | 31 | "update" => [] 32 | ]); 33 | 34 | $table = [ 35 | 'id' => 'int(11) PRIMARY KEY AUTO_INCREMENT', 36 | "result" => "varchar(255)", 37 | 'timestamp' => "double(50, 0) DEFAULT 0" 38 | ]; 39 | 40 | $config->set("import.tests", $table); 41 | 42 | $config->save(); 43 | 44 | $this->assertEquals($table, $config->get("import.tests")); 45 | } 46 | 47 | public function testDeleteGetConfiguration() : void { 48 | $config = new Config(Project::getConfigPath()); 49 | 50 | $config->set("test.delete", true); 51 | 52 | $config->save(); 53 | 54 | $config->delete("test.delete"); 55 | 56 | $this->assertEmpty($config->get("test.delete")); 57 | } 58 | 59 | public function testHasConfiguration() : void { 60 | $config = new Config(Project::getConfigPath()); 61 | 62 | $config->set("test.has", true); 63 | 64 | $config->save(); 65 | 66 | $this->assertTrue($config->get("test.has")); 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Delete.php: -------------------------------------------------------------------------------- 1 | table}"; 65 | 66 | $query .= !empty($this->where) ? " WHERE {$this->where}" : ""; 67 | 68 | $query .= $this->limit > 0 ? " LIMIT {$this->limit}" : ""; 69 | 70 | return $query; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /environment.php: -------------------------------------------------------------------------------- 1 | init(); 70 | } 71 | 72 | self::$initialized = true; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/ShowColumns.php: -------------------------------------------------------------------------------- 1 | prepare; 41 | } 42 | 43 | /** 44 | * Fetch all the results. 45 | * 46 | * @return array 47 | */ 48 | public function fetchAll() : array { 49 | return $this->execute()->fetchAll(); 50 | } 51 | 52 | /** 53 | * Fetch the first result false if is a bad query. 54 | * 55 | * @return array 56 | */ 57 | public function fetch() : array { 58 | return ($this->execute()->fetch() ?? []); 59 | } 60 | 61 | /** 62 | * @param string $like 63 | * @return ShowColumns 64 | */ 65 | public function like(string $like) : ShowColumns { 66 | $this->like = $like; 67 | 68 | $this->execute[] = $like; 69 | 70 | return $this; 71 | } 72 | 73 | /** 74 | * Generate the query string of the object. 75 | * 76 | * @return string 77 | */ 78 | public function toQuery() : string { 79 | $query = "SHOW COLUMNS FROM {$this->table}"; 80 | 81 | $query .= !empty($this->like) ? "LIKE ?" : ""; 82 | 83 | return $query; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /micro-advanced/config/IConfig.php: -------------------------------------------------------------------------------- 1 | format; 46 | } 47 | 48 | /** 49 | * @param string $format 50 | * @return void 51 | */ 52 | public function setFormat(string $format) { 53 | $this->format = $format; 54 | } 55 | 56 | /** 57 | * Get how much time ago passed since this date. 58 | * 59 | * @return string 60 | */ 61 | public function getAgo() : string { 62 | $time = (new DateTime())->getTimestamp() - $this->getTimestamp(); 63 | 64 | $lang = Bootstrap::getLanguage(false)->get("time.ago"); 65 | 66 | if ($time < 1) return $lang["just_now"]; 67 | 68 | $string = [365 * 24 * 60 * 60 => "year", 30 * 24 * 60 * 60 => "month", 24 * 60 * 60 => "day", 60 * 60 => "hour", 60 => "minute", 1 => "second"]; 69 | 70 | foreach ($string as $seconds => $str) { 71 | $d = $time / $seconds; 72 | 73 | if ($d >= 1) { 74 | $r = round($d); 75 | 76 | return $r . " " . ($r > 1 ? $lang["plural"][$str] : $lang["singular"][$str]) . " " . $lang["ago"]; 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /micro-advanced/exceptions/Exception.php: -------------------------------------------------------------------------------- 1 | code = $code; 57 | $this->message_code = $message; 58 | $this->parameters = $parameters; 59 | $this->message = $this->getTranslatedMessage(); 60 | } 61 | 62 | /** 63 | * Get parameters. 64 | * 65 | * @return array|null 66 | */ 67 | public function getParameters() : ?array { 68 | return $this->parameters; 69 | } 70 | 71 | /** 72 | * Translate message. 73 | * 74 | * @return string 75 | */ 76 | public function getTranslatedMessage() : string { 77 | $arguments = [$this->message_code, null]; 78 | 79 | foreach ($this->getParameters() as $parameter) $arguments[] = $parameter; 80 | 81 | $language = $this->getLanguage(); 82 | 83 | $language->getConfig()->setIfNotExists($this->message_code, Bootstrap::getMainLanguage()->get("exception.created", $language->getName()))->saveIfModified(); 84 | 85 | $return = @call_user_func_array([ $language, "get" ], $arguments); 86 | 87 | return $return ?? $this->message_code; 88 | } 89 | 90 | abstract function getLanguage() : Language; 91 | } 92 | -------------------------------------------------------------------------------- /micro-advanced/sql/ISQL.php: -------------------------------------------------------------------------------- 1 | response = Bootstrap::getResponse(); 42 | 43 | $this->request = Request::getInstance(); 44 | } 45 | 46 | /** 47 | * Create URL /index or / and let ALL methods request. 48 | * 49 | * @param string $method 50 | * @return string 51 | */ 52 | public function index(string $method = Request::ALL) : string { 53 | $webConfig = Bootstrap::getConfig()->get('web'); 54 | 55 | TemplateProvider::setParameters([ 56 | "title" => Bootstrap::getMainLanguage()->get("general.description"), 57 | "name" => $webConfig["name"], 58 | "cdn" => $webConfig["cdn"] 59 | ]); 60 | 61 | return TemplateProvider::getRootTemplate('main/index'); 62 | } 63 | 64 | abstract public function error404(string $method = Request::ALL) : string; 65 | 66 | /** 67 | * Set response code. 68 | * 69 | * @param integer $code 70 | * @return void 71 | */ 72 | protected function setResponseCode(int $code) : void { 73 | $this->response->setCode($code); 74 | } 75 | 76 | /** 77 | * Get response Object. 78 | * 79 | * @return Response 80 | */ 81 | protected function getResponse() : Response { 82 | return $this->response; 83 | } 84 | 85 | /** 86 | * Get response Object. 87 | * 88 | * @return Request 89 | */ 90 | protected function getRequest() : Request { 91 | return $this->request; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Advanced](https://github.com/DenzelCode/Advanced/blob/master/project/public/assets/images/advanced.png?raw=true) 2 | 3 | ## What's Advanced? 4 | 5 | Advanced Micro Framework - Create more by doing less 6 | 7 | Advanced Micro Framework is a PHP Object Oriented framework that make your life easier, advanced provides you a whole bunch of functionalities that you will not have the need of write a lot of code. It is already predefined so you only have to create your project and use the internal libraries of Advanced such as the authentications (login/register), In-code routing by controllers, SQL automatization (generate queries and execute them in a safe way with just PHP code), and more. 8 | 9 | Get started with Advanced and see what else it can provide you. 10 | 11 | [Get started](https://github.com/DenzelCode/Advanced/wiki/Get-started) 12 | 13 | ## Discussion/Help 14 | 15 | - [Discord](https://discord.gg/T7PsB5z) 16 | - [StackOverflow](https://stackoverflow.com/tags/advanced-framework) 17 | 18 | ## Sample projects 19 | 20 | [Advanced-Samples](https://github.com/DenzelCode/Advanced-Samples) 21 | 22 | ## Documentation 23 | 24 | [Click here to go to the documentation](https://github.com/DenzelCode/Advanced/wiki/Get-started) 25 | 26 | ## Installation 27 | 28 | Composer: 29 | 30 | ``` 31 | mkdir new-folder 32 | 33 | cd new-folder 34 | 35 | composer create-project denzelcode/advanced . 36 | 37 | cd project/public 38 | 39 | php -S localhost:8000 40 | ``` 41 | 42 | **THIS IS IMPORTANT** 43 | If Advanced file system is not working properly remember to add writing and reading permissions to the directory where you want to install the framework! 44 | 45 | Linux/Mac OS (Unix): 46 | 47 | ``` 48 | sudo chmod -R 777 new-folder 49 | ``` 50 | 51 | Windows: 52 | 53 | ``` 54 | CACLS new-folder /e /p Everyone:R 55 | CACLS new-folder /e /p Everyone:W 56 | ``` 57 | 58 | ## Requirements 59 | 60 | - PHP 7.2.0 61 | - Apache Server 62 | 63 | Xampp [Windows](https://www.apachefriends.org/xampp-files/7.4.2/xampp-windows-x64-7.4.2-0-VC15-installer.exe) | [Linux](https://www.apachefriends.org/xampp-files/7.4.2/xampp-linux-x64-7.4.2-0-installer.run) | [OS X](https://www.apachefriends.org/xampp-files/7.4.2/xampp-osx-7.4.2-0-vm.dmg), **IIS** or **Hosting** 64 | 65 | Postdata: To use **IIS** you are required to set the /project/public path as the root directory. 66 | 67 | ## Contributors 68 | 69 | - Denzel Code (Advanced main developer) 70 | - Soull Darknezz 71 | - mamazu 72 | 73 | ## Licensing information 74 | 75 | This project is licensed under LGPL-3.0. Please see the [LICENSE](/LICENSE) file for details. 76 | 77 | ## Donations 78 | 79 | - [PayPal](https://paypal.me/DenzelGiraldo) 80 | 81 | ## Contribution 82 | 83 | Anyone who wants to contribute to the project can do it, this is an independent project that plans to become a community. 84 | -------------------------------------------------------------------------------- /micro-advanced/session/SessionManager.php: -------------------------------------------------------------------------------- 1 | $value) self::set($key, $value); 70 | } 71 | 72 | /** 73 | * Delete session by name. 74 | * 75 | * @param string $name 76 | * @return void 77 | */ 78 | public static function delete(string $name) : void { 79 | unset($_SESSION[$name]); 80 | } 81 | 82 | /** 83 | * Delete session by array 84 | * 85 | * @param array $sessions 86 | * @return void 87 | */ 88 | public static function deleteByArray(array $sessions) : void { 89 | foreach ($sessions as $session) unset($_SESSION[$session]); 90 | } 91 | 92 | /** 93 | * Destroy all the sessions. 94 | * 95 | * @return void 96 | */ 97 | public static function destroy() : void { 98 | session_destroy(); 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /micro-advanced/resources/languages/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "guest": "Guest", 4 | "description": "Create more by doing less" 5 | }, 6 | "exception": { 7 | "created": "Exception message created on language file {0}", 8 | "exception": "Error: {0} file {1} on line {2}", 9 | "user": { 10 | "characters": "Username must have from {0} to {1} characters", 11 | "invalid_name": "Invalid username, try deleting characters or removing special characters", 12 | "invalid_email": "Invalid email address" 13 | }, 14 | "router": { 15 | "method_not_exists": "Method {0} does not exists" 16 | }, 17 | "config": { 18 | "invalid_format": "Config file {0} has an invalid format" 19 | }, 20 | "database": { 21 | "error": "An error occurred on the database: {0}", 22 | "pdo_required": "Advanced require PDO extension", 23 | "connecting": "Error connecting to MySQL Server: {0}", 24 | "needed": "You must set a Database to the Bootstrap to use this feature. Ex: Project::setSQL(new MySQL($host, $port, $username, $password, $database))", 25 | "create_table": "An error occurred creating the table {0}: {1}", 26 | "add_column": "An error ocurred addding a column for the table {0}: {1}", 27 | "modify_column": "An error ocurred modifing a column for the table {0}: {1}" 28 | }, 29 | "file": { 30 | "not_exist": "File {0} does not exists", 31 | "open": "An error occurred opening the file {0}", 32 | "write": "An error occurred writing the file {0}" 33 | }, 34 | "mailer": { 35 | "error": "An error occurred sending the mail: {0}" 36 | } 37 | }, 38 | "error": { 39 | "parameter_not_string": "(Parameter {0} is not a string)" 40 | }, 41 | "template": { 42 | "not_exists": "Template {0} does not exists", 43 | "default": "New template created on file {0}", 44 | "undefined": "Undefined", 45 | "welcome": { 46 | "description": "Advanced Micro Framework - Create more by doing less" 47 | } 48 | }, 49 | "time": { 50 | "ago": { 51 | "just_now": "Just now", 52 | "ago": "ago", 53 | "singular": { 54 | "month": "month", 55 | "week": "week", 56 | "day": "day", 57 | "hour": "hour", 58 | "minute": "minute", 59 | "second": "second" 60 | }, 61 | "plural": { 62 | "month": "months", 63 | "week": "weeks", 64 | "day": "days", 65 | "hour": "hours", 66 | "minute": "minutes", 67 | "second": "seconds" 68 | } 69 | } 70 | }, 71 | "execution_time": "This process delayed {0}s for its execution" 72 | } -------------------------------------------------------------------------------- /micro-advanced/file/UploadFile.php: -------------------------------------------------------------------------------- 1 | file = $file; 40 | } 41 | 42 | /** 43 | * Get file name. 44 | * 45 | * @return string 46 | */ 47 | public function getName() : string { 48 | return $this->file["name"]; 49 | } 50 | 51 | /** 52 | * Get file name without extension. 53 | * 54 | * @return string 55 | */ 56 | public function getNameWithoutExtension() : string { 57 | $name = explode(".", $this->getName()); 58 | 59 | unset($name[(count($name) - 1)]); 60 | 61 | return implode(".", $name); 62 | } 63 | 64 | /** 65 | * Get file extension. 66 | * 67 | * @return string 68 | */ 69 | public function getExtension() : string { 70 | return end(explode(".", $this->getName())); 71 | } 72 | 73 | /** 74 | * Get file temporary name. 75 | * 76 | * @return string 77 | */ 78 | public function getTemporaryName() : string { 79 | return $this->file["tmp_name"]; 80 | } 81 | 82 | /** 83 | * Get file type. 84 | * 85 | * @return string 86 | */ 87 | public function getType() : string { 88 | return $this->file["type"]; 89 | } 90 | 91 | /** 92 | * Get file size. 93 | * 94 | * @return integer 95 | */ 96 | public function getSize(): int { 97 | return $this->file["size"]; 98 | } 99 | 100 | /** 101 | * Get file error. 102 | * 103 | * @return integer 104 | */ 105 | public function getError(): int { 106 | return $this->file["error"]; 107 | } 108 | 109 | /** 110 | * Upload file. 111 | * 112 | * @param string $path The path where you want to put the file. 113 | * @return boolean 114 | */ 115 | public function upload(string $path): bool { 116 | return move_uploaded_file($this->getTemporaryName(), $path); 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /micro-advanced/session/CookieManager.php: -------------------------------------------------------------------------------- 1 | $value) self::set($key, $value, $cookie, $time, $directory); 75 | } 76 | 77 | /** 78 | * Delete cookie by name. 79 | * 80 | * @param string $name 81 | * @param string $directory 82 | * @return void 83 | */ 84 | public static function delete(string $name, string $directory = "/") : void { 85 | setcookie($name, null, time() - 1000, $directory); 86 | } 87 | 88 | /** 89 | * Delete cookie by array 90 | * 91 | * @param array $cookies 92 | * @param string $directory 93 | * @return void 94 | */ 95 | public static function deleteByArray(array $cookies, string $directory = "/") : void { 96 | foreach ($sessions as $session) setcookie($session, null, time() - 1000, $directory); 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /micro-advanced/resources/languages/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "guest": "Huésped", 4 | "description": "Haciendo tu vida en PHP mas fácil" 5 | }, 6 | 7 | "exception": { 8 | "created": "Exception message created on language file {0}", 9 | "exception": "Error: {0} en el archivo {1} en la linea {2}", 10 | 11 | "router": { 12 | "method_not_exists": "El metodo {0} no existe" 13 | }, 14 | 15 | "user": { 16 | "characters": "El nombre de usuario debe tener de {0} a {1} caracteres", 17 | "invalid_name": "Nombre de usuario inválido, elimina los caracteres especiales", 18 | "invalid_email": "Correo electrónico inválido" 19 | }, 20 | 21 | "config": { 22 | "invalid_format": "El archivo de configuracion {0} tiene un formato invalido" 23 | }, 24 | 25 | "database": { 26 | "error": "Ha ocurrido un error en la base de datos: {0}", 27 | "pdo_required": "Advanced requiere la extension PDO", 28 | "connecting": "Error conectando a el servidor MySQL: {0}", 29 | "needed": "Debes configurar un Database en el Bootstrap para poder usar esta característica. Ej: Project::setSQL(new MySQL($host, $port, $username, $password, $database))", 30 | "create_table": "Ha ocurrido un error creando la tabla {0}: {1}", 31 | "add_column": "Ha ocurrido un error agregando una columna a la tabla {0}: {1}", 32 | "modify_column": "Ha ocurrido un error modificando una columna en la tabla {0}: {1}" 33 | }, 34 | 35 | "file": { 36 | "not_exist":"El archivo {0} no existe", 37 | "open": "Ha ocurrido un error abriendo el archivo {0}", 38 | "write": "Ha ocurrido un error modificando el archivo {0}" 39 | }, 40 | 41 | "mailer": { 42 | "error": "Ha ocurrido un error enviando el correo electrónico: {0}" 43 | } 44 | }, 45 | 46 | "error": { 47 | "parameter_not_string": "(El parametro {0} no es un string)" 48 | }, 49 | 50 | "template": { 51 | "not_exists": "Plantilla {0} no existente", 52 | "default": "Nueva plantilla creada en el archivo {0}", 53 | "undefined": "Indefinido", 54 | 55 | "welcome": { 56 | "description": "Advanced Micro Framework - Crea más haciendo menos" 57 | } 58 | }, 59 | 60 | "time": { 61 | "ago": { 62 | "just_now": "Hace un momento", 63 | "ago": "", 64 | 65 | "singular": { 66 | "month": "mes", 67 | "week": "semana", 68 | "day": "dia", 69 | "hour": "hora", 70 | "minute": "minuto", 71 | "second": "segundo" 72 | }, 73 | 74 | "plural": { 75 | "month": "meses", 76 | "week": "semanas", 77 | "day": "días", 78 | "hour": "horas", 79 | "minute": "minutos", 80 | "second": "segundos" 81 | } 82 | } 83 | }, 84 | 85 | "execution_time": "Este proceso tardó {0}s para completarse\n" 86 | } -------------------------------------------------------------------------------- /micro-advanced/sql/query/DropColumns.php: -------------------------------------------------------------------------------- 1 | columns[] = $column; 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * Set a column that you want to drop by string. 41 | * 42 | * @param string $column 43 | * @return DropColumns 44 | */ 45 | public function column(string $column) : DropColumns { 46 | $this->setColumn($column); 47 | 48 | return $this; 49 | } 50 | 51 | /** 52 | * Set the columns list that you want to drop by array. 53 | * 54 | * @param array $columns 55 | * @return DropColumns 56 | */ 57 | public function setColumnsByArray(array $columns) : DropColumns { 58 | foreach ($columns as $key => $value) $this->setColumn($key, $value); 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * Set the columns list that you want to drop by array. 65 | * 66 | * @param array $columns 67 | * @return DropColumns 68 | */ 69 | public function columns(array $columns) : DropColumns { 70 | $this->setColumnsByArray($columns); 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * Set the columns list that you want to drop by array. 77 | * 78 | * @param array $datcolumnsa 79 | * @return DropColumns 80 | */ 81 | public function setColumns(array $columns) : DropColumns { 82 | $this->setColumnsByArray($columns); 83 | 84 | return $this; 85 | } 86 | 87 | /** 88 | * Execute the query 89 | * 90 | * @return boolean 91 | */ 92 | public function execute() { 93 | $this->execute = $this->columns; 94 | 95 | return parent::execute(); 96 | } 97 | 98 | /** 99 | * Generate the query string of the object 100 | * 101 | * @return string 102 | */ 103 | public function toQuery() : string { 104 | $query = "ALTER TABLE {$this->table}"; 105 | 106 | for ($i = 0; $i < count($this->columns); $i++) $query .= $i != (count($this->columns) == 1) ? " DROP COLUMN {$this->columns[$i]};" : ($i == 0 ? " DROP COLUMN {$this->columns[$i]}, " : ($i != (count($this->columns) != 1) ? "DROP COLUMN {$this->columns[$i]}, " : "DROP COLUMN {$this->columns[$i]};")); 107 | 108 | return $query; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Insert.php: -------------------------------------------------------------------------------- 1 | fields[] = $field; 47 | 48 | $this->values[] = $value; 49 | 50 | $this->execute[] = $value; 51 | 52 | return $this; 53 | } 54 | 55 | /** 56 | * Set the column name and the value that you want to asign to the row. 57 | * 58 | * @param string $field 59 | * @param mixed $value 60 | * @return Insert 61 | */ 62 | public function field(string $field, $value) : Insert { 63 | return $this->setField($field, $value); 64 | } 65 | 66 | /** 67 | * Set the column name and the value that you want to asign to the row bu array. 68 | * 69 | * @param array $fields 70 | * @return Insert 71 | */ 72 | public function setFieldsByArray(array $fields) : Insert { 73 | foreach ($fields as $key => $value) $this->setField($key, $value); 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * Set the column name and the value that you want to asign to the row bu array. 80 | * 81 | * @param array $fields 82 | * @return Insert 83 | */ 84 | public function fields(array $fields) : Insert { 85 | return $this->setFieldsByArray($fields); 86 | } 87 | 88 | /** 89 | * Set the column name and the value that you want to asign to the row bu array. 90 | * 91 | * @param array $fields 92 | * @return Insert 93 | */ 94 | public function setFields(array $fields) : Insert { 95 | return $this->setFieldsByArray($fields); 96 | } 97 | 98 | /** 99 | * Generate the query string of the object. 100 | * 101 | * @return string 102 | */ 103 | public function toQuery() : string { 104 | $query = "INSERT INTO {$this->table} ("; 105 | 106 | foreach ($this->fields as $i => $field) $query .= $i != (count($this->fields) - 1) ? "{$field}, " : $field; 107 | 108 | $query .= ") VALUES ("; 109 | 110 | for ($i = 0; $i < count($this->values); $i++) $query .= $i != (count($this->values) - 1) ? "?, " : "?"; 111 | 112 | $query .= ")"; 113 | 114 | return $query; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Create.php: -------------------------------------------------------------------------------- 1 | columns[] = $column; 46 | 47 | $this->types[] = $value; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * Set a column that you want to add. 54 | * 55 | * @param string $column 56 | * @param mixed $value 57 | * @return Create 58 | */ 59 | public function column(string $column, $value) : Create { 60 | $this->setColumn($column, $value); 61 | 62 | return $this; 63 | } 64 | 65 | /** 66 | * Set the columns that you want to add by array. 67 | * 68 | * @param array $columns 69 | * @return Create 70 | */ 71 | public function setColumnsByArray(array $columns) : Create { 72 | foreach ($columns as $key => $value) $this->setColumn($key, $value); 73 | 74 | return $this; 75 | } 76 | 77 | /** 78 | * Set the columns that you want to add by array. 79 | * 80 | * @param array $columns 81 | * @return Create 82 | */ 83 | public function columns(array $columns) : Create { 84 | $this->setColumnsByArray($columns); 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Create a column named "id" as primary key with auto increment. 91 | * 92 | * @return Create 93 | */ 94 | public function id(): Create { 95 | return $this->setColumn("id", "int(11) PRIMARY KEY AUTO_INCREMENT"); 96 | } 97 | 98 | /** 99 | * Set the columns that you want to add by array. 100 | * 101 | * @param array $columns 102 | * @return Create 103 | */ 104 | public function setColumns(array $columns) : Create { 105 | $this->setColumnsByArray($columns); 106 | 107 | return $this; 108 | } 109 | 110 | /** 111 | * Convert object to query. 112 | * 113 | * @return string 114 | */ 115 | public function toQuery() : string { 116 | $query = "CREATE TABLE IF NOT EXISTS {$this->table} ( "; 117 | 118 | for ($i = 0; $i < count($this->columns); $i++) $query .= $i != (count($this->columns) - 1) ? "{$this->columns[$i]} {$this->types[$i]}, " : "{$this->columns[$i]} {$this->types[$i]} "; 119 | 120 | $query .= ")"; 121 | 122 | return $query; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /micro-advanced/file/Directory.php: -------------------------------------------------------------------------------- 1 | path = $directory; 24 | 25 | $this->path = str_replace("\\", DIRECTORY_SEPARATOR, $this->path); 26 | $this->path = str_replace("/", DIRECTORY_SEPARATOR, $this->path); 27 | 28 | $directories = explode(DIRECTORY_SEPARATOR, $this->path); 29 | 30 | $this->name = end($directories); 31 | } 32 | 33 | /** 34 | * Get directory name. 35 | * 36 | * @return string 37 | */ 38 | public function getName() : string { 39 | return $this->name; 40 | } 41 | 42 | /** 43 | * Set directory name. 44 | * 45 | * @param string $name 46 | * @return void 47 | */ 48 | public function setName(string $name): void { 49 | rename($this->path, dirname($this->path) . DIRECTORY_SEPARATOR . $name); 50 | 51 | $this->name = $name; 52 | } 53 | 54 | /** 55 | * Change directory path. 56 | * 57 | * @param string $path 58 | * @return void 59 | */ 60 | public function setPath(string $path): void { 61 | rename($this->path, $path); 62 | 63 | $this->path = $path; 64 | 65 | $this->name = end(explode(DIRECTORY_SEPARATOR, $this->path)); 66 | } 67 | 68 | /** 69 | * Get directory path. 70 | * 71 | * @return string 72 | */ 73 | public function getPath() : string { 74 | return $this->path; 75 | } 76 | 77 | /** 78 | * Get directory permissions. 79 | * 80 | * @return integer 81 | */ 82 | public function getPermission(): int { 83 | return fileperms($this->path); 84 | } 85 | 86 | /** 87 | * Set directory permissions. 88 | * 89 | * @param integer $permission 90 | * @return void 91 | */ 92 | public function setPermission(int $permission): void { 93 | chmod($this->path, $permission); 94 | } 95 | 96 | /** 97 | * Check if directory exists. 98 | * 99 | * @return boolean 100 | */ 101 | public function exists(): bool { 102 | return is_dir($this->path); 103 | } 104 | 105 | /** 106 | * Create direcrtory if not exists. 107 | * 108 | * @param integer $permission 109 | * @return void 110 | */ 111 | public function create(int $permission = 0777): void { 112 | if ($this->exists()) return; 113 | 114 | $directories = explode(DIRECTORY_SEPARATOR, $this->path); 115 | 116 | $str = ""; 117 | 118 | foreach ($directories as $key => $dir) { 119 | if (empty($dir)) continue; 120 | 121 | $str .= (empty($str) && \strpos($dir, ":") ? $dir : DIRECTORY_SEPARATOR . $dir); 122 | 123 | if (!file_exists($str)) @mkdir($str, $permission); 124 | } 125 | } 126 | 127 | /** 128 | * Delete directory. 129 | * 130 | * @return boolean 131 | */ 132 | public function delete(): bool { 133 | $class_func = array(__CLASS__, __FUNCTION__); 134 | 135 | return is_file($this->path) ? @unlink($this->path) : array_map($class_func, glob($this->path.'/*')) == @rmdir($this->path); 136 | } 137 | } -------------------------------------------------------------------------------- /micro-advanced/sql/query/AddColumns.php: -------------------------------------------------------------------------------- 1 | columns[] = $column; 44 | 45 | $this->values[] = $value; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * Set a column that you want to add. 52 | * 53 | * @param string $column 54 | * @param string $value 55 | * @return AddColumns 56 | */ 57 | public function column(string $column, string $value) : AddColumns { 58 | $this->setColumn($column, $value); 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * Set the columns that you want to add by array. 65 | * 66 | * @param string $column 67 | * @param string $value 68 | * @return AddColumns 69 | */ 70 | public function setColumnsByArray(array $data) : AddColumns { 71 | foreach ($data as $key => $value) $this->setColumn($key, $value); 72 | 73 | return $this; 74 | } 75 | 76 | /** 77 | * Set the columns that you want to add by array. 78 | * 79 | * @param string $column 80 | * @param string $value 81 | * @return AddColumns 82 | */ 83 | public function columns(array $columns) : AddColumns { 84 | $this->setColumnsByArray($columns); 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Set the columns that you want to add by array. 91 | * 92 | * @param string $column 93 | * @param string $value 94 | * @return AddColumns 95 | */ 96 | public function setColumns(array $data) : AddColumns { 97 | $this->setColumnsByArray($data); 98 | 99 | return $this; 100 | } 101 | 102 | /** 103 | * Execute the query. 104 | * 105 | * @return boolean 106 | */ 107 | public function execute() { 108 | $this->execute = array_merge($this->values, $this->execute); 109 | 110 | return parent::execute(); 111 | } 112 | 113 | /** 114 | * Convert object to query. 115 | * 116 | * @return string 117 | */ 118 | public function toQuery() : string { 119 | $query = "ALTER TABLE {$this->table}"; 120 | 121 | for ($i = 0; $i < count($this->columns); $i++) $query .= $i != (count($this->columns) == 1) ? " ADD COLUMN {$this->columns[$i]} {$this->values[$i]};" : ($i == 0 ? " ADD COLUMN {$this->columns[$i]} {$this->values[$i]}, " : ($i != (count($this->columns) != 1) ? "ADD COLUMN {$this->columns[$i]} {$this->values[$i]}, " : "ADD COLUMN {$this->columns[$i]} {$this->values[$i]};")); 122 | 123 | return $query; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/ModifyColumns.php: -------------------------------------------------------------------------------- 1 | columns[] = $column; 44 | 45 | $this->values[] = $value; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * Set a column that you want to modify. 52 | * 53 | * @param string $column 54 | * @param string $value 55 | * @return ModifyColumns 56 | */ 57 | public function column(string $column, string $value) : ModifyColumns { 58 | $this->setColumn($column, $value); 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * Set the columns that you want to modify by array. 65 | * 66 | * @param string $column 67 | * @param string $value 68 | * @return ModifyColumns 69 | */ 70 | public function setColumnsByArray(array $data) : ModifyColumns { 71 | foreach ($data as $key => $value) $this->setColumn($key, $value); 72 | 73 | return $this; 74 | } 75 | 76 | /** 77 | * Set the columns that you want to modify by array. 78 | * 79 | * @param string $column 80 | * @param string $value 81 | * @return ModifyColumns 82 | */ 83 | public function columns(array $columns) : ModifyColumns { 84 | $this->setColumnsByArray($columns); 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Set the columns that you want to modify by array. 91 | * 92 | * @param string $column 93 | * @param string $value 94 | * @return ModifyColumns 95 | */ 96 | public function setColumns(array $data) : ModifyColumns { 97 | $this->setColumnsByArray($data); 98 | 99 | return $this; 100 | } 101 | 102 | /** 103 | * Execute the query. 104 | * 105 | * @return boolean 106 | */ 107 | public function execute() { 108 | $this->execute = array_merge($this->values, $this->execute); 109 | 110 | return parent::execute(); 111 | } 112 | 113 | /** 114 | * Convert object to query. 115 | * 116 | * @return string 117 | */ 118 | public function toQuery() : string { 119 | $query = "ALTER TABLE {$this->table}"; 120 | 121 | for ($i = 0; $i < count($this->columns); $i++) $query .= $i != (count($this->columns) == 1) ? " MODIFY COLUMN {$this->columns[$i]} {$this->values[$i]};" : ($i == 0 ? " MODIFY COLUMN {$this->columns[$i]} {$this->values[$i]}, " : ($i != (count($this->columns) != 1) ? "MODIFY COLUMN {$this->columns[$i]} {$this->values[$i]}, " : "MODIFY COLUMN {$this->columns[$i]} {$this->values[$i]};")); 122 | 123 | return $query; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Query.php: -------------------------------------------------------------------------------- 1 | sql = $table->getSQL(); 64 | 65 | $this->table = $table; 66 | } 67 | 68 | /** 69 | * Set the LIMIT attribute to the SQL query. 70 | * 71 | * @param int $limit 72 | * @return IQuery 73 | */ 74 | public function setLimit(int $limit) : IQuery { 75 | $this->limit = $limit; 76 | 77 | return $this; 78 | } 79 | 80 | /** 81 | * Set the LIMIT attribute to the SQL query. 82 | * 83 | * @param int $limit 84 | * @return IQuery 85 | */ 86 | public function limit(int $limit) : IQuery { 87 | return $this->setLimit($limit); 88 | } 89 | 90 | /** 91 | * Get the table that you want to modify. 92 | * 93 | * @return ITable 94 | */ 95 | public function getTable() : ?ITable { 96 | return $this->table; 97 | } 98 | 99 | /** 100 | * Set the WHERE SQL parameter. 101 | * 102 | * @param string $where Set where example: "name = ?" or "name = ? AND last = ?". 103 | * @param mixed $execute Set values example "Denzel" or ["Denzel", "Code"]. 104 | * @return IQuery 105 | */ 106 | public function where(string $where, $execute = []) : IQuery { 107 | $this->where = $where; 108 | 109 | if (is_array($execute)) $this->execute = $execute; else $this->execute[] = $execute; 110 | 111 | return $this; 112 | } 113 | 114 | /** 115 | * Execute the query. 116 | * 117 | * @return boolean 118 | */ 119 | public function execute() { 120 | $prepare = $this->sql->prepare($this); 121 | 122 | $this->sql->setLastStatement($prepare); 123 | 124 | $this->prepare = $prepare; 125 | 126 | return $prepare->execute($this->execute); 127 | } 128 | 129 | /** 130 | * @return PDOStatement|null 131 | */ 132 | public function getPrepare() : ?PDOStatement { 133 | return $this->prepare; 134 | } 135 | 136 | /** 137 | * Get error string if there is a problem with the Query. 138 | * 139 | * @return string|null 140 | */ 141 | public function getError() : ?string { 142 | return $this->prepare = null || empty($this->prepare->errorInfo()[2]) ? null : $this->prepare->errorInfo()[2]; 143 | } 144 | 145 | /** 146 | * Generate the query string of the object. 147 | * 148 | * @return string 149 | */ 150 | public abstract function toQuery() : string; 151 | 152 | /** 153 | * @return string 154 | */ 155 | public function __toString() { 156 | return $this->toQuery(); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /tests/unit/data/MySQLTest.php: -------------------------------------------------------------------------------- 1 | setIfNotExists("database", [ 34 | "host" => "127.0.0.1", 35 | "port" => 3306, 36 | "username" => "root", 37 | "password" => "", 38 | "database" => "unittesting" 39 | ])->saveIfModified(); 40 | 41 | Project::setSQL(new MySQL( 42 | $config->get("database.host"), 43 | $config->get("database.port"), 44 | $config->get("database.username"), 45 | $config->get("database.password"), 46 | $config->get("database.database") 47 | )); 48 | } 49 | 50 | public function testCreateTable() : void { 51 | $sql = Project::getSQL(); 52 | 53 | $query = $sql->table("test")->create()->columns([ 54 | "id" => "int(11) PRIMARY KEY AUTO_INCREMENT", 55 | "name" => "varchar(255)" 56 | ]); 57 | 58 | $this->assertTrue($query->execute()); 59 | } 60 | 61 | public function testInsert() : void { 62 | $sql = Project::getSQL(); 63 | 64 | $query = $sql->table("test")->insert()->fields([ 65 | "name" => "Testing" 66 | ]); 67 | 68 | $this->assertTrue($query->execute()); 69 | } 70 | 71 | public function testSelect() : void { 72 | $sql = Project::getSQL(); 73 | 74 | $query = $sql->table("test")->select()->where("name = ?", "Testing")->execute(); 75 | 76 | $data = $query->fetch(); 77 | 78 | $this->assertEquals($data["name"], "Testing"); 79 | } 80 | 81 | public function testUpdate() : void { 82 | $sql = Project::getSQL(); 83 | 84 | $find = "Testing"; 85 | 86 | $execute = $sql->table("test")->update()->field("name", "Replacement")->where("name = ?", $find)->execute(); 87 | 88 | $this->assertTrue($execute); 89 | } 90 | 91 | public function testDelete() : void { 92 | $sql = Project::getSQL(); 93 | 94 | $find = "Replacement"; 95 | 96 | $execute = $sql->table("test")->delete()->where("name = ?", $find)->execute(); 97 | 98 | $this->assertTrue($execute); 99 | } 100 | 101 | public function testAddColumns() : void { 102 | $sql = Project::getSQL(); 103 | 104 | $execute = $sql->table("test")->addColumns()->column("last_name", "varchar(255)")->execute(); 105 | 106 | $this->assertTrue($execute); 107 | } 108 | 109 | public function testDropColumns() : void { 110 | $sql = Project::getSQL(); 111 | 112 | $execute = $sql->table("test")->dropColumns()->column("last_name")->execute(); 113 | 114 | $this->assertTrue($execute); 115 | } 116 | 117 | public function testShowColumns() : void { 118 | $sql = Project::getSQL(); 119 | 120 | $execute = $sql->table("test")->showColumns()->execute(); 121 | 122 | $this->assertIsArray($execute->fetchAll()); 123 | } 124 | 125 | public function testTruncate() : void { 126 | $sql = Project::getSQL(); 127 | 128 | $execute = $sql->table("test")->truncate()->execute(); 129 | 130 | $this->assertTrue($execute); 131 | } 132 | 133 | public function testDropTable() : void { 134 | $sql = Project::getSQL(); 135 | 136 | $execute = $sql->table("test")->drop()->execute(); 137 | 138 | $this->assertTrue($execute); 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Update.php: -------------------------------------------------------------------------------- 1 | fields[] = $field; 77 | 78 | $this->values[] = $value; 79 | 80 | return $this; 81 | } 82 | 83 | /** 84 | * Set the column name and the value that you want to asign to the row. 85 | * 86 | * @param string $field 87 | * @param mixed $value 88 | * @return Update 89 | */ 90 | public function field(string $field, $value) : Update { 91 | return $this->setField($field, $value); 92 | } 93 | 94 | /** 95 | * Set the column name and the value that you want to asign to the row bu array. 96 | * 97 | * @param array $fields 98 | * @return Update 99 | */ 100 | public function setFieldsByArray(array $fields) : Update { 101 | foreach ($fields as $key => $value) $this->setField($key, $value); 102 | 103 | return $this; 104 | } 105 | 106 | /** 107 | * Set the column name and the value that you want to asign to the row bu array. 108 | * 109 | * @param array $fields 110 | * @return Update 111 | */ 112 | public function fields(array $fields) : Update { 113 | return $this->setFieldsByArray($fields); 114 | } 115 | 116 | /** 117 | * Set the column name and the value that you want to asign to the row bu array. 118 | * 119 | * @param array $fields 120 | * @return Update 121 | */ 122 | public function setFields(array $fields) : Update { 123 | return $this->setFieldsByArray($fields); 124 | } 125 | 126 | /** 127 | * Execute the query. 128 | * 129 | * @return boolean 130 | */ 131 | public function execute(): bool { 132 | $this->execute = array_merge($this->values, $this->execute); 133 | 134 | return parent::execute(); 135 | } 136 | 137 | /** 138 | * Generate the query string of the object. 139 | * 140 | * @return string 141 | */ 142 | public function toQuery() : string { 143 | $query = "UPDATE {$this->table} "; 144 | 145 | foreach ($this->fields as $i => $field) $query .= (count($this->fields) == 1) ? "SET {$field} = ? " : ($i == 0 ? "SET {$field} = ?, " : ($i != (count($this->fields) - 1) ? "{$field} = ?, " : "{$field} = ?")); 146 | 147 | $query .= !empty($this->where) ? " WHERE {$this->where}" : ""; 148 | 149 | $query .= $this->limit > 0 ? " LIMIT {$this->limit}" : ""; 150 | 151 | return $query; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /micro-advanced/user/User.php: -------------------------------------------------------------------------------- 1 | authenticate(), put the non-hashed password here. 35 | * @throws UserException 36 | */ 37 | public function __construct(array $data, ?string $password = null) { 38 | $this->data = $data; 39 | 40 | $this->password = $password; 41 | 42 | UserFactory::setup(); 43 | 44 | if (!$this->exists()) { 45 | $config = Bootstrap::getMainConfig(); 46 | 47 | $min = $config->get("sign_up.min_characters", 4); 48 | 49 | $max = $config->get("sign_up.max_characters", 32); 50 | 51 | if (strlen($this->getName()) < $min || strlen($this->getName()) > $max) { 52 | throw new UserException(0, "exception.user.characters", $min, $max); 53 | } if (!self::isValidName($this->getName())) { 54 | throw new UserException(1, "exception.user.invalid_name"); 55 | } else if (!empty($this->getMail()) && !self::isValidMail($this->getMail())) { 56 | throw new UserException(2, "exception.user.invalid_email"); 57 | } else if (!$this->create()) throw new UserException(3, "exception.database.error", Bootstrap::getSQL()->getLastError()); 58 | } 59 | 60 | $fetch = UserFactory::getProvider()->getAll($this); 61 | 62 | if ($fetch) $this->data = $fetch; 63 | } 64 | 65 | /** 66 | * Send mail into the user. 67 | * 68 | * @param string $server 69 | * @param string $subject 70 | * @param string $body 71 | * @param ReplyTo $replyTo 72 | * @param Attachment|Attachment[] $attachments 73 | * @throws MailerException 74 | * @return void 75 | */ 76 | public function sendMail(string $server, string $subject, string $body, $replyTo = null, $attachments = null, bool $html = true) : bool { 77 | return Mailer::sendMail($server, $subject, $body, $replyTo, $attachments, new Receipient($this->getName(), $this->getMail())); 78 | } 79 | 80 | /** 81 | * Update the data from the table. 82 | * 83 | * @return void 84 | */ 85 | public function updateData() : void { 86 | $this->data = UserFactory::getProvider()->getAll($this); 87 | } 88 | 89 | /** 90 | * Delete user. 91 | * 92 | * @return bool 93 | */ 94 | public function delete() : bool { 95 | if (!$this->exists()) return false; 96 | 97 | return UserFactory::getProvider()->delete($this); 98 | } 99 | 100 | /** 101 | * Create user. 102 | * 103 | * @return boolean 104 | */ 105 | public function create() : bool { 106 | return UserFactory::getProvider()->create($this->data); 107 | } 108 | 109 | /** 110 | * Check if user exists. 111 | * 112 | * @return boolean 113 | */ 114 | public function exists() : bool { 115 | $data = UserFactory::getProvider()->getAll($this); 116 | 117 | return !empty($data); 118 | } 119 | 120 | /** 121 | * Set user object values by array. 122 | * 123 | * @param array $data 124 | * @return void 125 | */ 126 | public function setByArray(array $data) : bool { 127 | foreach ($data as $key => $value) $this->data[$key] = $value; 128 | 129 | return UserFactory::getProvider()->set($this, $data); 130 | } 131 | 132 | /** 133 | * Get all data. 134 | * 135 | * @return array 136 | */ 137 | public function getAll() : array { 138 | return !empty($this->data) ? $this->data : []; 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /micro-advanced/sql/table/Table.php: -------------------------------------------------------------------------------- 1 | sql = $sql; 48 | 49 | $this->name = $name; 50 | } 51 | 52 | /** 53 | * Get table name. 54 | * 55 | * @return string 56 | */ 57 | public function getName(): string { 58 | return $this->name; 59 | } 60 | 61 | /** 62 | * Get SQL instance. 63 | * 64 | * @return ISQL 65 | */ 66 | public function getSQL(): ISQL { 67 | return $this->sql; 68 | } 69 | 70 | /** 71 | * Generate a select query. 72 | * 73 | * @param string|null $table 74 | * @return Select 75 | */ 76 | public function select() : Select { 77 | return (new Select($this)); 78 | } 79 | 80 | /** 81 | * Generate an insert query. 82 | * 83 | * @param string|null $table 84 | * @return Insert 85 | */ 86 | public function insert() : Insert { 87 | return (new Insert($this)); 88 | } 89 | 90 | /** 91 | * Generate an update query. 92 | * 93 | * @param string|null $table 94 | * @return Update 95 | */ 96 | public function update() : Update { 97 | return (new Update($this)); 98 | } 99 | 100 | /** 101 | * Generate a delete query. 102 | * 103 | * @param string|null $table 104 | * @return Delete 105 | */ 106 | public function delete() : Delete { 107 | return (new Delete($this)); 108 | } 109 | 110 | /** 111 | * Generate a create query. 112 | * 113 | * @param string|null $table 114 | * @return Create 115 | */ 116 | public function create() : Create { 117 | return (new Create($this)); 118 | } 119 | 120 | /** 121 | * Generate a drop query. 122 | * 123 | * @param string|null $table 124 | * @return Drop 125 | */ 126 | public function drop() : Drop { 127 | return (new Drop($this)); 128 | } 129 | 130 | /** 131 | * Generate a query to show table columns. 132 | * 133 | * @param string|null $table 134 | * @return ShowColumns 135 | */ 136 | public function showColumns() : ShowColumns { 137 | return (new ShowColumns($this)); 138 | } 139 | 140 | /** 141 | * Generate a query to add columns into a table. 142 | * 143 | * @param string|null $table 144 | * @return AddColumns 145 | */ 146 | public function addColumns() : AddColumns { 147 | return (new AddColumns($this)); 148 | } 149 | 150 | /** 151 | * Generate a query to modify columns from a table. 152 | * 153 | * @param string|null $table 154 | * @return ModifyColumns 155 | */ 156 | public function modifyColumns() : ModifyColumns { 157 | return (new ModifyColumns($this)); 158 | } 159 | 160 | /** 161 | * Generate a query to drop columns from a table. 162 | * 163 | * @param string|null $table 164 | * @return DropColumns 165 | */ 166 | public function dropColumns() : DropColumns { 167 | return (new DropColumns($this)); 168 | } 169 | 170 | /** 171 | * Generate a query to truncate a table. 172 | * 173 | * @param string|null $table 174 | * @return Truncate 175 | */ 176 | public function truncate() : Truncate { 177 | return (new Truncate($this)); 178 | } 179 | 180 | /** 181 | * Check if the table exists. 182 | * 183 | * @return boolean 184 | */ 185 | public function exists(): bool { 186 | return $this->select()->executeBool(); 187 | } 188 | 189 | public function __toString() { 190 | return $this->name; 191 | } 192 | } -------------------------------------------------------------------------------- /micro-advanced/sql/query/join/Join.php: -------------------------------------------------------------------------------- 1 | query = $query; 62 | 63 | $this->table = $table; 64 | } 65 | 66 | /** 67 | * Add on argument to query. 68 | * 69 | * @param string $conditional 70 | * @return Join 71 | */ 72 | public function on(string $conditional) : Join { 73 | $this->on = $conditional; 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * Add alias into the join table. 80 | * 81 | * @param string $alias 82 | * @return Join 83 | */ 84 | public function as(string $alias) : Join { 85 | $this->as = $alias; 86 | 87 | return $this; 88 | } 89 | 90 | /** 91 | * Add using argument into the using. 92 | * 93 | * @param array $columns 94 | * @return Join 95 | */ 96 | public function using(array $columns) : Join { 97 | $this->using = $columns; 98 | 99 | return $this; 100 | } 101 | 102 | /** 103 | * Join table. 104 | * 105 | * @param string $table 106 | * @return Join 107 | */ 108 | public function join(string $table) : IJoin { 109 | return $this->query->join($table); 110 | } 111 | 112 | /** 113 | * Left join table. 114 | * 115 | * @param string $table 116 | * @return LeftJoin 117 | */ 118 | public function leftJoin(string $table) : IJoin { 119 | return $this->query->leftJoin($table); 120 | } 121 | 122 | /** 123 | * Inner join table. 124 | * 125 | * @param string $table 126 | * @return InnerJoin 127 | */ 128 | public function innerJoin(string $table) : IJoin { 129 | return $this->query->innerJoin($table); 130 | } 131 | 132 | /** 133 | * Right join table. 134 | * 135 | * @param string $table 136 | * @return RightJoin 137 | */ 138 | public function rightJoin(string $table) : IJoin { 139 | return $this->query->rightJoin($table); 140 | } 141 | 142 | /** 143 | * Full join table. 144 | * 145 | * @param string $table 146 | * @return FullJoin 147 | */ 148 | public function fullJoin(string $table) : IJoin { 149 | return $this->query->fullJoin($table); 150 | } 151 | 152 | /** 153 | * Set the WHERE SQL parameter. 154 | * 155 | * @param string $where Set where example: "name = ?" or "name = ? AND last = ?". 156 | * @param mixed $execute Set values example "Denzel" or ["Denzel", "Code"]. 157 | * @return IQuery 158 | */ 159 | public function where(string $where, $execute = []) : IQuery { 160 | return $this->query->where($where, $execute); 161 | } 162 | 163 | /** 164 | * Execute query and return PDOStatement. 165 | * 166 | * @return PDOStatement 167 | */ 168 | public function execute() : PDOStatement { 169 | return $this->query->execute(); 170 | } 171 | 172 | /** 173 | * @return string 174 | */ 175 | public function getPreffix(): string { 176 | return "JOIN"; 177 | } 178 | 179 | /** 180 | * Convert Object to Query string. 181 | * 182 | * @return string 183 | */ 184 | public function toQuery(): string { 185 | $query = "{$this->getPreffix()} {$this->table}"; 186 | 187 | $query .= !empty($this->as) ? " AS ($this->as)" : ""; 188 | 189 | $query .= !empty($this->on) ? " ON ($this->on)" : ""; 190 | 191 | $query .= !empty($this->using) ? " USING (" . join(", ", $this->using) . ")" : ""; 192 | 193 | return $query; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /micro-advanced/user/Guest.php: -------------------------------------------------------------------------------- 1 | has("sign_up.user")) $config->set("sign_up.user", [])->save(); 37 | 38 | $signup = $config->get("sign_up"); 39 | 40 | $data = [ 41 | "id" => 0, 42 | "username" => Bootstrap::getMainLanguage()->get("general.guest"), 43 | "firstname" => Bootstrap::getMainLanguage()->get("general.guest"), 44 | "password" => "", 45 | "mail" => "guest@example.com", 46 | "lastname" => "", 47 | "rank" => 1, 48 | "gender" => "M", 49 | "ip_last" => Request::getInstance()->getIp(), 50 | "ip_reg" => Request::getInstance()->getIp(), 51 | "display_name" => Bootstrap::getMainLanguage()->get("general.guest") 52 | ]; 53 | 54 | foreach ((!empty($signup["user"]) ? $signup["user"] : []) as $key => $value) $data[$key] = $value; 55 | 56 | $this->setByArray($data); 57 | } 58 | 59 | /** 60 | * Set guest data value. 61 | * 62 | * @param string $key 63 | * @param mixed $value 64 | * @return boolean 65 | */ 66 | public function set(string $key, $value): bool { 67 | return $this->setByArray([ $key => $value ]); 68 | } 69 | 70 | /** 71 | * Set guest data by array. 72 | * 73 | * @param array $values 74 | * @return boolean 75 | */ 76 | public function setByArray(array $values) : bool { 77 | foreach ($values as $key => $value) $this->data[$key] = $value; 78 | 79 | return true; 80 | } 81 | 82 | /** 83 | * Get user data. 84 | * 85 | * @param string $key 86 | * @return void 87 | */ 88 | public function get(string $key) { 89 | return $this->data[$key]; 90 | } 91 | 92 | /** 93 | * Get guest id. 94 | * 95 | * @return integer 96 | */ 97 | public function getId() : int { 98 | return $this->data["id"]; 99 | } 100 | 101 | /** 102 | * Get guest name. 103 | * 104 | * @return string 105 | */ 106 | public function getName() : string { 107 | return $this->data["username"]; 108 | } 109 | 110 | /** 111 | * Get guest first name. 112 | * 113 | * @return string 114 | */ 115 | public function getFirstName() : string { 116 | return $this->data["firstname"]; 117 | } 118 | 119 | /** 120 | * Get last name. 121 | * 122 | * @return string 123 | */ 124 | public function getLastName() : string { 125 | return $this->data["lastname"]; 126 | } 127 | 128 | /** 129 | * Get full name. 130 | * 131 | * @return string 132 | */ 133 | public function getFullName() : string { 134 | return $this->getFirstName() . " " . $this->getLastName(); 135 | } 136 | 137 | /** 138 | * Get gender. 139 | * 140 | * @return string 141 | */ 142 | public function getGender() : string { 143 | return $this->data["gender"]; 144 | } 145 | 146 | /** 147 | * Get mail. 148 | * 149 | * @return string 150 | */ 151 | public function getMail() : string { 152 | return $this->data["mail"]; 153 | } 154 | 155 | /** 156 | * Get password. 157 | * 158 | * @return string 159 | */ 160 | public function getPassword() : string { 161 | return $this->data["password"]; 162 | } 163 | 164 | /** 165 | * Get IP of registration 166 | * 167 | * @return string 168 | */ 169 | public function getRegisterIp() : string { 170 | return $this->data["ip_reg"]; 171 | } 172 | 173 | /** 174 | * Get last IP. 175 | * 176 | * @return string 177 | */ 178 | public function getLastIp() : string { 179 | return $this->data["ip_last"]; 180 | } 181 | 182 | /** 183 | * Get all data as array. 184 | * 185 | * @return array 186 | */ 187 | public function getAll(): array { 188 | return (is_array($this->data) ? $this->data : []); 189 | } 190 | } 191 | 192 | -------------------------------------------------------------------------------- /micro-advanced/http/router/Router.php: -------------------------------------------------------------------------------- 1 | getControllerFile("advanced"))) { 46 | self::run($request, "project"); 47 | 48 | return; 49 | } 50 | 51 | Bootstrap::getResponse()->setCode(Response::HTTP_OK); 52 | 53 | self::check404($request, $preffix); 54 | 55 | $execute = $request->getArguments(); 56 | 57 | array_unshift($execute, $request->getRequestMethod()); 58 | 59 | try { 60 | $method = $request->getMethod(); 61 | 62 | $body = @call_user_func_array([$request->getControllerObject($preffix), $method], $execute); 63 | } catch (\TypeError $e) { 64 | if (\strpos($e->getMessage(), "passed to " . $request->getControllerNamespace($preffix)) !== false) { 65 | Bootstrap::getResponse()->setCode(Response::HTTP_NOT_FOUND); 66 | 67 | $body = @call_user_func_array([$request->getControllerObject($preffix), "error404"], $execute); 68 | } else print($e); 69 | } 70 | 71 | if (isset($body)) print($body); 72 | } 73 | 74 | /** 75 | * Check if it is an error 404. 76 | * 77 | * @param Request $request 78 | * @param string $preffix 79 | * @return void 80 | */ 81 | private static function check404(Request $request, string $preffix): void 82 | { 83 | $set404 = function (Request $request) { 84 | Bootstrap::getResponse()->setCode(Response::HTTP_NOT_FOUND); 85 | 86 | $request->setMethod("error404"); 87 | }; 88 | 89 | $object_name = $request->getControllerNamespace($preffix); 90 | 91 | if (!method_exists($object_name, $request->getMethod())) $set404($request); 92 | 93 | if (in_array($request->getMethod(), self::getPrivateMethods($object_name))) $set404($request); 94 | 95 | $parameters = (new ReflectionMethod($object_name, $request->getMethod()))->getParameters(); 96 | 97 | $parameter = (empty($parameters[0]) ? null : $parameters[0]); 98 | 99 | $request->setRequestMethod(strtolower($_SERVER["REQUEST_METHOD"])); 100 | 101 | if ($parameter && $parameter->getName() == "method" && !self::checkRequestMethods(explode("|", $parameter->getDefaultValue()))) 102 | throw new RouterException(0, "exception.router.method_not_exists", $parameter->getDefaultValue()); 103 | 104 | if ($parameter && $parameter->getName() == "method" && strtolower($parameter->getDefaultValue()) != "*" && strtolower($parameter->getDefaultValue()) != strtolower(Request::GENERAL) && strtolower($parameter->getDefaultValue()) != strtolower(Request::ALL) && strtolower($parameter->getDefaultValue()) != strtolower(Request::ANY) && !in_array($request->getRequestMethod(), explode("|", strtolower($parameter->getDefaultValue())))) $set404($request); 105 | } 106 | 107 | /** 108 | * Get private class methods. 109 | * 110 | * @return array 111 | */ 112 | private static function getPrivateMethods(string $object_name): array 113 | { 114 | $private_methods = []; 115 | 116 | $class_methods = (new ReflectionClass($object_name))->getMethods(ReflectionMethod::IS_PRIVATE | ReflectionMethod::IS_PROTECTED); 117 | 118 | foreach ($class_methods as $method) $private_methods[] = $method->getName(); 119 | 120 | return $private_methods; 121 | } 122 | 123 | /** 124 | * Check if request methods exist. 125 | * 126 | * @param array $methods 127 | * @return boolean 128 | */ 129 | private static function checkRequestMethods(array $methods): bool 130 | { 131 | $methods = array_map("strtolower", $methods); 132 | 133 | $main = array_map("strtolower", self::$http_methods); 134 | 135 | foreach ($methods as $method) if (!in_array($method, $main)) return false; 136 | 137 | return true; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /micro-advanced/language/Language.php: -------------------------------------------------------------------------------- 1 | language = $language === null ? self::$defaultLanguage : $language; 57 | 58 | $this->path = $path; 59 | 60 | self::updateConfig($this->language); 61 | } 62 | 63 | /** 64 | * Get the language name. 65 | * 66 | * @return string 67 | */ 68 | public function getName() : string { 69 | return $this->language; 70 | } 71 | 72 | /** 73 | * Enable/disable project mode. 74 | * 75 | * @param boolean $value 76 | * @return void 77 | */ 78 | public function setProjectMode(bool $value = true) : void { 79 | $path = $this->path; 80 | 81 | $this->path = $value ? self::PATH_PROJECT : self::PATH_ADVANCED; 82 | 83 | if ($path != $this->path) self::updateConfig($this->language); 84 | } 85 | 86 | /** 87 | * Get the path where we are going to get the language. 88 | * 89 | * @return string 90 | */ 91 | public function getPath() : string { 92 | return ($this->path == self::PATH_ADVANCED ? ADVANCED : PROJECT) . self::LANGUAGE_PATH; 93 | } 94 | 95 | /** 96 | * Update language file. 97 | * 98 | * @param string $file 99 | * @return void 100 | */ 101 | private function updateConfig(string $file) : void { 102 | $file = $this->getPath() . $file; 103 | 104 | $this->config = new Config($file); 105 | } 106 | 107 | /** 108 | * Get translated string from the language files. 109 | * 110 | * @param string $key 111 | * @param string $default 112 | * @param mixed ...$params 113 | * @return mixed 114 | */ 115 | public function get(string $key, string $default = null, ...$params) { 116 | $value = $this->config->get($key, $default); 117 | 118 | return is_string($value) ? self::filter($value, $params) : $value; 119 | } 120 | 121 | /** 122 | * @return IConfig 123 | */ 124 | public function getConfig() : IConfig { 125 | return $this->config; 126 | } 127 | 128 | /** 129 | * Change app language. 130 | * 131 | * @param string $language 132 | * @return void 133 | */ 134 | public static function setCurrentLanguage(string $language) { 135 | if ($language == null) $language = self::$defaultLanguage; 136 | 137 | $language = new Language($language); 138 | 139 | CookieManager::set("language", $language->getName()); 140 | } 141 | 142 | /** 143 | * Get app language 144 | * 145 | * @return string|null 146 | */ 147 | public static function getCurrentLanguage() : ?string { 148 | return CookieManager::get("language"); 149 | } 150 | 151 | /** 152 | * Get default language, 153 | * 154 | * @return string 155 | */ 156 | public static function getDefaultLanguage() : ?string { 157 | return self::$defaultLanguage; 158 | } 159 | 160 | /** 161 | * Filter string. 162 | * 163 | * @param string $text 164 | * @param mixed $params 165 | * @return string 166 | */ 167 | private function filter(string $text, $params) : string { 168 | foreach ($params as $key => $value) $text = str_replace("{{$key}}", $value, $text); 169 | 170 | return $text; 171 | } 172 | 173 | /** 174 | * Init current language. 175 | * 176 | * @param string $defaultLanguage 177 | * @return void 178 | */ 179 | public static function init(string $defaultLanguage = "en") : void { 180 | self::$defaultLanguage = $defaultLanguage; 181 | 182 | $language = empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]) ? $defaultLanguage : substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2); 183 | 184 | self::setCurrentLanguage(file_exists(ADVANCED . self::LANGUAGE_PATH) || !file_exists(PROJECT . self::LANGUAGE_PATH) ? $language : $defaultLanguage); 185 | } 186 | } 187 | 188 | -------------------------------------------------------------------------------- /micro-advanced/user/auth/Auth.php: -------------------------------------------------------------------------------- 1 | verify($password)) return false; 48 | 49 | self::create([ 50 | "user_id" => $user->getId(), 51 | "username" => $user->getName(), 52 | "hash" => $user->getPassword(), 53 | "cookie" => $cookie 54 | ]); 55 | 56 | return true; 57 | } 58 | 59 | /** 60 | * Use this method to know if the browser got an account logged in. 61 | * 62 | * @return boolean 63 | */ 64 | public static function check() : bool { 65 | if (!Bootstrap::getSQL()) return false; 66 | 67 | if (!self::get("user_id") && !self::get("username") && !self::get("auth_code")) return false; 68 | 69 | $user = Bootstrap::getUserFactory()->getUser(self::get("username")); 70 | 71 | if (!$user) return false; 72 | 73 | $auth_code = md5($user->getPassword() . Request::getInstance()->getIP()); 74 | 75 | if (self::get("auth_code") == $auth_code) return true; 76 | 77 | return false; 78 | } 79 | 80 | /** 81 | * @return IUser|null 82 | */ 83 | public static function getUser() : ?IUser { 84 | $guest = UserFactory::getGuestObject(); 85 | 86 | if (!Bootstrap::getSQL()) return new $guest(); 87 | 88 | if (!self::check()) return new $guest(); 89 | 90 | $user = Bootstrap::getUserFactory()->getUser(self::get("username")); 91 | 92 | if (!$user) return new $guest(); 93 | 94 | return $user; 95 | } 96 | 97 | /** 98 | * Check if session is authenticated. 99 | * 100 | * @return boolean 101 | */ 102 | public static function isAuthenticated() : bool { 103 | return !self::getUser() instanceof Guest; 104 | } 105 | 106 | /** 107 | * Set auth session parameters. 108 | * 109 | * @param array $data 110 | * @param boolean $cookie 111 | * @param integer $time 112 | * @param string $directory 113 | * @return void 114 | */ 115 | public static function set(array $data, bool $cookie = false, int $time = 3600 * 24 * 365, string $directory = "/") : void { 116 | if ($cookie) CookieManager::setByArray($data, $time, $directory); else SessionManager::setByArray($data); 117 | } 118 | 119 | /** 120 | * Get auth session parameter. 121 | * 122 | * @param string $data 123 | * @return mixed 124 | */ 125 | public static function get(string $data) { 126 | return SessionManager::getFromSessionOrCookie($data); 127 | } 128 | 129 | /** 130 | * Unset auth session parameter. 131 | * 132 | * @param array $data 133 | * @param string $directory 134 | * @return void 135 | */ 136 | public static function unset(array $data, string $directory = "/") { 137 | SessionManager::deleteByArray($data); 138 | 139 | CookieManager::deleteByArray($data, $directory); 140 | } 141 | 142 | /** 143 | * Destroy session. 144 | * 145 | * @return void 146 | */ 147 | public static function destroy() : void { 148 | self::unset([ "user_id", "username", "auth_code" ]); 149 | } 150 | 151 | /** 152 | * Create session. 153 | * 154 | * @param array $data 155 | * @return void 156 | */ 157 | public static function create(array $data) : void { 158 | self::set([ 159 | "user_id" => $data["user_id"], 160 | "username" => $data["username"], 161 | "auth_code" => md5($data["hash"] . Request::getIP()) 162 | ], $data["cookie"]); 163 | } 164 | 165 | /** 166 | * Hash passsword. 167 | * 168 | * @param string $password 169 | * @return void 170 | */ 171 | public static function hash(string $password) : string { 172 | return password_hash($password, PASSWORD_DEFAULT); 173 | } 174 | 175 | /** 176 | * Verify if a password match with the hash. 177 | * 178 | * @param string $password 179 | * @param string $hash 180 | * @return boolean 181 | */ 182 | public static function verify(string $password, string $hash) : bool { 183 | return password_verify($password, $hash); 184 | } 185 | } 186 | 187 | -------------------------------------------------------------------------------- /micro-advanced/http/Response.php: -------------------------------------------------------------------------------- 1 | setContentType('text/json'); 114 | 115 | return json_encode($data); 116 | } 117 | 118 | /** 119 | * Set response code. 120 | * 121 | * @param integer $code 122 | * @return Response 123 | */ 124 | public function setCode(int $code) : Response { 125 | http_response_code($code); 126 | 127 | return $this; 128 | } 129 | 130 | /** 131 | * Get response code. 132 | * 133 | * @return integer 134 | */ 135 | public function getCode() : int { 136 | return http_response_code(); 137 | } 138 | 139 | /** 140 | * Set app header. 141 | * 142 | * @param string $header 143 | * @return void 144 | */ 145 | public function setContentType(string $header) { 146 | header("Content-Type: {$header}"); 147 | } 148 | 149 | /** 150 | * Redirect app into an URL. 151 | * 152 | * @param string $url 153 | * @return void 154 | */ 155 | public function redirect(string $url) : void { 156 | header("Location: {$url}"); 157 | 158 | exit; 159 | } 160 | } -------------------------------------------------------------------------------- /micro-advanced/Bootstrap.php: -------------------------------------------------------------------------------- 1 | new Request(empty($_SERVER["REQUEST_URI"]) ? "" : $_SERVER["REQUEST_URI"]), 54 | "response" => new Response() 55 | ]; 56 | 57 | try { 58 | self::$classes["config"] = new Config(Project::getConfigPath()); 59 | 60 | self::$classes["mainConfig"] = ($config = new Config(ADVANCED . "resources" . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "config")); 61 | } catch (ConfigException $e) { 62 | die($e->getMessage()); 63 | } 64 | 65 | Language::init($config->get("language.default")); 66 | 67 | self::$classes["mainLanguage"] = new Language(Language::getCurrentLanguage(), Language::PATH_ADVANCED); 68 | 69 | self::$classes["language"] = clone self::$classes["mainLanguage"]; 70 | 71 | self::$classes["language"]->setProjectMode(); 72 | } 73 | 74 | /** 75 | * Instance Bootstrap. 76 | * 77 | * @return Bootstrap 78 | */ 79 | public static function getInstance() : Bootstrap { 80 | if (!self::$instance) self::$instance = new Bootstrap(); 81 | 82 | return self::$instance; 83 | } 84 | 85 | /** 86 | * Get request object, access to route arguments and more. 87 | * 88 | * @return Request 89 | */ 90 | public static function getRequest() : Request { 91 | return self::$classes["request"]; 92 | } 93 | 94 | /** 95 | * Get project config. 96 | * 97 | * @return IConfig 98 | */ 99 | public static function getConfig() : IConfig { 100 | return self::$classes["config"]; 101 | } 102 | 103 | /** 104 | * Get Advanced config. 105 | * 106 | * @return IConfig 107 | */ 108 | public static function getMainConfig() : IConfig { 109 | return self::$classes["mainConfig"]; 110 | } 111 | 112 | /** 113 | * Get project language. 114 | * 115 | * @return Language 116 | */ 117 | public static function getLanguage() : Language { 118 | return self::$classes["language"]; 119 | } 120 | 121 | /** 122 | * Get Advanced language. 123 | * 124 | * @return Language 125 | */ 126 | public static function getMainLanguage() : Language { 127 | return self::$classes["mainLanguage"]; 128 | } 129 | 130 | /** 131 | * Get response. 132 | * 133 | * @return Response 134 | */ 135 | public static function getResponse() : Response { 136 | return self::$classes["response"]; 137 | } 138 | 139 | /** 140 | * Set SQL connection (OLD). 141 | * 142 | * @return Database 143 | */ 144 | public static function setDatabase(Database $database) : void { 145 | self::$classes["database"] = $database; 146 | } 147 | 148 | /** 149 | * Get SQL connection (OLD). 150 | * 151 | * @return Database 152 | */ 153 | public static function getDatabase(): ?Database { 154 | return self::$classes["database"] ?? null; 155 | } 156 | 157 | /** 158 | * Set SQL connection. 159 | * 160 | * @param ISQL $sql 161 | * @return void 162 | */ 163 | public static function setSQL(ISQL $sql) : void { 164 | self::$classes["sql"] = $sql; 165 | } 166 | 167 | /** 168 | * Get SQL connection. 169 | * 170 | * @return ISQL|null 171 | */ 172 | public static function getSQL(): ?ISQL { 173 | return self::$classes["sql"] ?? null; 174 | } 175 | 176 | /** 177 | * Get users factory. 178 | * 179 | * @return UserFactory 180 | */ 181 | public static function getUserFactory() : UserFactory { 182 | if (empty(self::$classes["users"])) self::$classes["users"] = new UserFactory(); 183 | 184 | return self::$classes["users"]; 185 | } 186 | 187 | /** 188 | * Set a class in the list of classes. 189 | * 190 | * @param string $name 191 | * @param mixed $object 192 | * @return void 193 | */ 194 | public static function setClass(string $name, $object) : void { 195 | self::$classes[$name] = $object; 196 | } 197 | 198 | /** 199 | * Get a class in the list of classes. 200 | * 201 | * @param string $name 202 | * @return mixed 203 | */ 204 | public static function getClass(string $name) { 205 | return self::$classes[$name]; 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /micro-advanced/project/Project.php: -------------------------------------------------------------------------------- 1 | getMessage(); 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /micro-advanced/file/File.php: -------------------------------------------------------------------------------- 1 | path = $file; 53 | $this->path = str_replace("\\", DIRECTORY_SEPARATOR, $this->path); 54 | $this->path = str_replace("/", DIRECTORY_SEPARATOR, $this->path); 55 | 56 | $this->directory = new Directory(dirname($this->path)); 57 | 58 | $this->mode = $mode; 59 | } 60 | 61 | /** 62 | * Write file content. 63 | * 64 | * @param string $content 65 | * @return void 66 | * @throws FileException 67 | */ 68 | public function write(string $content) : void { 69 | if (!($handle = @fopen($this->path, $this->mode))) throw new FileException(0, "exception.file.open", $this->path); 70 | 71 | if (!fwrite($handle, (string) $content)) throw new FileException(1, "exception.file.write", $this->path); 72 | 73 | fclose($handle); 74 | } 75 | 76 | /** 77 | * Append content into a file. 78 | * 79 | * @param string $content 80 | * @return void 81 | * @throws FileException 82 | */ 83 | public function append(string $content) : void { 84 | $this->write($this->read() . $content); 85 | } 86 | 87 | /** 88 | * Create file and directories if not exists. 89 | * 90 | * @param string $default 91 | * @param integer $permission 92 | * @return void 93 | * @throws FileException 94 | */ 95 | public function create(string $default = null, int $permission = 0777): void { 96 | if ($this->exists()) return; 97 | 98 | $this->directory->create($permission); 99 | 100 | $this->write($default); 101 | 102 | $this->setPermission($permission); 103 | } 104 | 105 | /** 106 | * Get file name. 107 | * 108 | * @return string 109 | */ 110 | public function getName() : string { 111 | return $this->name; 112 | } 113 | 114 | /** 115 | * Get file name without extension. 116 | * 117 | * @return string 118 | */ 119 | public function getNameWithoutExtension() : string { 120 | $name = explode(".", $this->getName()); 121 | 122 | unset($name[(count($name) - 1)]); 123 | 124 | return implode(".", $name); 125 | } 126 | 127 | /** 128 | * Set file name. 129 | * 130 | * @param string $name 131 | * @return void 132 | */ 133 | public function setName(string $name): void { 134 | rename($this->path, $this->directory->getPath() . DIRECTORY_SEPARATOR . $name); 135 | 136 | $this->name = $name; 137 | } 138 | 139 | /** 140 | * Get file extension. 141 | * 142 | * @return string 143 | */ 144 | public function getExtension() : string { 145 | return end(explode(".", $this->getName())); 146 | } 147 | 148 | /** 149 | * Get file path. 150 | * 151 | * @return string 152 | */ 153 | public function getPath() : string { 154 | return $this->path; 155 | } 156 | 157 | /** 158 | * Set file path. 159 | * 160 | * @param string $path 161 | * @return void 162 | */ 163 | public function setPath(string $path): void { 164 | rename($this->path, $path); 165 | 166 | $this->path = $path; 167 | 168 | $this->name = end(explode(DIRECTORY_SEPARATOR, $this->path)); 169 | 170 | $this->directory = new Directory(dirname($this->path)); 171 | } 172 | 173 | /** 174 | * Get file permissions. 175 | * 176 | * @return integer 177 | */ 178 | public function getPermission(): int { 179 | return fileperms($this->path); 180 | } 181 | 182 | /** 183 | * Set file permissions. 184 | * 185 | * @param integer $permission 186 | * @return void 187 | */ 188 | public function setPermission(int $permission): void { 189 | chmod($this->path, $permission); 190 | } 191 | 192 | /** 193 | * Get file size 194 | * 195 | * @return integer 196 | */ 197 | public function getSize(): int { 198 | return filesize($this->path); 199 | } 200 | 201 | /** 202 | * Check if file exists. 203 | * 204 | * @return boolean 205 | */ 206 | public function exists(): bool { 207 | return file_exists($this->path); 208 | } 209 | 210 | /** 211 | * Delete a file 212 | * 213 | * @return void 214 | */ 215 | public function delete(): bool { 216 | return @unlink($this->directory->getPath() . DIRECTORY_SEPARATOR . $this->name); 217 | } 218 | 219 | /** 220 | * Return file content. 221 | * 222 | * @param array $extract 223 | * @return string 224 | */ 225 | public function read(array $extract = null) : string { 226 | extract($extract ?? []); 227 | 228 | ob_start(); 229 | include($this->path); 230 | $data = ob_get_contents(); 231 | ob_end_clean(); 232 | 233 | return $data; 234 | } 235 | } 236 | 237 | -------------------------------------------------------------------------------- /micro-advanced/sql/query/Select.php: -------------------------------------------------------------------------------- 1 | order = $by; 61 | 62 | return $this; 63 | } 64 | 65 | /** 66 | * Set the LIMIT attribute to the SQL query. 67 | * 68 | * @param int $limit 69 | * @return Select 70 | */ 71 | public function setLimit(int $limit) : IQuery { 72 | return parent::setLimit($limit); 73 | } 74 | 75 | /** 76 | * Set the LIMIT attribute to the SQL query. 77 | * 78 | * @param int $limit 79 | * @return Select 80 | */ 81 | public function limit(int $limit) : IQuery { 82 | return parent::limit($limit); 83 | } 84 | 85 | /** 86 | * Set the WHERE SQL parameter. 87 | * 88 | * @param string $where Set where example: "name = ?" or "name = ? AND last = ?". 89 | * @param mixed $execute Set values example "Denzel" or ["Denzel", "Code"]. 90 | * @return Select 91 | */ 92 | public function where(string $where, $execute = []) : IQuery { 93 | return parent::where($where, $execute); 94 | } 95 | 96 | /** 97 | * Set the list of columns that tou want to select by array 98 | * 99 | * @param array $columns 100 | * @return Select 101 | */ 102 | public function setColumns(array $columns = ["*"]) : Select { 103 | $this->columns = $columns; 104 | 105 | return $this; 106 | } 107 | 108 | /** 109 | * Set the list of columns that tou want to select by array 110 | * 111 | * @param array $columns 112 | * @return Select 113 | */ 114 | public function columns(array $columns = ["*"]) : Select { 115 | return $this->setColumns($columns); 116 | } 117 | 118 | /** 119 | * Select distinct value 120 | * 121 | * @param string $column 122 | * @return Select 123 | */ 124 | public function distinct(string $column = null) : Select { 125 | $this->distinct = $column; 126 | 127 | return $this; 128 | } 129 | 130 | /** 131 | * Join table. 132 | * 133 | * @param string $table 134 | * @return Join 135 | */ 136 | public function join(string $table) : IJoin { 137 | return ($this->joins[] = new Join($this, $table)); 138 | } 139 | 140 | /** 141 | * Left join table. 142 | * 143 | * @param string $table 144 | * @return LeftJoin 145 | */ 146 | public function leftJoin(string $table) : IJoin { 147 | return ($this->joins[] = new LeftJoin($this, $table)); 148 | } 149 | 150 | /** 151 | * Inner join table. 152 | * 153 | * @param string $table 154 | * @return InnerJoin 155 | */ 156 | public function innerJoin(string $table) : IJoin { 157 | return ($this->joins[] = new InnerJoin($this, $table)); 158 | } 159 | 160 | /** 161 | * Right join table. 162 | * 163 | * @param string $table 164 | * @return RightJoin 165 | */ 166 | public function rightJoin(string $table) : IJoin { 167 | return ($this->joins[] = new RightJoin($this, $table)); 168 | } 169 | 170 | /** 171 | * Full join table. 172 | * 173 | * @param string $table 174 | * @return FullJoin 175 | */ 176 | public function fullJoin(string $table) : IJoin { 177 | return ($this->joins[] = new FullJoin($this, $table)); 178 | } 179 | 180 | /** 181 | * Fetch all the results. 182 | * 183 | * @return array 184 | */ 185 | public function fetchAll() : array { 186 | return $this->execute()->fetchAll(); 187 | } 188 | 189 | /** 190 | * Fetch the first result false if is a bad query. 191 | * 192 | * @return array 193 | */ 194 | public function fetch() : array { 195 | $data = $this->execute()->fetch(); 196 | 197 | return $data == false ? [] : $data; 198 | } 199 | 200 | /** 201 | * Execute the Query and return an PDOStatement Object so you can fetch results. 202 | * 203 | * @return PDOStatement 204 | */ 205 | public function execute() { 206 | parent::execute(); 207 | 208 | return $this->prepare; 209 | } 210 | 211 | /** 212 | * Execute the query. 213 | * 214 | * @return bool 215 | */ 216 | public function executeBool() { 217 | return parent::execute(); 218 | } 219 | 220 | /** 221 | * Generate the query string of the object 222 | * 223 | * @return string 224 | */ 225 | public function toQuery() : string { 226 | $query = "SELECT " . (!empty($this->distinct) ? "DISTINCT {$this->distinct} " : ""); 227 | 228 | $query .= join(", ", $this->columns); 229 | 230 | $query .= !empty($this->table) ? " FROM {$this->table}" : ""; 231 | 232 | foreach ($this->joins as $join) $query .= " " . $join->toQuery(); 233 | 234 | $query .= !empty($this->where) ? " WHERE {$this->where}" : ""; 235 | 236 | $query .= !empty($this->order) ? " ORDER BY {$this->order}" : ""; 237 | 238 | $query .= $this->limit > 0 ? " LIMIT {$this->limit}" : ""; 239 | 240 | return $query; 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /micro-advanced/user/provider/MySQLProvider.php: -------------------------------------------------------------------------------- 1 | sql = $sql; 52 | 53 | $this->setup(); 54 | } 55 | 56 | /** 57 | * Setup the users tables. 58 | * 59 | * @return void 60 | */ 61 | public function setup(): void{ 62 | $config = new Config(Database::getConfigPath()); 63 | 64 | $config->setIfNotExists("import.{$this->table}", [ 65 | "id" => "int(11) PRIMARY KEY AUTO_INCREMENT", 66 | "username" => "varchar(255)", 67 | "firstname" => "varchar(255)", 68 | "lastname" => "varchar(255)", 69 | "password" => "varchar(255)", 70 | "mail" => "varchar(255)", 71 | "country" => "varchar(4)", 72 | "gender" => "enum('M', 'F') DEFAULT 'M'", 73 | "account_created" => "double(50, 0) DEFAULT 0", 74 | "last_used" => "double(50, 0) DEFAULT 0", 75 | "last_online" => "double(50, 0) DEFAULT 0", 76 | "last_password" => "double(50, 0) DEFAULT 0", 77 | "online" => "enum('0', '1') DEFAULT '0'", 78 | "ip_reg" => "varchar(45) NOT NULL", 79 | "ip_last" => "varchar(45) NOT NULL", 80 | "language" => "varchar(255) DEFAULT 'en'", 81 | "connection_id" => "text", 82 | "birth_date" => "varchar(55)", 83 | "facebook_id" => "text", 84 | "facebook_token" => "text", 85 | "facebook_account" => "boolean DEFAULT false" 86 | ]); 87 | 88 | $config->saveIfModified(); 89 | 90 | Bootstrap::getSQL()->setup($config); 91 | } 92 | 93 | /** 94 | * @param IUser $user 95 | * @return array 96 | */ 97 | public function getAll(IUser $user) : array { 98 | $fetch = $this->sql->table($this->table)->select()->where((!empty($user->getName()) && !empty($user->getId()) ? "id = ? AND username = ?" : (!empty($user->getName()) ? "username = ?" : "id = ?")), (!empty($user->getName()) && !empty($user->getId()) ? [$user->getId(), $user->getName()] : (!empty($user->getName()) ? [$user->getName()] : [$user->getId()])))->fetch(); 99 | 100 | return !$fetch ? [] : $fetch; 101 | } 102 | 103 | /** 104 | * @param IUser $user 105 | * @param array $data 106 | * @return boolean 107 | */ 108 | public function set(IUser $user, array $data) : bool { 109 | return $this->sql->table($this->table)->update()->fields($data)->where("id = ?", [$user->getId()])->execute(); 110 | } 111 | 112 | /** 113 | * @param array $data 114 | * @return boolean 115 | */ 116 | public function create(array $data) : bool { 117 | $insert = $this->sql->table($this->table)->insert()->fields($data); 118 | 119 | return $insert->execute(); 120 | } 121 | 122 | /** 123 | * @param IUser $user 124 | * @return boolean 125 | */ 126 | public function delete(IUser $user) : bool { 127 | return $this->sql->table($this->table)->delete()->where("id = ?", $user->getId())->execute(); 128 | } 129 | 130 | /** 131 | * @param string $field 132 | * @param mixed $value 133 | * @return array 134 | */ 135 | public function getUserBy(string $field, $value) : array { 136 | $fetch = $this->sql->table($this->table)->select()->where("{$field} = ?", $value)->limit(1)->fetch(); 137 | 138 | return !$fetch ? [] : $fetch; 139 | } 140 | 141 | /** 142 | * @param string $field 143 | * @param mixed $value 144 | * @param integer $limit 145 | * @param string|null $orderBy 146 | * @return array 147 | */ 148 | public function getUsersBy(string $field, $value, int $limit = 0, ?string $orderBy = null) : array { 149 | $fetchAll = $this->sql->table($this->table)->select()->where("{$field} = ?", $value)->orderBy($orderBy)->limit($limit)->fetchAll(); 150 | 151 | return !$fetchAll ? [] : $fetchAll; 152 | } 153 | 154 | /** 155 | * @param string $field 156 | * @param mixed $value 157 | * @param integer $limit 158 | * @param string|null $orderBy 159 | * @return array 160 | */ 161 | public function getUsersNotEqual(string $field, $value, int $limit = 0, ?string $orderBy = null) : array { 162 | $fetchAll = $this->sql->table($this->table)->select()->where("{$field} = ?", $value)->orderBy($orderBy)->limit($limit)->fetchAll(); 163 | 164 | return !$fetchAll ? [] : $fetchAll; 165 | } 166 | 167 | /** 168 | * @param string $field 169 | * @param mixed $value 170 | * @param integer $limit 171 | * @param string|null $orderBy 172 | * @return array 173 | */ 174 | public function getUsersByMultiple(string $fields, array $values, int $limit = 0, ?string $orderBy = null) : array { 175 | $fetchAll = $this->sql->table($this->table)->select()->where($fields, $values)->orderBy($orderBy)->limit($limit)->fetchAll(); 176 | 177 | return !$fetchAll ? [] : $fetchAll; 178 | } 179 | 180 | /** 181 | * Get users table name. 182 | * 183 | * @return string 184 | */ 185 | public function getTable(): string { 186 | return $this->table; 187 | } 188 | 189 | /** 190 | * Set users table name. 191 | * 192 | * @param string $table 193 | * @return void 194 | */ 195 | public function setTable(string $table): void { 196 | $this->table = $table; 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /micro-advanced/user/UserFactory.php: -------------------------------------------------------------------------------- 1 | setup(); 63 | } 64 | 65 | /** 66 | * @return UserFactory 67 | */ 68 | public static function getInstance() : ?UserFactory { 69 | return self::$instance; 70 | } 71 | 72 | /** 73 | * Get data provider. 74 | * 75 | * @return IProvider 76 | */ 77 | public static function getProvider() : IProvider { 78 | return self::$provider; 79 | } 80 | 81 | /** 82 | * Set data provider. 83 | * 84 | * @param IProvider $provider 85 | * @return void 86 | */ 87 | public static function setProvider(IProvider $provider) : void { 88 | self::$provider = $provider; 89 | } 90 | 91 | /** 92 | * Get the User object namespace. 93 | * 94 | * @return string 95 | */ 96 | public static function getUserObject() : string { 97 | return self::$userObject; 98 | } 99 | 100 | /** 101 | * Modify the User object namespace. 102 | * 103 | * @param string $object 104 | * @return void 105 | */ 106 | public static function setUserObject(string $object) : void { 107 | self::$userObject = $object; 108 | } 109 | 110 | /** 111 | * Get the Guest object namespace. 112 | * 113 | * @return string 114 | */ 115 | public static function getGuestObject() : string { 116 | return self::$guestObject; 117 | } 118 | 119 | /** 120 | * Modify the Guest object namespace. 121 | * 122 | * @return string 123 | */ 124 | public static function setGuestObject(string $object) : void { 125 | self::$guestObject = $object; 126 | } 127 | 128 | /** 129 | * Create user object. 130 | * 131 | * @param array $data 132 | * @param string|null $password If you want to sign in using $user->authenticate(), put the non-hashed password here. 133 | * @return User 134 | */ 135 | public function createUser(array $data, ?string $password = null) : User { 136 | $user = new self::$userObject($data, $password); 137 | 138 | return $user; 139 | } 140 | 141 | /** 142 | * Get user by username. 143 | * 144 | * @param string $name 145 | * @param string|null $password If you want to sign in using $user->authenticate(), put the non-hashed password here. 146 | * @return User 147 | */ 148 | public function getUser(string $name, ?string $password = null) : ?User { 149 | $return = null; 150 | 151 | if (($data = self::$provider->getUserBy("username", $name))) return $this->createUser($data, $password); 152 | 153 | return $return; 154 | } 155 | 156 | /** 157 | * Get user by ID. 158 | * 159 | * @param integer $id 160 | * @param string|null $password If you want to sign in using $user->authenticate(), put the non-hashed password here. 161 | * @return User 162 | */ 163 | public function getUserById(int $id, ?string $password = null) : ?User { 164 | $return = null; 165 | 166 | if (($data = self::$provider->getUserBy("id", $id))) return $this->createUser($data, $password); 167 | 168 | return $return; 169 | } 170 | 171 | /** 172 | * Get user by mail. 173 | * 174 | * @param string $mail 175 | * @param string|null $password If you want to sign in using $user->authenticate(), put the non-hashed password here. 176 | * @return User 177 | */ 178 | public function getUserByMail(string $mail, ?string $password = null) : ?User { 179 | $return = null; 180 | 181 | if (($data = self::$provider->getUserBy("mail", $mail))) return $this->createUser($data, $password); 182 | 183 | return $return; 184 | } 185 | 186 | /** 187 | * Get last users registered. 188 | * 189 | * @param integer $limit 190 | * @return User[] 191 | */ 192 | public function getLastUsers(int $limit = 1) : array { 193 | return $this->getTopUsers("id", $limit); 194 | } 195 | 196 | /** 197 | * Get random users 198 | * 199 | * @param integer $limit 200 | * @return User[] 201 | */ 202 | public function getRandomUsers(int $limit = 1) : array { 203 | $users = []; 204 | 205 | $data = self::$provider->getUsersNotEqual("username", "", $limit, "RAND()"); 206 | 207 | foreach ($data as $user) $users[$user["id"]] = $this->createUser($user); 208 | 209 | return $users; 210 | } 211 | 212 | /** 213 | * Get users by IP 214 | * 215 | * @param string $ip 216 | * @param integer $limit 217 | * @return User[] 218 | */ 219 | public function getUsersByIp(string $ip, int $limit = 1) : array { 220 | $users = []; 221 | 222 | // Users 223 | $data = self::$provider->getUsersByMultiple("ip_last LIKE ? OR ip_reg LIKE ?", [$ip, $ip], $limit); 224 | 225 | foreach ($data as $user) $users[$user["id"]] = $this->createUser($user); 226 | 227 | return $users; 228 | } 229 | 230 | /** 231 | * Get users ordered by a column from from highest to lowest. 232 | * 233 | * @param string $column 234 | * @param integer $limit 235 | * @return array 236 | */ 237 | public function getTopUsers(string $column, int $limit = 1) : array { 238 | $users = []; 239 | 240 | // Users 241 | $data = self::$provider->getUsersNotEqual("username", "", $limit, "{$column} DESC"); 242 | 243 | foreach ($data as $user) $users[$user["id"]] = $this->createUser($user); 244 | 245 | return $users; 246 | } 247 | } 248 | 249 | -------------------------------------------------------------------------------- /micro-advanced/config/Config.php: -------------------------------------------------------------------------------- 1 | data = $default; 75 | 76 | $this->initial = $default; 77 | 78 | $this->updateProvider($provider); 79 | 80 | $this->file = new File($file . $this->provider->getExtension()); 81 | 82 | if (empty(self::$files[$this->file->getPath()])) $this->update($default); else $this->data = self::$files[$this->file->getPath()]; 83 | } 84 | 85 | /** 86 | * @return Config 87 | */ 88 | public function getInstance() : IConfig { 89 | return self::$instance; 90 | } 91 | 92 | /** 93 | * Set config data. 94 | * 95 | * @param string $key 96 | * @param mixed $value 97 | * @return Config 98 | */ 99 | public function set(string $key, $value): IConfig { 100 | $values = &$this->data; 101 | 102 | foreach (($properties = explode(".", $key)) as $k => $segment) { 103 | if ((!isset($values[$segment]) || !is_array($values[$segment])) && $k != count($properties) - 1) $values[$segment] = []; 104 | 105 | $values = &$values[$segment]; 106 | } 107 | 108 | $values = $value; 109 | 110 | self::$files[$this->file->getPath()] = $this->data; 111 | 112 | return $this; 113 | } 114 | 115 | /** 116 | * Set config data if not exists. 117 | * 118 | * @param string $key 119 | * @param mixed $value 120 | * @return Config 121 | */ 122 | public function setIfNotExists(string $key, $value) : IConfig { 123 | if (!$this->has($key)) $this->set($key, $value); 124 | 125 | return $this; 126 | } 127 | 128 | /** 129 | * Save if file has been modified. 130 | * 131 | * @return void 132 | */ 133 | public function saveIfModified() : void { 134 | if ($this->initial != $this->data) $this->save(); 135 | } 136 | 137 | /** 138 | * Save file. 139 | * 140 | * @return void 141 | */ 142 | public function save() : void { 143 | $this->file->write($this->provider->prettyPrint($this->data)); 144 | 145 | $this->initial = $this->data; 146 | 147 | self::$files[$this->file->getPath()] = $this->data; 148 | } 149 | 150 | /** 151 | * Get config field. 152 | * 153 | * @param string $key 154 | * @param mixed $default 155 | * @return mixed 156 | */ 157 | public function get(string $key, $default = null) { 158 | if (!is_array($this->data)) $this->data = []; 159 | 160 | if (array_key_exists($key, $this->data)) return $this->data[$key]; 161 | 162 | if (strpos($key, ".") === false) return $default; 163 | 164 | $values = $this->data; 165 | 166 | foreach (explode(".", $key) as $segment) { 167 | if (!is_array($values) || !array_key_exists($segment, $values)) return $default; 168 | 169 | $values = $values[$segment]; 170 | } 171 | 172 | return $values; 173 | } 174 | 175 | /** 176 | * Get all data. 177 | * 178 | * @return array 179 | */ 180 | public function getAll() : array { 181 | return $this->data; 182 | } 183 | 184 | /** 185 | * Check if config has method. 186 | * 187 | * @param string $key 188 | * @return boolean 189 | */ 190 | public function has(string $key) : bool { 191 | return ($this->get($key) !== null); 192 | } 193 | 194 | /** 195 | * Delete a config field. 196 | * 197 | * @param string $key 198 | * @return void 199 | */ 200 | public function delete(string $key): void { 201 | $values = &$this->data; 202 | 203 | foreach (($properties = explode(".", $key)) as $k => $segment) { 204 | if ((!isset($values[$segment]) || !is_array($values[$segment])) && $k != count($properties) - 1) $values[$segment] = []; 205 | 206 | $values = &$values[$segment]; 207 | } 208 | 209 | unset($values); 210 | 211 | self::$files[$this->file->getPath()] = $this->data; 212 | } 213 | 214 | /** 215 | * @return File|null 216 | */ 217 | public function getFile() : ?File { 218 | return $this->file; 219 | } 220 | 221 | /** 222 | * @var string 223 | */ 224 | public function updateProvider(string $provider) : void { 225 | switch ($provider) { 226 | case self::PROVIDER_JSON: 227 | default: 228 | $this->provider = new JsonProvider(); 229 | break; 230 | 231 | case self::PROVIDER_YAML: 232 | $this->provider = new JsonProvider(); 233 | break; 234 | } 235 | } 236 | 237 | /** 238 | * @return IProvider|null 239 | */ 240 | public function getProvider() : ?IProvider { 241 | return $this->provider; 242 | } 243 | 244 | /** 245 | * Update config. 246 | * 247 | * @param array $default 248 | * @return void 249 | */ 250 | private function update(array $default = null) : void { 251 | $this->file->create(!$default ? $this->provider->encode([]) : $this->provider->prettyPrint($default)); 252 | 253 | $this->data = $this->provider->decode($this->file->read()); 254 | 255 | if ($this->data === null) throw new ConfigException(0, "exception.config.invalid_format", $this->file->getPath()); 256 | 257 | $this->initial = $this->data; 258 | 259 | self::$files[$this->file->getPath()] = $this->data; 260 | } 261 | } 262 | --------------------------------------------------------------------------------