/**
  * @param string $serialized
  */
 public final function unserialize($serialized)
 {
     $props = unserialize($serialized);
     $reflect = new \ReflectionClass($this);
     /** @var $prop \ReflectionProperty */
     foreach ($reflect->getProperties() as $prop) {
         $key = $prop->getName();
         $this->{$key} = $props[$key] ?? null;
     }
     $this->schemaTable = Schema::getTable($this->schemaTable);
     call_user_func_array([$this, "callBack"], Schema::getCallbackArgs());
 }
示例#2
0
 /**
  * Load configuration to bootstrap Kernel
  */
 private function loadConfig()
 {
     // Read configuration if not already
     $this->readConfig();
     // Databases
     if (property_exists($this->config, "databases")) {
         // Database component defined in container?
         if ($this->container->has("Database")) {
             $this->setDatabases($this->config->databases);
         }
         // Fluent/ORM callback args
         Schema::setCallbackArgs($this);
         // Remove databases node from config
         unset($this->config->databases);
     }
     // Site
     if (property_exists($this->config, "site")) {
         // Build a URL from given props.
         if (!property_exists($this->config->site, "url")) {
             $domain = $this->config->site->domain ?? null;
             $https = $this->config->site->https ?? null;
             $port = intval($this->config->site->port ?? 0);
             if (!empty($domain)) {
                 $this->config->site->url = sprintf('%s://%s%s/', $https === true ? "https" : "http", $domain, $port > 0 ? sprintf(':%d', $port) : '');
             }
         }
     }
     // App
     if (property_exists($this->config, "app")) {
         // Timezone
         if (property_exists($this->config->app, "timeZone")) {
             $this->dateTime->setTimeZone($this->config->app->timeZone);
         }
         // Error Handler
         if (property_exists($this->config->app, "errorHandler")) {
             // Format
             if (property_exists($this->config->app->errorHandler, "format")) {
                 $this->errorHandler->setFormat($this->config->app->errorHandler->format);
             }
             // Flag for handling triggered error messages
             $this->errorHandler->setFlag(Kernel::ERRORS_COLLECT);
             if (property_exists($this->config->app->errorHandler, "hideErrors")) {
                 if (!$this->config->app->errorHandler->hideErrors) {
                     $this->errorHandler->setFlag(Kernel::ERRORS_DEFAULT);
                 }
             }
         }
         // Security
         if (property_exists($this->config->app, "security")) {
             // Cipher Component
             if (isset($this->cipher)) {
                 // Configure Cipher
                 $this->registerCipher();
             }
             // Remove security prop. from config->app
             unset($this->config->app->security);
         }
         // Mailer
         if ($this->container->has("Mailer")) {
             // Register Mailer
             $this->registerMailer();
         }
         // Cache
         if ($this->container->has("Cache")) {
             // Register Cache
             $this->registerCache();
         }
         // Sessions
         if ($this->container->has("Session")) {
             // Register Session
             $this->registerSession();
         }
         // Translator
         if ($this->container->has("Translator")) {
             $this->registerTranslator();
         }
         // Knit
         if ($this->container->has("Knit")) {
             $this->registerKnit();
         }
     }
 }
