isundil il y a 10 ans
Parent
commit
ba8d66cbd0

+ 43 - 11
core/models/ModelBase.php

@@ -16,7 +16,7 @@ abstract class ModelBase
 	{
         self::init();
         $this->id = null;
-        if ($id !== null)
+        if ($id !== null && is_numeric($id))
             $this->selectById($id);
 	}
 
@@ -78,6 +78,8 @@ abstract class ModelBase
     {
         if ($key == "meta")
             return $this->getMeta();
+        if ($key == "id")
+            return $this->id;
         if (!isset($this->fieldsValues[$key]))
             return null;
         return $this->fieldsValues[$key];
@@ -97,14 +99,16 @@ abstract class ModelBase
 
     public function save()
     {
-        \Tools\Hook::trigger("onBeforeEntitySave");
-        \Tools\Hook::trigger("onBeforeEntitySave".$this->getTableName());
+        \Tools\Hooks::trigger("onBeforeEntitySave");
+        \Tools\Hooks::trigger("onBeforeEntitySave".$this->getTableName());
         if ($this->id === null)
         {
             if (empty ($this->changed))
             {
-                //TODO
-                return true;
+                $query = "INSERT INTO `{$this->getTableName()}` () VALUES ()";
+                $result = self::$dbo->exec($query);
+                if (!$result)
+                    throw new \Exception(self::$dbo->errorInfo()[2]);
             }
             else
             {
@@ -114,7 +118,7 @@ abstract class ModelBase
                     throw new \Exception(self::$dbo->errorInfo()[2]);
                 $this->changed = array();
             }
-                //TODO get last id
+            $this->id = self::$dbo->lastInsertId();
         }
         else
         {
@@ -133,11 +137,11 @@ abstract class ModelBase
                 $this->changed = array();
             }
         }
-        \Tools\Hook::trigger("onAfterEntitySave");
-        \Tools\Hook::trigger("onAfterEntitySave".$this->getTableName());
+        \Tools\Hooks::trigger("onAfterEntitySave");
+        \Tools\Hooks::trigger("onAfterEntitySave".$this->getTableName());
     }
 
-    public function selects($criteria = null)
+    public function selects($criteria = null, $orderBy = null)
     {
         $query = "SELECT * FROM {$this->getTableName()}";
 
@@ -148,11 +152,35 @@ abstract class ModelBase
             {
                 if ($j == null)
                     $subQuery[] = "`{$i}` IS NULL";
+                else if (is_array($j))
+                {
+                    $inArray = [];
+                    foreach ($j as $k)
+                        $inArray[] = self::$dbo->quote($k);
+                    $subQuery[] = "`{$i}` IN (".implode(",", $inArray).")";
+                }
                 else
                     $subQuery[] = "`{$i}`=".self::$dbo->quote($j);
             }
             $query .= " WHERE ".implode(" AND ", $subQuery);
         }
+        if (!empty($orderBy))
+        {
+            $_orderBy = array();
+            foreach ($orderBy as $i => $j)
+            {
+                if (is_numeric($i))
+                    $_orderBy[] = "`{$j}` ASC";
+                else
+                {
+                    $orderType = "ASC";
+                    if (strtoupper($j == "DESC"))
+                        $orderType = "DESC";
+                    $_orderBy[] = "`{$i}` {$orderType}";
+                }
+            }
+            $query .= " ORDER BY ".implode(",", $_orderBy);
+        }
         $result = self::$dbo->query($query, \PDO::FETCH_ASSOC);
         if ($result === false)
             throw new \Exception(self::$dbo->errorInfo()[2]);
@@ -160,16 +188,20 @@ abstract class ModelBase
         $className = get_class($this);
         foreach ($result as $i)
         {
-            $iObj = new $className($this);
+            $iObj = new $className();
             $iObj->populate($i);
             $resultObj[] = $iObj;
         }
         return $resultObj;
     }
 
-    //TODO@1
     public function selectById($id)
     {
+        $query = "SELECT * FROM {$this->getTableName()} WHERE id=".(int)$id." LIMIT 1";
+        $result = self::$dbo->query($query, \PDO::FETCH_ASSOC);
+        if ($result === false)
+            throw new \Exception("Cannot fetch data: ".self::$dbo->errorInfo()[2]);
+        $this->populate($result);
     }
 
     private function populate($data)

