-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0b13b66
Showing
22 changed files
with
1,180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/vendor/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<?php | ||
/** | ||
* @link https://framework.iziweb.net | ||
* @copyright Copyright (c) 2021 Izi Software LLC | ||
* @license https://framework.iziweb.net/license | ||
*/ | ||
|
||
namespace app\core; | ||
|
||
use app\controllers\Controller; | ||
use app\core\db\Database; | ||
use app\core\db\DbModel; | ||
|
||
/** | ||
* Class Application | ||
* @package app\core | ||
* @author Giàng A Tỉn <vantruong1898@gmail.com> | ||
* @since 1.0 | ||
* @var $userClass app\models\User | ||
*/ | ||
class Application | ||
{ | ||
public string $layout = 'main'; | ||
public string $userClass; | ||
public static string $ROOT_DIR; | ||
public Router $router; | ||
public Request $request; | ||
public Response $response; | ||
public Session $session; | ||
public Database $db; | ||
public ?DbModel $user; | ||
public ?Controller $controller = null; | ||
public View $view; | ||
public static Application $app; | ||
|
||
public function __construct($rootPath, array $config) | ||
{ | ||
self::$ROOT_DIR = $rootPath; | ||
self::$app = $this; | ||
$this->userClass = $config['user']['class']; | ||
$this->request = new Request(); | ||
$this->response = new Response(); | ||
$this->session = new Session(); | ||
$this->router = new Router($this->request, $this->response); | ||
$this->db = new Database($config['db']); | ||
$this->view = new View(); | ||
|
||
$primaryValue = $this->session->get('user'); | ||
if($primaryValue){ | ||
$primaryKey = $this->userClass::primaryKey(); | ||
$this->user = $this->userClass::findOne([$primaryKey => $primaryValue]); | ||
}else{ | ||
$this->user = null; | ||
} | ||
|
||
} | ||
|
||
public function run() | ||
{ | ||
try{ | ||
echo $this->router->resolve(); | ||
}catch (\Exception $e){ | ||
$this->response->setStatusCode($e->getCode()); | ||
echo $this->view->renderView('_error', [ | ||
'exception' => $e | ||
]); | ||
} | ||
} | ||
|
||
/** | ||
* @return Controller | ||
*/ | ||
public function getController(): Controller | ||
{ | ||
return $this->controller; | ||
} | ||
|
||
/** | ||
* @param Controller $controller | ||
*/ | ||
public function setController(Controller $controller): void | ||
{ | ||
$this->controller = $controller; | ||
} | ||
|
||
public function login(DbModel $user): bool | ||
{ | ||
$this->user = $user; | ||
$primaryKey = $user->primaryKey(); | ||
$primaryValue = $user->{$primaryKey}; | ||
$this->session->set('user', $primaryValue); | ||
return true; | ||
} | ||
|
||
public function logout() | ||
{ | ||
$this->user = null; | ||
$this->session->remove('user'); | ||
} | ||
|
||
public static function isGuest(): bool | ||
{ | ||
return !self::$app->user; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
<?php | ||
/** | ||
* @link https://framework.iziweb.net | ||
* @copyright Copyright (c) 2021 Izi Software LLC | ||
* @license https://framework.iziweb.net/license | ||
*/ | ||
|
||
namespace app\core; | ||
|
||
/** | ||
* Class Model | ||
* | ||
* @package app\core | ||
* @author Giang A Tin <vantruong1898@gmail.com> | ||
* @since 1.0 | ||
*/ | ||
abstract class Model | ||
{ | ||
public const RULE_REQUIRED = 'required'; | ||
public const RULE_EMAIL = 'email'; | ||
public const RULE_MIN = 'min'; | ||
public const RULE_MAX = 'max'; | ||
public const RULE_MATCH = 'match'; | ||
public const RULE_UNIQUE = 'unique'; | ||
|
||
abstract public function rules() : array; | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function labels(): array | ||
{ | ||
return []; | ||
} | ||
|
||
/** | ||
* @param $attribute | ||
* @return mixed | ||
*/ | ||
public function getLabel($attribute) | ||
{ | ||
return $this->labels()[$attribute] ?? $attribute; | ||
} | ||
/** | ||
* @param array $data | ||
*/ | ||
public function loadData(array $data) | ||
{ | ||
foreach ($data as $key=>$value){ | ||
if(property_exists($this, $key)){ | ||
$this->{$key} = $value; | ||
} | ||
} | ||
} | ||
|
||
public array $errors = []; | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function validate(): bool | ||
{ | ||
foreach ($this->rules() as $attribute => $rules){ | ||
$value = $this->{$attribute}; | ||
foreach ($rules as $rule){ | ||
$ruleName = $rule; | ||
if(!is_string($ruleName)){ | ||
$ruleName = $rule[0]; | ||
} | ||
|
||
if($ruleName === self::RULE_REQUIRED && !$value){ | ||
$this->addErrorForRule($attribute, self::RULE_REQUIRED); | ||
} | ||
|
||
if($ruleName === self::RULE_EMAIL && !filter_var($value, FILTER_VALIDATE_EMAIL)){ | ||
$this->addErrorForRule($attribute, self::RULE_EMAIL); | ||
} | ||
|
||
if($ruleName === self::RULE_MIN && strlen($value) < $rule['min']){ | ||
$this->addErrorForRule($attribute, self::RULE_MIN, $rule); | ||
} | ||
|
||
if($ruleName === self::RULE_MAX && strlen($value) > $rule['max']){ | ||
$this->addErrorForRule($attribute, self::RULE_MAX, $rule); | ||
} | ||
if($ruleName === self::RULE_MATCH && $value !== $this->{$rule['match']}){ | ||
$rule['match'] = $this->getLabel($rule['match']); | ||
$this->addErrorForRule($attribute, self::RULE_MATCH, $rule); | ||
} | ||
|
||
if($ruleName === self::RULE_UNIQUE){ | ||
$className = $rule['class']; | ||
$uniqueAttr = $rule['attribute'] ?? $attribute; | ||
$tableName = $className::tableName(); | ||
|
||
$statement = Application::$app->db->prepare("SELECT * FROM $tableName WHERE $uniqueAttr = :attr"); | ||
$statement->bindValue(":attr", $value); | ||
$statement->execute(); | ||
$record = $statement->fetchObject(); | ||
if($record){ | ||
$this->addErrorForRule($attribute, self::RULE_UNIQUE, ['field' => $this->getLabel($attribute)]); | ||
} | ||
|
||
} | ||
|
||
|
||
} | ||
} | ||
|
||
return empty($this->errors); | ||
|
||
} | ||
|
||
/** | ||
* @param string $attribute | ||
* @param string $rule | ||
* @param array $params | ||
*/ | ||
private function addErrorForRule(string $attribute, string $rule, $params = []) | ||
{ | ||
$message = $this->errorMessages()[$rule] ?? ''; | ||
|
||
foreach ($params as $key => $value){ | ||
$message = str_replace("{{$key}}","<b>$value</b>", $message); | ||
} | ||
|
||
$this->errors[$attribute][] = $message; | ||
} | ||
|
||
public function addError(string $attribute, string $message) | ||
{ | ||
$this->errors[$attribute][] = $message; | ||
} | ||
|
||
/** | ||
* @return string[] | ||
*/ | ||
public function errorMessages(): array | ||
{ | ||
return [ | ||
self::RULE_REQUIRED => 'This field is required', | ||
self::RULE_EMAIL => 'This field must be valid email address', | ||
self::RULE_MIN => 'Min length of this field must be {min}', | ||
self::RULE_MAX => 'Max length of this field must be {max}', | ||
self::RULE_MATCH => 'This field must be the same as {match}', | ||
self::RULE_UNIQUE => 'Record with this field {field} already existed', | ||
]; | ||
} | ||
|
||
|
||
/** | ||
* @param $attribute | ||
* @return false|mixed | ||
*/ | ||
public function hasError($attribute) | ||
{ | ||
return $this->errors[$attribute] ?? false; | ||
} | ||
|
||
/** | ||
* @param $attribute | ||
* @return false|mixed | ||
*/ | ||
public function getFirstError($attribute) | ||
{ | ||
return $this->errors[$attribute][0] ?? false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# izi-framework | ||
PHP MVC Framework |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
/** | ||
* @link https://framework.iziweb.net | ||
* @copyright Copyright (c) 2021 Izi Software LLC | ||
* @license https://framework.iziweb.net/license | ||
*/ | ||
|
||
namespace app\core; | ||
|
||
/** | ||
* Class Request | ||
* | ||
* @package app\core | ||
* @author Giang A Tin <vantruong1898@gmail.com> | ||
* @since 1.0 | ||
*/ | ||
class Request | ||
{ | ||
public function getPath() | ||
{ | ||
$path = $_SERVER['REQUEST_URI'] ?? '/'; | ||
$position = strpos($path, '?'); | ||
if($position === false){ | ||
return $path; | ||
} | ||
|
||
return substr($path,0, $position); | ||
} | ||
|
||
public function method(): string | ||
{ | ||
return strtolower($_SERVER['REQUEST_METHOD']); | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function isGet(): bool | ||
{ | ||
return $this->method() === 'get'; | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function isPost(): bool | ||
{ | ||
return $this->method() === 'post'; | ||
} | ||
|
||
public function getBody() | ||
{ | ||
$body = []; | ||
if($this->method() === 'get' && !empty($_GET)){ | ||
foreach ($_GET as $key => $value){ | ||
$body[$key] = filter_input(INPUT_GET, $key, FILTER_SANITIZE_SPECIAL_CHARS); | ||
} | ||
} | ||
|
||
if($this->method() === 'post' && !empty($_POST)){ | ||
foreach ($_POST as $key => $value){ | ||
$body[$key] = filter_input(INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS); | ||
} | ||
} | ||
|
||
|
||
return $body; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
/** | ||
* @link https://framework.iziweb.net | ||
* @copyright Copyright (c) 2021 Izi Software LLC | ||
* @license https://framework.iziweb.net/license | ||
*/ | ||
|
||
namespace app\core; | ||
|
||
/** | ||
* Class Response | ||
* | ||
* @package app\core | ||
* @author Giang A Tin <vantruong1898@gmail.com> | ||
* @since 1.0 | ||
*/ | ||
class Response | ||
{ | ||
public function setStatusCode(int $code) | ||
{ | ||
http_response_code($code); | ||
} | ||
|
||
public function redirect(string $url, int $code = 302) | ||
{ | ||
header("Location: $url", true, $code); | ||
} | ||
} |
Oops, something went wrong.