示例#3
0
 /**
  * Using OOP magic to create magical findBy* methods
  * Arguments:
  * First = (mixed) Value to search in database with
  * Second = (int) Number of rows to return
  * Third = (bool) Throw exception on no rows found or return false?
  *
  * @param $name
  * @param $arguments
  * @throws SchemaException
  * @return object|bool|array
  */
 public static final function __callStatic($name, $arguments)
 {
     // Check if necessary constants are defined
     if (!defined("static::SCHEMA_TABLE")) {
         throw SchemaException::tableInitConstant("SCHEMA_TABLE");
     } elseif (!defined("static::SCHEMA_MODEL")) {
         throw SchemaException::tableInitConstant("SCHEMA_MODEL");
     }
     $tableNameConstant = constant("static::SCHEMA_TABLE");
     $modelNameConstant = constant("static::SCHEMA_MODEL");
     // Check if calling findBy* method
     if (substr($name, 0, 6) === "findBy") {
         $findBy = substr($name, 6);
         $findValue[] = $arguments[0] ?? null;
         $findLimit = 1;
         if (array_key_exists(1, $arguments)) {
             // Check if fetch limit is explicitly provided
             if (is_int($arguments[1])) {
                 // Fetch limit is provided and is an Integer
                 $findLimit = $arguments[1];
             } else {
                 // Fetch limit must be an Integer
                 throw SchemaException::badArgType(__METHOD__, 2, "integer", gettype($arguments[1]));
             }
         }
         // Throw exception is row not found?
         $throwException = true;
         if (isset($arguments[2]) && $arguments[2] === false) {
             $throwException = false;
         }
         // Convert PascalCase/camelCase to snake_case
         $findBy = Comely::snakeCase($findBy);
         // SELECT query
         $findQuery = sprintf('SELECT * FROM `%1$s` WHERE `%2$s`=? LIMIT %3$s', $tableNameConstant, $findBy, $findLimit);
         // Run Query
         $tableName = get_called_class();
         $db = Schema::getTable($tableName)->getDb();
         $rows = $db->query($findQuery, $findValue, Database::QUERY_FETCH);
         // Row(s) were found?
         if (empty($rows)) {
             // No rows were found
             if ($throwException) {
                 throw new SchemaException($name, "No rows were returned from database", 1201);
             } else {
                 // Return FALSE
                 return false;
             }
         }
         // Check if SCHEMA_MODEL constant is set
         $modelClass = $modelNameConstant;
         $callbackArgs = Schema::getCallbackArgs();
         if (!is_null($modelClass)) {
             if ($findLimit === 1) {
                 // Return single model instance
                 $model = new $modelClass($tableName, $rows[0]);
                 // Arguments injection
                 if (method_exists($model, "callBack")) {
                     $model->callBack(...$callbackArgs);
                 }
                 return $model;
             } else {
                 $models = [];
                 // Iterate through rows
                 foreach ($rows as $row) {
                     $model = new $modelClass($tableName, $row);
                     // Arguments injection
                     if (method_exists($model, "callBack")) {
                         $model->callBack(...$callbackArgs);
                     }
                     $models[] = $model;
                 }
                 // return indexed Array containing Model's instances
                 return $models;
             }
         } else {
             // Model is not set, return fetched Array
             return $findLimit === 1 ? $rows[0] : $rows;
         }
     }
     // Throw undefined method exception
     throw SchemaException::undefinedMethod($name);
 }
示例#4
0
 /**
  * Fluent constructor.
  *
  * When directly constructing a model that extends Fluent, no argument should be passed as these parameters accept
  * NULL values and they are only intended to be filled by AbstractTable::findBy[COL*] method
  *
  * @param string|null $table
  * @param array|null $row
  * @throws FluentException
  */
 public final function __construct(string $table = null, array $row = null)
 {
     // Set modelName
     $this->modelName = get_called_class();
     // Check if table relation is defined
     if (!defined("static::SCHEMA_TABLE")) {
         throw FluentException::initConstant("SCHEMA_TABLE", $this->modelName);
     }
     $modelSchemaTable = constant("static::SCHEMA_TABLE");
     // Check if $table is provided for cross-checking
     if (!is_null($table)) {
         // Cross-check $table with model's SCHEMA_TABLE
         if ($table !== $modelSchemaTable) {
             // On fail, Cross-check if $table has SCHEMA_TABLE constant and that matches
             $tableConstant = sprintf("%s::SCHEMA_TABLE", $table);
             if (!defined($tableConstant) || constant($tableConstant) !== $modelSchemaTable) {
                 // Model and table are NOT related
                 throw FluentException::tableModelMismatch($this->modelName, $modelSchemaTable, $table);
             }
         }
     }
     // Save AbstractTable instance
     $this->schemaTable = Schema::table($modelSchemaTable);
     // Bootstrap data mapping
     $this->private = [];
     // Check if $row is Array
     if (is_array($row)) {
         // Verify that $row has all columns defined for AbstractTable
         $columnsKeys = $this->schemaTable->getColumnsKeys();
         foreach ($columnsKeys as $column) {
             if (!array_key_exists($column, $row)) {
                 throw FluentException::missingColumn($column, $this->modelName);
             }
         }
         // Get all columns
         $columns = $this->schemaTable->getColumns();
         // Data mapping
         foreach ($row as $key => $value) {
             // Get column
             switch ($columns[$key]->scalarType) {
                 case "integer":
                     $value = (int) $value;
                     break;
                 case "double":
                     $d = $columns[$key]->attributes["d"];
                     $value = round($value, $d + 1);
                     break;
                 default:
                     break;
             }
             // Sort this key as public or private?
             $camelKey = Comely::camelCase($key);
             if (property_exists($this->modelName, $camelKey)) {
                 // Public property
                 $this->{$camelKey} = $value;
             } else {
                 // Private variable
                 $this->private[$camelKey] = $value;
             }
         }
     }
 }
示例#5
0
 /**
  * @param Database $db
  * @return StorageInterface
  */
 public static function Database(Database $db) : StorageInterface
 {
     Schema::loadTable($db, "Comely\\IO\\Session\\Storage\\Database");
     return Schema::table("comely_sessions");
 }