init commit
in it to delet it
This commit is contained in:
parent
f85e93b789
commit
8140d14f41
13 changed files with 360 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -8,6 +8,9 @@ Desktop.ini
|
||||||
# Recycle Bin used on file shares
|
# Recycle Bin used on file shares
|
||||||
$RECYCLE.BIN/
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# PHPStorm folder
|
||||||
|
.idea/*
|
||||||
|
|
||||||
# Windows Installer files
|
# Windows Installer files
|
||||||
*.cab
|
*.cab
|
||||||
*.msi
|
*.msi
|
||||||
|
|
4
.htaccess
Normal file
4
.htaccess
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Options -MultiViews
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.php [QSA,L]
|
67
AroMVC/AroModel.php
Normal file
67
AroMVC/AroModel.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Core;
|
||||||
|
|
||||||
|
abstract class AroModel {
|
||||||
|
protected $rawData = [];
|
||||||
|
protected $associations = [];
|
||||||
|
protected $hooks = [];
|
||||||
|
protected $index = "id";
|
||||||
|
protected $deleted = false;
|
||||||
|
|
||||||
|
public function __construct() {}
|
||||||
|
public static function withId(int $id) {
|
||||||
|
$new = new static();
|
||||||
|
$new->initialize();
|
||||||
|
|
||||||
|
return $new;
|
||||||
|
}
|
||||||
|
public static function withRow(array $row) {
|
||||||
|
$new = new static();
|
||||||
|
$new->initialize();
|
||||||
|
array_walk($row, function($v, $k) use (&$new) {
|
||||||
|
$new->rawData[strtolower($k)] = $v;
|
||||||
|
});
|
||||||
|
return $new;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract function initialize();
|
||||||
|
|
||||||
|
public function __get(string $name) {
|
||||||
|
$name = strtolower($name);
|
||||||
|
|
||||||
|
if(array_key_exists($name, $this->hooks))
|
||||||
|
return $this->hooks[$name]();
|
||||||
|
else if(array_key_exists($name, $this->associations))
|
||||||
|
return $this->rawData[$this->associations[$name]];
|
||||||
|
else if(array_key_exists($name, $this->rawData))
|
||||||
|
return $this->rawData[$name];
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __set(string $name, $value) {
|
||||||
|
$name = strtolower($name);
|
||||||
|
|
||||||
|
if(array_key_exists($name, $this->associations))
|
||||||
|
$rawData[$this->associations[$name]] = $value;
|
||||||
|
else if(array_key_exists($name, $this->rawData))
|
||||||
|
$rawData[$name] = $value;
|
||||||
|
else
|
||||||
|
throw new \Exception("Cannot set the value for property '$name'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addHook(string $name, $func) {
|
||||||
|
$this->hooks[strtolower($name)] = $func;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addAssociation(string $associationName, string $rawName) {
|
||||||
|
$this->associations[strtolower($associationName)] = strtolower($rawName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function delete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
9
AroMVC/Database.php
Normal file
9
AroMVC/Database.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Core;
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
private static $preparedQueries = [];
|
||||||
|
private static $rawQueries = [];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
57
AroMVC/Queryable.php
Normal file
57
AroMVC/Queryable.php
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Core;
|
||||||
|
|
||||||
|
define("AMVC_QRY_SEL_FROM", 1);
|
||||||
|
define("AMVC_QRY_SEL_JOINS", 2);
|
||||||
|
define("AMVC_QRY_SEL_NEEDON", 4);
|
||||||
|
define("AMVC_QRY_SEL_WHERE", 8);
|
||||||
|
define("AMVC_QRY_SEL_GROUP", 16);
|
||||||
|
define("AMVC_QRY_SEL_HAVING", 32);
|
||||||
|
define("AMVC_QRY_SEL_ORDER", 64);
|
||||||
|
define("AMVC_QRY_SEL_LIMIT", 128);
|
||||||
|
|
||||||
|
abstract class Queryable {
|
||||||
|
protected $query = [];
|
||||||
|
protected $results = null;
|
||||||
|
protected $flags = 0;
|
||||||
|
protected $allowConditionals = true;
|
||||||
|
|
||||||
|
public function and(string $condition) {
|
||||||
|
if(!$this->allowConditionals)
|
||||||
|
throw new \Exception("Query type does not allow AND/OR subclauses");
|
||||||
|
|
||||||
|
array_push($this->query, "AND", $condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function or(string $condition) {
|
||||||
|
if(!$this->allowConditionals)
|
||||||
|
throw new \Exception("Query type does not allow AND/OR subclauses");
|
||||||
|
|
||||||
|
array_push($this->query, "OR", $condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(array $params) {
|
||||||
|
// TODO execution logic
|
||||||
|
var_dump($this->query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setFlag(int $flag) {
|
||||||
|
$this->flags = $this->flags | $flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function clearFlag(int $flag) {
|
||||||
|
$this->flags = $this->flags & ~$flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkFlag(int $flag): bool {
|
||||||
|
return ($this->flags & $flag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkPast(int $flag): bool {
|
||||||
|
return ~(($flag - 1) | $flag) & $this->flags != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkForOrPast(int $flag): bool {
|
||||||
|
return $this->checkFlag($flag) || $this->checkPast($flag);
|
||||||
|
}
|
||||||
|
}
|
6
AroMVC/Router.php
Normal file
6
AroMVC/Router.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Core;
|
||||||
|
|
||||||
|
class Router {
|
||||||
|
|
||||||
|
}
|
163
AroMVC/Selectable.php
Normal file
163
AroMVC/Selectable.php
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Core;
|
||||||
|
|
||||||
|
class Selectable extends Queryable {
|
||||||
|
public function __construct($selection) {
|
||||||
|
if(is_array($selection))
|
||||||
|
$selection = implode(",", $selection);
|
||||||
|
|
||||||
|
$this->query = ["SELECT", $selection];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(array $params): Selectable {
|
||||||
|
if($this->checkFlag(AMVC_QRY_SEL_NEEDON))
|
||||||
|
throw new \Exception("JOIN clause declared in query with no matching ON clause");
|
||||||
|
|
||||||
|
if($this->checkFlag(AMVC_QRY_SEL_GROUP) && !$this->checkFlag(AMVC_QRY_SEL_ORDER)) {
|
||||||
|
if($this->checkFlag(AMVC_QRY_SEL_HAVING)) {
|
||||||
|
$having = array_search("HAVING", $this->query);
|
||||||
|
array_splice($this->query, $having + 2, 0, ["ORDER BY", "null"]);
|
||||||
|
} else {
|
||||||
|
$group = array_search("GROUP BY", $this->query);
|
||||||
|
array_splice($this->query, $group + 2, 0, ["ORDER BY", "null"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::execute($params);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkFrom() {
|
||||||
|
if(!$this->checkFlag(AMVC_QRY_SEL_FROM))
|
||||||
|
throw new \Exception("FROM clause must come first in a SELECT query");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function from(string $where): Selectable {
|
||||||
|
if($this->checkFlag(AMVC_QRY_SEL_FROM))
|
||||||
|
throw new \Exception("Cannot declare second FROM clause on a SELECT query");
|
||||||
|
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_FROM);
|
||||||
|
array_push($this->query, "FROM", $where);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function join(string $type, string $table): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
if($this->checkPast(AMVC_QRY_SEL_JOINS))
|
||||||
|
throw new \Exception("Invalid JOIN clause, must proceed FROM clause");
|
||||||
|
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_JOINS);
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_NEEDON);
|
||||||
|
array_push($this->query, $type, $table);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function on(string $condition): Selectable {
|
||||||
|
if(!$this->checkFlag(AMVC_QRY_SEL_NEEDON))
|
||||||
|
throw new \Exception("Cannot declare ON clause without prior JOIN clause");
|
||||||
|
|
||||||
|
$this->clearFlag(AMVC_QRY_SEL_NEEDON);
|
||||||
|
array_push($this->query, "ON", $condition);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function using($columns): Selectable {
|
||||||
|
if(!$this->checkFlag(AMVC_QRY_SEL_NEEDON))
|
||||||
|
throw new \Exception("Cannot declare USING clause without prior JOIN clause");
|
||||||
|
|
||||||
|
if(is_array($columns))
|
||||||
|
$columns = implode(",", $columns);
|
||||||
|
|
||||||
|
$this->clearFlag(AMVC_QRY_SEL_NEEDON);
|
||||||
|
array_push($this->query, "USING", "({$columns})");
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where(string $condition): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
if($this->checkForOrPast(AMVC_QRY_SEL_WHERE))
|
||||||
|
throw new \Exception("Duplicate or misplaced WHERE clause in SELECT query");
|
||||||
|
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_WHERE);
|
||||||
|
array_push($this->query, "WHERE", $condition);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function and(string $condition): Selectable {
|
||||||
|
if(!$this->checkFlag(AMVC_QRY_SEL_FROM))
|
||||||
|
throw new \Exception("Cannot use AND subclause until FROM clause has been declared in SELECT query");
|
||||||
|
|
||||||
|
parent::and($condition);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function or(string $condition): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
parent::or($condition);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function groupBy($columns): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
if($this->checkForOrPast(AMVC_QRY_SEL_GROUP))
|
||||||
|
throw new \Exception("Duplicate or misplaced GROUP BY clause in SELECT query");
|
||||||
|
|
||||||
|
if(is_array($columns))
|
||||||
|
$columns = implode(",", $columns);
|
||||||
|
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_GROUP);
|
||||||
|
array_push($this->query, "GROUP BY", $columns);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function having(string $condition): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
if($this->checkForOrPast(AMVC_QRY_SEL_HAVING))
|
||||||
|
throw new \Exception("Duplicate or misplaced HAVING clause in SELECT query");
|
||||||
|
|
||||||
|
array_push($this->query, "HAVING", $condition);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orderBy($columns): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
if($this->checkForOrPast(AMVC_QRY_SEL_ORDER))
|
||||||
|
throw new \Exception("Duplicate or misplaced ORDER BY clause in SELECT query");
|
||||||
|
|
||||||
|
if(is_array($columns))
|
||||||
|
$columns = implode(",", $columns);
|
||||||
|
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_ORDER);
|
||||||
|
array_push($this->query, "ORDER BY", $columns);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function limit(int $count, int $offset = 0): Selectable {
|
||||||
|
$this->checkFrom();
|
||||||
|
if($this->checkForOrPast(AMVC_QRY_SEL_LIMIT))
|
||||||
|
throw new \Exception("Duplicate or misplaced LIMIT clause in SELECT query");
|
||||||
|
|
||||||
|
$this->setFlag(AMVC_QRY_SEL_LIMIT);
|
||||||
|
array_push($this->query, "LIMIT", "$offset,$count");
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function asArray() {
|
||||||
|
if($this->results == null)
|
||||||
|
throw new \Exception("Cannot return results from a query that has not executed.");
|
||||||
|
|
||||||
|
return $this->results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function asModels($obj) {
|
||||||
|
if($this->results == null)
|
||||||
|
throw new \Exception("Cannot return results from a query that has not executed.");
|
||||||
|
|
||||||
|
$type = new \ReflectionClass($obj);
|
||||||
|
if(!$type->isSubclassOf("\\AroMVC\\Core\\AroModel"))
|
||||||
|
throw new \Exception("Cannot instantiate non-model object.");
|
||||||
|
|
||||||
|
foreach($this->results as $result)
|
||||||
|
yield $type->getMethod("withRow")->invoke(null, $result);
|
||||||
|
}
|
||||||
|
}
|
5
Controllers/Home.php
Normal file
5
Controllers/Home.php
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Home {
|
||||||
|
|
||||||
|
}
|
7
Models/Company.php
Normal file
7
Models/Company.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Models;
|
||||||
|
use \AroMVC\Core\AroModel;
|
||||||
|
|
||||||
|
class Company extends AroModel {
|
||||||
|
|
||||||
|
}
|
7
Models/State.php
Normal file
7
Models/State.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC\Models;
|
||||||
|
use \AroMVC\Core;
|
||||||
|
|
||||||
|
class State extends AroModel {
|
||||||
|
|
||||||
|
}
|
1
Views/Home/Index.php
Normal file
1
Views/Home/Index.php
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?php
|
18
auto.php
Normal file
18
auto.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
spl_autoload_register(function($class) {
|
||||||
|
$class = str_replace("_", "\\", $class);
|
||||||
|
$class = ltrim($class, '\\');
|
||||||
|
|
||||||
|
$parts = explode("\\", $class);
|
||||||
|
if($parts[0] == "AroMVC") {
|
||||||
|
if(count($parts) < 3)
|
||||||
|
die("Autoloader failed: malformed class name $class");
|
||||||
|
|
||||||
|
if($parts[1] == "Core")
|
||||||
|
require_once "AroMVC". DIRECTORY_SEPARATOR . $parts[2] .".php";
|
||||||
|
else if(in_array($parts[1], ["Controllers", "Models", "ViewModels"]))
|
||||||
|
require_once $parts[1]. DIRECTORY_SEPARATOR. $parts[2] .".php";
|
||||||
|
else
|
||||||
|
die("Autoloader failed: malformed class name $class");
|
||||||
|
}
|
||||||
|
});
|
13
index.php
Normal file
13
index.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
namespace AroMVC;
|
||||||
|
include "auto.php";
|
||||||
|
use AroMVC\Core\Selectable;
|
||||||
|
use AroMVC\Models\Company;
|
||||||
|
|
||||||
|
$tmp = new Selectable("*");
|
||||||
|
|
||||||
|
$tmp->from("Companies")
|
||||||
|
->where("`name` = ?")
|
||||||
|
->or("`id` = ?")
|
||||||
|
->execute(["dekko", 12])
|
||||||
|
->asModels(new Company);
|
Reference in a new issue