Browse Source

* Don't make earray force convert into integer offsets
* on ORM remove each_where, make references to static::$table use static::table() and have static::table() handle initializing the table
* add ORM->count($filter)
* ORM models should be in the \Model namespace
* Add views and templates
* Add Table::each and make Table::fetch use it

Nathaniel van Diepen 7 years ago
parent
commit
13f90b5f13
5 changed files with 92 additions and 38 deletions
  1. 19 4
      App/view.abstract.class.php
  2. 1 1
      Data/earray.class.php
  3. 32 2
      Data/template.class.php
  4. 23 6
      PDO/table.class.php
  5. 17 25
      orm.abstract.class.php

+ 19 - 4
App/view.abstract.class.php

@@ -1,20 +1,35 @@
 <?php
 	namespace Juju\App;
+	require_once(realpath(dirname(__DIR__).'/Http/Response.class.php'));
+	require_once(realpath(dirname(__DIR__).'/Data/template.class.php'));
+	use Juju\Data\{Response, Template};
 
 	abstract class View {
-		private $name;
-		public abstract static function render(array $data);
-		public static function views(){
+		private  static $name;
+		protected static $template;
+		public static function views() : array{
 			return array_filter(get_declared_classes(), function($class){
 				return 0 === strpos($class, "View\\");
 			});
 		}
-		public static function name(){
+		public static function name() : string{
 			if(is_null(static::$name)){
 				$name = get_called_class();
 				return substr($name, strrpos($name, '\\') + 1);
 			}
 			return static::$name;
 		}
+		final public static function render(array $data = []) : string{
+			if(is_null(static::$template) && method_exists(get_called_class(), 'setup')){
+				static::setup();
+			}
+			$template = static::$template ?? static::name();
+			if(is_string($template)){
+				return Template::from($template, $data);
+			}elseif(is_array($template)){
+					$template = new Template($template['name'], $template['fn']);
+			}
+			return $template->run($data);
+		}
 	}
 ?>

+ 1 - 1
Data/earray.class.php

@@ -10,7 +10,7 @@
 			return new static($data);
 		}
 		protected function __construct(array $data){
-			$this->data = array_values($data);
+			$this->data = $data;
 		}
 		public function offsetExists($offset){
 			$this->fire('exists', $offset);

+ 32 - 2
Data/template.class.php

@@ -1,10 +1,40 @@
 <?php
 	namespace Juju\Data;
+	require_once(realpath(dirname(__DIR__).'/events.trait.php'));
+	require_once('earray.class.php');
+	use Juju\{Events, Data\EArray};
+	use \Exception;
 
 	class Template {
+		use Events;
 		private static $templates = [];
-		public function __construct(string $name, string $template){
-			
+		private $template;
+		private $name;
+		public function __construct(string $name, callable $template){
+			if(isset(static::$templates[$name])){
+				throw new Exception("Template {$name} already exists");
+			}
+			$this->template = $template;
+			$this->name = $name;
+			static::$templates[$name] = $this;
+		}
+		public function run(array $data) : string{
+			$data = EArray::from($data);
+			if($this->fire('before', $data) === false){
+				throw new Exception("Render on template {$this->name} cancelled. Before.");
+			}
+			$output = \Closure::FromCallable($this->template)->call($data);
+			if($this->fire('after', $output) === false){
+				throw new Exception("Render on template {$this->name} cancelled. After");
+			}
+			return (string)$output;
+		}
+		public static function from(string $name, array $data = []) : string{
+			$template = static::$templates[$name] ?? null;
+			if(is_null($template)){
+				throw new Exception("Template {$name} does not exist");
+			}
+			return $template->run($data);
 		}
 	}
 ?>

+ 23 - 6
PDO/table.class.php

@@ -363,15 +363,32 @@
 		public function delete(array $filter = null){
 			return $this->exists ? $this->pdo->exec("delete from `{$this->name}` {$this->pdo->stringFilter($filter)}") : 0;
 		}
-		public function fetch(array $filter = null){
+		public function fetch(array $columns = null, array $filter = null, int $start = null, int $amount = null){
+			$results = [];
+			$this->each(function($row) use($results){
+				$results[] = $row;
+			}, $columns, $filter, $start, $amount);
+			return $results;
+		}
+		public function each(callable $fn, array $columns = null, array $filter = null, int $start = null, int $amount = null){
 			if($this->exists){
-				$query = $this->pdo->query("select * from `{$this->name}` {$this->pdo->stringFilter($filter)}");
-				$results = $query->fetchAll();
+				$limit = '';
+				if(!is_null($start) && !is_null($amount)){
+					$limit .= " limit {$start}, {$amount}";
+				}
+				$columns = $columns ?? ['*'];
+				$cols = '';
+				foreach($columns as $column){
+					$cols .= "{$column},";
+				}
+				$cols = rtrim($cols, ',');
+				$query = $this->pdo->query("select {$cols} from `{$this->name}` {$this->pdo->stringFilter($filter)} {$limit}");
+				while($row = $query->fetch()){
+					$fn($row);
+				}
 				$query->closeCursor();
-			}else{
-				$results = [];
 			}
-			return $results;
+			return $this;
 		}
 		public function count(array $filter = null){
 			return $this->exists ? $this->pdo->exec("select 1 from `{$this->name}` {$this->pdo->stringFilter($filter)}") : 0;

+ 17 - 25
orm.abstract.class.php

@@ -157,11 +157,14 @@
 		public static function table_name(){
 			if(is_null(static::$table_name)){
 				$name = get_called_class();
-				return substr($name, strrpos($name, '\\') + 1);
+				static::$table_name = substr($name, strrpos($name, '\\') + 1);
 			}
 			return static::$table_name;
 		}
 		public static function table(){
+			if(is_null(static::$table)){
+				static::$table = self::$pdo->table(static::table_name());
+			}
 			return static::$table;
 		}
 		public static function primary_key(){
@@ -179,7 +182,6 @@
 			}
 			if($pdo instanceof PDO){
 				self::$pdo = $pdo;
-				self::$table = $pdo->table(static::table_name());
 				// @todo handle updating live instances
 			}else{
 				throw new \Exception("Invalid argument. Must pass a DSN string or a PDO instance");
@@ -233,7 +235,7 @@
 			return !is_null(self::cached_instance($id));
 		}
 		public static function delete(int $id){
-			return self::$table->delete([
+			return static::table()->delete([
 				static::primary_key() => $id
 			]) > 0;
 		}
@@ -243,27 +245,14 @@
 				array_walk(self::$instances[$name], $fn);
 			}
 		}
-		public static function each_where(callable $fn, array $filter = null, int $start = null, int $amount = null){
-			$limit = '';
-			if(!is_null($start) && !is_null($amount)){
-				$limit .= " limit {$start}, {$amount}";
-			}
-			$query = self::query(
-				"select ".static::primary_key().' id '.
-				"from ".static::table_name().' '.
-				self::$table->stringFilter($filter).
-				$limit
-			);
-			foreach($query->fetchAll() as $row){
+		public static function each(callable $fn, array $filter = null, int $start = null, int $amount = null){
+			static::table()->each(function($row) use($fn){
 				$fn(self::instance((int)$row['id']));
-			}
-		}
-		public static function each(callable $fn, int $start = null, int $amount = null){
-			self::each_where($fn, null, $start, $amount);
+			}, [static::primary_key()], $filter, $start, $amount);
 		}
 		public static function fetch(array $filter = null, int $start = null, int $amount = null){
 			$results = [];
-			self::each_where(function($item) use($results){
+			self::each(function($item) use($results){
 				$results[] = $item;
 			}, $filter, $start, $amount);
 			return $results;
@@ -279,6 +268,9 @@
 				return 0 === strpos($class, "Model\\");
 			});
 		}
+		public static function count(array $filter = null){
+			return static::table()->count($filter);
+		}
 		// Instance Api
 		public function values($values){
 			foreach($values as $key => $val){
@@ -317,11 +309,11 @@
 					}
 				}
 				if(!is_null($this->id) && !in_array(static::primary_key(), $this->_changed)){
-					self::$table->update($data, [
+					static::table()->update($data, [
 						static::primary_key() => $this->id
 					]);
 				}else{
-					self::$table->insert($data);
+					static::table()->insert($data);
 					$this->_data[static::primary_key()] = self::$pdo->lastInsertId();
 				}
 				foreach($this->_related as $related){
@@ -382,15 +374,15 @@
 				$aliases = self::$aliases[$this->name];
 				if(isset($aliases['belongs_to'][$name])){
 					$alias = $aliases['has_many'][$name];
-					$class = "\\Models\\{$alias['model']}";
+					$class = "\\Model\\{$alias['model']}";
 					$this->_related[$name] = $class::fetch([$alias['foreign_key'] => $this->id])[0];
 				}elseif(isset($aliases['has_one'][$name])){
 					$alias = $aliases['has_many'][$name];
-					$class = "\\Models\\{$alias['model']}";
+					$class = "\\Model\\{$alias['model']}";
 					$this->_related[$name] = $class::instance($this[$alias['foreign_key']]);
 				}elseif(isset($aliases['has_many'][$name])){
 					$alias = $aliases['has_many'][$name];
-					$class = "\\Models\\{$alias['model']}";
+					$class = "\\Model\\{$alias['model']}";
 					$sql = "select ";
 					if($alias['through']){
 						$sql .= $class::table_name().$class::foreign_key_suffix()." id from {$alias['through']} ";