+ 1 - 2
core/models/ModuleHook.php

@@ -23,8 +23,7 @@ class ModuleHook extends ModelBase
     public static function getModules($moduleIds)
     {
         $fetcher = new self();
-        //TODO@1 order by
-        return $fetcher->selects(array("module_id" => $moduleIds));
+        return $fetcher->selects(array("module_id" => $moduleIds), array("hookName", "hookPosition"));
     }
 }
 

+ 93 - 0
core/tools/AModule.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace Tools;
+
+/**
+ * Module superclass
+ * Contains all informations about the module
+**/
+abstract class AModule
+{
+    /**
+     * @var \Tools\Context $context
+     * /core/tools/Context.php
+     * Website context
+     * Can be accessed read-only
+    **/
+    private $context;
+
+    /**
+     * @var Module database object
+    **/
+    private $entity;
+
+    /**
+     * Called on module install
+     * Should register shortcodes and Hooks
+    **/
+    public abstract function install();
+
+    /**
+     * Called on module unsinstall
+    **/
+    public function uninstall()
+    { }
+
+    /**
+     * @param \Tools\HookEvent $event called hook
+     * /core/tools/HookEvent.php
+     * Called on hook reception
+    **/
+    public abstract function doAction($event);
+
+    /**
+     * @param string $shortCode
+     * @param array ( key => value ) shortcode's parameters
+     * Called on shortcode reception
+    **/
+    public abstract function doShortCode($shortCode, $params);
+
+    /**
+     * @param \Tools\Context $context
+     * /core/tools/Context.php
+     * set the application context
+     * Will work only one time
+    **/
+    public function setContext($context)
+    {
+        if ($this->context === null)
+            $this->context = $context;
+    }
+
+    /**
+     * @param \Entity\Module $module
+     * /core/models/Module.php
+     * set the module database object
+     * Will work only one time
+    **/
+    public function setEntity($entity)
+    {
+        if ($this->entity === null)
+            $this->entity = $entity;
+    }
+
+    public function __get($key)
+    {
+        switch ($key)
+        {
+            case "context": return $this->context; break;
+            case "entity": return $this->entity; break;
+        }
+        throw new \Exception("Cannot access attribute {$key}");
+    }
+
+	/**
+	 * Register hook to be triggered
+	 * Can only be triggered while module setup
+	**/
+    public static function registerHook($hookName)
+    {
+        $this->context->hooks->register($this, $hookname);
+    }
+}
+

+ 1 - 1
core/tools/Context.php

