Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
thecodeholic committed Jul 26, 2020
0 parents commit 831487c
Show file tree
Hide file tree
Showing 19 changed files with 1,012 additions and 0 deletions.
84 changes: 84 additions & 0 deletions Application.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php
/**
* User: TheCodeholic
* Date: 7/7/2020
* Time: 9:57 AM
*/

namespace app\core;

use app\core\db\Database;

/**
* Class Application
*
* @author Zura Sekhniashvili <[email protected]>
* @package app
*/
class Application
{
public static Application $app;
public static string $ROOT_DIR;
public string $userClass;
public string $layout = 'main';
public Router $router;
public Request $request;
public Response $response;
public ?Controller $controller = null;
public Database $db;
public Session $session;
public View $view;
public ?UserModel $user;

public function __construct($rootDir, $config)
{
$this->user = null;
$this->userClass = $config['userClass'];
self::$ROOT_DIR = $rootDir;
self::$app = $this;
$this->request = new Request();
$this->response = new Response();
$this->router = new Router($this->request, $this->response);
$this->db = new Database($config['db']);
$this->session = new Session();
$this->view = new View();

$userId = Application::$app->session->get('user');
if ($userId) {
$key = $this->userClass::primaryKey();
$this->user = $this->userClass::findOne([$key => $userId]);
}
}

public static function isGuest()
{
return !self::$app->user;
}

public function login(UserModel $user)
{
$this->user = $user;
$primaryKey = $user->primaryKey();
$value = $user->{$primaryKey};
Application::$app->session->set('user', $value);

return true;
}

public function logout()
{
$this->user = null;
self::$app->session->remove('user');
}

public function run()
{
try {
echo $this->router->resolve();
} catch (\Exception $e) {
echo $this->router->renderView('_error', [
'exception' => $e,
]);
}
}
}
49 changes: 49 additions & 0 deletions Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* User: TheCodeholic
* Date: 7/8/2020
* Time: 8:43 AM
*/

namespace app\core;

use app\core\middlewares\BaseMiddleware;
/**
* Class Controller
*
* @author Zura Sekhniashvili <[email protected]>
* @package app\core
*/
class Controller
{
public string $layout = 'main';
public string $action = '';

/**
* @var \app\core\BaseMiddleware[]
*/
protected array $middlewares = [];

public function setLayout($layout): void
{
$this->layout = $layout;
}

public function render($view, $params = []): string
{
return Application::$app->router->renderView($view, $params);
}

public function registerMiddleware(BaseMiddleware $middleware)
{
$this->middlewares[] = $middleware;
}

/**
* @return \app\core\middlewares\BaseMiddleware[]
*/
public function getMiddlewares(): array
{
return $this->middlewares;
}
}
141 changes: 141 additions & 0 deletions Model.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php
/**
* User: TheCodeholic
* Date: 7/8/2020
* Time: 9:16 AM
*/

namespace app\core;


/**
* Class Model
*
* @author Zura Sekhniashvili <[email protected]>
* @package app\core
*/
class Model
{
const RULE_REQUIRED = 'required';
const RULE_EMAIL = 'email';
const RULE_MIN = 'min';
const RULE_MAX = 'max';
const RULE_MATCH = 'match';
const RULE_UNIQUE = 'unique';

public array $errors = [];

public function loadData($data)
{
foreach ($data as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}

public function attributes()
{
return [];
}

public function labels()
{
return [];
}

public function getLabel($attribute)
{
return $this->labels()[$attribute] ?? $attribute;
}

public function rules()
{
return [];
}

public function validate()
{
foreach ($this->rules() as $attribute => $rules) {
$value = $this->{$attribute};
foreach ($rules as $rule) {
$ruleName = $rule;
if (!is_string($rule)) {
$ruleName = $rule[0];
}
if ($ruleName === self::RULE_REQUIRED && !$value) {
$this->addErrorByRule($attribute, self::RULE_REQUIRED);
}
if ($ruleName === self::RULE_EMAIL && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
$this->addErrorByRule($attribute, self::RULE_EMAIL);
}
if ($ruleName === self::RULE_MIN && strlen($value) < $rule['min']) {
$this->addErrorByRule($attribute, self::RULE_MIN, ['min' => $rule['min']]);
}
if ($ruleName === self::RULE_MAX && strlen($value) > $rule['max']) {
$this->addErrorByRule($attribute, self::RULE_MAX);
}
if ($ruleName === self::RULE_MATCH && $value !== $this->{$rule['match']}) {
$this->addErrorByRule($attribute, self::RULE_MATCH, ['match' => $rule['match']]);
}
if ($ruleName === self::RULE_UNIQUE) {
$className = $rule['class'];
$uniqueAttr = $rule['attribute'] ?? $attribute;
$tableName = $className::tableName();
$db = Application::$app->db;
$statement = $db->prepare("SELECT * FROM $tableName WHERE $uniqueAttr = :$uniqueAttr");
$statement->bindValue(":$uniqueAttr", $value);
$statement->execute();
$record = $statement->fetchObject();
if ($record) {
$this->addErrorByRule($attribute, self::RULE_UNIQUE);
}
}
}
}
return empty($this->errors);
}

public function errorMessages()
{
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 with this {field} already exists',
];
}

public function errorMessage($rule)
{
return $this->errorMessages()[$rule];
}

protected function addErrorByRule(string $attribute, string $rule, $params = [])
{
$params['field'] ??= $attribute;
$errorMessage = $this->errorMessage($rule);
foreach ($params as $key => $value) {
$errorMessage = str_replace("{{$key}}", $value, $errorMessage);
}
$this->errors[$attribute][] = $errorMessage;
}

public function addError(string $attribute, string $message)
{
$this->errors[$attribute][] = $message;
}

public function hasError($attribute)
{
return $this->errors[$attribute] ?? false;
}

public function getFirstError($attribute)
{
$errors = $this->errors[$attribute] ?? [];
return $errors[0] ?? '';
}
}
59 changes: 59 additions & 0 deletions Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* User: TheCodeholic
* Date: 7/7/2020
* Time: 10:23 AM
*/

namespace app\core;


/**
* Class Request
*
* @author Zura Sekhniashvili <[email protected]>
* @package thecodeholic\mvc
*/
class Request
{
public function getMethod()
{
return strtolower($_SERVER['REQUEST_METHOD']);
}

public function getUrl()
{
$path = $_SERVER['REQUEST_URI'];
$position = strpos($path, '?');
if ($position !== false) {
$path = substr($path, 0, $position);
}
return $path;
}

public function isGet()
{
return $this->getMethod() === 'get';
}

public function isPost()
{
return $this->getMethod() === 'post';
}

public function getBody()
{
$data = [];
if ($this->isGet()) {
foreach ($_GET as $key => $value) {
$data[$key] = filter_input(INPUT_GET, $key, FILTER_SANITIZE_SPECIAL_CHARS);
}
}
if ($this->isPost()) {
foreach ($_POST as $key => $value) {
$data[$key] = filter_input(INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS);
}
}
return $data;
}
}
28 changes: 28 additions & 0 deletions Response.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
/**
* User: TheCodeholic
* Date: 7/7/2020
* Time: 10:53 AM
*/

namespace app\core;


/**
* Class Response
*
* @author Zura Sekhniashvili <[email protected]>
* @package app\core
*/
class Response
{
public function statusCode(int $code)
{
http_response_code($code);
}

public function redirect($url)
{
header("Location: $url");
}
}
Loading

0 comments on commit 831487c

Please sign in to comment.