@@ -58,7 +58,7 @@ class Context
     public function __construct()
     {
         $this->hookManager = new Hooks($this);
-        $this->router = new Router();
+        $this->router = new Router($this);
         if (!\Entity\ModelBase::init())
         {
             @require_once(getcwd().'/core/setup/index.php');

+ 28 - 0
core/tools/HookEvent.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace Tools;
+
+class HookEvent
+{
+    private $context;
+    private $hookName;
+    private $params;
+
+    public function __construct($hookName, $context, $params)
+    {
+        $this->context = $context;
+        $this->hookName = $hookName;
+        $this->params = $params;
+    }
+
+    public function __get($key)
+    {
+        switch ($key)
+        {
+            case "hookName": return $this->hookName; break;
+            case "params": return $this->params; break;
+        }
+        throw new \Exception("Cannot access attribute {$key}");
+    }
+}
+

+ 61 - 5
core/tools/Hooks.php

@@ -14,12 +14,29 @@ class Hooks
     **/
     private $context;
 
+    /**
+     * @var array( string: hookName => module Id )
+    **/
+    private $hooks;
+
+    /**
+     * @var SplStack $currentHook
+     * Contains current trigerred event
+    **/
+    private $currentHook;
+
+    /**
+     * @var \Tools\HookEvent $currentHook
+     * get current hook event
+     **/
+
     /**
      * ctor. Initialize context for having them passed to hook as parameter
     **/
-    public function __construct($context)
+    public function __construct(&$context)
     {
         $this->context = $context;
+        $this->currentHook = array();
     }
 
     /**
@@ -38,13 +55,40 @@ class Hooks
 
     /**
      * @param string $hookName
+     * @return number of modules successfully reached
      * fire the hook hookName
-     * call the AModule::doAction($hookName, $context) function for each attached modules
+     * call the AModule::doAction($hookEvent) function for each attached modules
     **/
-    public function trigger($hookName)
+    public function trigger($hookName, $params =null)
     {
-        echo "Triggering hook `{$hookName}'";
-        //TODO@2
+        if (empty($this->hooks[$hookName]))
+            return 0;
+        $hookEvent = new HookEvent($hookName, $this->context, $params);
+        array_push($this->currentHook, $hookEvent);
+        $result = 0;
+        foreach ($this->hooks[$hookName] as $module_id)
+        {
+            $module = $this->context->moduleManager->getModuleFromId($module_id);
+            if (!$module)
+                continue;
+            $module->doAction($hookEvent);
+            $result++;
+        }
+        array_pop($this->currentHook);
+        return $result;
+    }
+
+    /**
+     * @param string $hookName
+     * @return boolean
+     * Check if $hookName is treating
+    **/
+    public function isInHook($hookName)
+    {
+        foreach ($this->currentHook as $i)
+            if ($i->hookName == $hookName)
+                return true;
+        return false;
     }
 
     /**
@@ -53,6 +97,18 @@ class Hooks
     **/
     public function loadHooks($hookEntities)
     {
+        $this->hooks = array();
+        foreach ($hookEntities as $i)
+            $this->hooks[$i->hookName][] = (int) $i->module_id;
+    }
+
+    public function __get($key)
+    {
+        switch ($key)
+        {
+            case "currentHook": return end($this->currentHook);
+        }
+        throw new \Exception("Cannot access attribute {$key}");
     }
 }
 

+ 32 - 3
core/tools/ModuleManager.php

@@ -23,13 +23,19 @@ class ModuleManager
     **/
     private $modules = array();
 
+    /**
+     * @var _id_{ID}
+     * Get the module identified with id ID
+     * ex: $context->moduleManager->_id_2 will return module with id 2
+    **/
+
     /**
      * @param \Tool\Context $context
      * Load all active modules from database.
      * Enable hooks for these modules
      * Disable them if the module cannot be loaded
     **/
-    public function __construct($context)
+    public function __construct(&$context)
     {
         $this->context = $context;
         $modulesRoot = $context->router->modulesPath;
@@ -44,11 +50,12 @@ class ModuleManager
             }
             else
             {
+                die ("out");
                 $i->active = false;
                 $i->save();
             }
         }
-        \Tools\Hooks::loadHooks(\Entity\ModuleHook::getModules($ids));
+        $context->hookManager->loadHooks(\Entity\ModuleHook::getModules($ids));
     }
 
     /**
@@ -63,7 +70,12 @@ class ModuleManager
     **/
     private function loadModule($path, $module)
     {
-        $this->modules[] = $module;
+        $mod = include_once($path);
+        if (!$mod || !($mod instanceof \Tools\AModule))
+            return false;
+        $mod->setContext($this->context);
+        $mod->setEntity($module);
+        $this->modules[] = $mod;
         return true;
     }
 
@@ -86,6 +98,21 @@ class ModuleManager
         }
     }
 
+    /**
+     * @param int $id
+     * @return AModule on success, FALSE on failure (no such ID / module not loaded)
+     * Get the module identified with id ID
+    **/
+    public function getModuleFromId($id)
+    {
+        foreach ($this->modules as $i)
+        {
+            if ($i->entity->id == $id)
+                return $i;
+        }
+        return FALSE;
+    }
+
     public function __get($key)
     {
         switch ($key)
@@ -93,6 +120,8 @@ class ModuleManager
             case "modules":
                 return $this->modules; break;
         }
+        if (substr($key, 0, 4) == "_id_")
+            return $this->getModuleFromId((int) substr($key, 4));
         throw new \Exception("Cannot access attribute {$key}");
     }
 }

+ 76 - 7
core/tools/Router.php

@@ -22,31 +22,67 @@ class Router
     **/
     private $rootUrl;
 
+    /**
+     * @var string $requestUrl
+     * Contains request
+    **/
+    private $requestUrl;
+
+    /**
+     * @var array ( array ( uri => controller ) ) $routes
+     **/
+    private $routes;
+
+    /**
+     * @var \Tools\Context $context
+     * /core/tools/Context.php
+     * Contains website's informations
+    **/
+    private $context;
+
     /**
      * @var string $modulePath
      * Contains the module directory
     **/
 
+    /**
+     * @var string $moduleUrl
+     * Contains the module Uri
+    **/
+
+    /**
+     * @var string $themePath
+     * Contains the theme directory
+    **/
+
+    /**
+     * @var string $themeUrl
+     * Contains the theme Uri
+    **/
+
     /**
      * Create the router, initialize url and path
     **/
-    public function __construct()
+    public function __construct($context)
     {
         $pos = strrpos($_SERVER["SCRIPT_NAME"], "/");
         $relativePath = (($pos === FALSE) ? "" : substr($_SERVER["SCRIPT_NAME"], 0, $pos));
         $this->rootPath = $_SERVER["DOCUMENT_ROOT"] . $relativePath . "/";
         $this->rootUrl = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . $relativePath ."/";
+        $this->requestUrl = substr($_SERVER["REQUEST_URI"], count($this->rootUrl) -1);
+        $this->context = $context;
+        $this->routes = array();
     }
 
     /**
-     * TODO@1 This function SHOULD be disabled by configuration
      * Called after database initialization
      * Check the site url and redirect user if the HOST does not match
+     * If the site url is not defined in database, do not redirect
     **/
     public function init()
     {
         $siteUrl = \Entity\Config::getConfig(null, "siteUrl");
-        if ($siteUrl != $_SERVER["HTTP_HOST"])
+        if ($siteUrl != $_SERVER["HTTP_HOST"] && $siteUrl !== null)
         {
             header("location: http://{$siteUrl}{$_SERVER['REQUEST_URI']}");
             die;
@@ -62,6 +98,11 @@ class Router
     public function serveUrl()
     {
         $this->prepareUrl();
+        $requestParams = explode("/", $this->requestUrl);
+        foreach ($this->routes as $i)
+        {
+            $routeParams = explode("/", $i[0]);
+        }
         //TODO@2
     }
 
@@ -71,12 +112,36 @@ class Router
     **/
     private function prepareUrl()
     {
-        //TODO@2 add internal route config
+        $this->doRouteAdd("/:item", "\Controller\Product");
+        $this->doRouteAdd("/:category/:item", "\Controller\Product");
+    }
+
+	/**
+	 * Add a route to the internal route list
+	 * Internal procedure
+	**/
+    private function doRouteAdd($route, $controller)
+    {
+        $this->routes[] = array($route, $controller);
+    }
+
+	/**
+	 * @param string $route Uri to match the controller
+	 * Uri can be formatted as '/:param/static'.
+	 * expl. '/product/:id/'
+	 * @param string $controller Controller class name.
+	 * new $controller() MUST return a \Tool\AController instance
+	 *
+	 * Add a route and a Controller to the list
+	 * Can only be called from `routerSetup' hook
+	**/
+    public function routeAdd($route, $controller)
+    {
+        if (!$this->context->hookManager->isInHook("routerSetup"))
+            throw new \Exception("You can only add routes from `routerSetup' hook");
+        $this->doRouteAdd($route, $controller);
     }
 
-    /**
-     * TODO@1 check end of tag to format url and paths
-    **/
     public function __get($key)
     {
         switch ($key)
@@ -84,7 +149,11 @@ class Router
         case "rootPath": return $this->rootPath; break;
         case "rootUrl": return $this->rootUrl; break;
         case "modulesPath": return $this->rootPath."content/modules/"; break;
+        case "modulesUrl": return $this->rootUrl."content/modules/"; break;
+        case "themesPath": return $this->rootPath."content/theme/"; break;
+        case "themesUrl": return $this->rootUrl."content/theme/"; break;
         }
+        throw new \Exception("Cannot access attribute {$key}");
     }
 }