Exemplo n.º 1
0
 /**
  * @covers Cougar\Cache\CacheFactory::getLocalCache
  */
 public function testGetMemoryCache()
 {
     $cache = CacheFactory::getMemoryCache();
     $this->assertinstanceOf("Cougar\\Cache\\Cache", $cache);
     $this->assertEquals("memory", $cache->getCacheType());
 }
Exemplo n.º 2
0
 /**
  * Initializes the REST resource. If properties are provided the resource
  * will be loaded. Otherwise, a new resource will be created on save().
  *
  * @history
  * 2013.09.30:
  *   (AT)  Initial release
  * 2014.08.06:
  *   (AT)  Turn the execution cache into a proper memory cache
  *
  * @version 2014.08.06
  * @author (AT) Alberto Trevino, Brigham Young Univ. <*****@*****.**>
  *
  * @param iSecurity $security Security context
  * @param iCache $cache Cache object
  * @param iRestClient $rest_client Rest client object
  * @param mixed $object Object or assoc. array of property values
  * @param string $view Set view on load
  * @param bool $strict Whether to perform strict property checking (on by default)
  * @throws \Cougar\Exceptions\Exception
  */
 public function __construct(iSecurity $security, iCache $cache, iRestClient $rest_client, $object = null, $view = null, $strict = true)
 {
     # Get a local and a memory cache
     # TODO: Set through static property(?)
     $local_cache = CacheFactory::getLocalCache();
     $execution_cache = CacheFactory::getMemoryCache();
     # Store the object references
     $this->__security = $security;
     $this->__cache = $cache;
     $this->__restClient = $rest_client;
     # Add the class name to the default cache prefix
     $this->__cachePrefix .= "." . get_class($this);
     # Create our own cache keys
     $class = get_class($this) . ".WsModel";
     $cache_key = Annotations::$annotationsCachePrefix . "." . $class;
     # Call the parent constructor
     $this->__constructModel(null, $view);
     # See if the execution cache has the object properties
     $parsed_annotations = $execution_cache->get($cache_key);
     if (!$parsed_annotations) {
         # See if the annotations came from the cache
         if ($this->__annotations->cached) {
             $parsed_annotations = $local_cache->get($cache_key);
         }
     }
     # See if we have pre-parsed annotations
     if ($parsed_annotations === false) {
         # Go through the class annotations
         foreach ($this->__annotations->class as $annotation) {
             switch ($annotation->name) {
                 case "Allow":
                     # Set all the operation to false
                     $this->__allowCreate = false;
                     $this->__allowRead = false;
                     $this->__allowUpdate = false;
                     $this->__allowDelete = false;
                     $this->__allowQuery = false;
                     # See which operations will be allowed
                     foreach (preg_split("/\\s+/u", strtolower($annotation->value)) as $operation) {
                         switch ($operation) {
                             case "create":
                                 $this->__allowCreate = true;
                                 break;
                             case "read":
                                 $this->__allowRead = true;
                                 break;
                             case "update":
                                 $this->__allowUpdate = true;
                                 break;
                             case "delete":
                                 $this->__allowDelete = true;
                                 break;
                             case "query":
                             case "list":
                                 $this->__allowQuery = true;
                                 break;
                         }
                     }
                     break;
                 case "BaseUri":
                     $values = preg_split("/\\s+/u", $annotation->value, 2);
                     if (ENVIRONMENT == strtolower($values[0])) {
                         $this->__baseUri = $values[1];
                     } else {
                         if (ENVIRONMENT == "local" && strtolower($values[0]) == "development" && !$this->__baseUri) {
                             $this->__baseUri = $values[1];
                         }
                     }
                     break;
                 case "ResourceID":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__resourceIds[] = $property;
                                 $this->__readOnly[$property] = true;
                             } else {
                                 throw new Exception("Specified Resource ID property " . $property . " does not exist");
                             }
                         }
                     }
                     break;
                 case "ReadOnly":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (array_key_exists($property, $this->__readOnly)) {
                                 $this->__readOnly[$property] = true;
                             } else {
                                 throw new Exception("Specified read-only property " . $property . " does not exist");
                             }
                         }
                     }
                     break;
                 case "Create":
                     if ($annotation->value) {
                         $values = preg_split("/\\s+/u", $annotation->value, 2);
                         switch (count($values)) {
                             case 2:
                                 $this->__createCall["method"] = $values[0];
                                 $this->__createCall["uri"] = $values[1];
                                 break;
                             case 1:
                                 $this->__createCall["method"] = $values[0];
                                 $this->__createCall["uri"] = "";
                                 break;
                         }
                     }
                     break;
                 case "CreateGetFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__createCall["get"][] = $property;
                             }
                         }
                     }
                     break;
                 case "CreatePostFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__createCall["post"][] = $property;
                             }
                         }
                     }
                     break;
                 case "CreateBody":
                     switch (strtolower($annotation->value)) {
                         case "xml":
                             $this->__createCall["bodyType"] = "xml";
                             break;
                         case "json":
                             $this->__createCall["bodyType"] = "json";
                             break;
                         case "php":
                             $this->__createCall["bodyType"] = "php";
                             break;
                         default:
                             throw new Exception("Invalid create call " . "body type: " . $annotation->value);
                     }
                     break;
                 case "Read":
                     if ($annotation->value) {
                         $values = preg_split("/\\s+/u", $annotation->value, 2);
                         switch (count($values)) {
                             case 2:
                                 $this->__readCall["method"] = $values[0];
                                 $this->__readCall["uri"] = $values[1];
                                 break;
                             case 1:
                                 $this->__readCall["method"] = $values[0];
                                 $this->__readCall["uri"] = "";
                                 break;
                         }
                     }
                     break;
                 case "ReadGetFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__readCall["get"][] = $property;
                             }
                         }
                     }
                     break;
                 case "ReadPostFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__readCall["post"][] = $property;
                             }
                         }
                     }
                     break;
                 case "ReadBody":
                     switch (strtolower($annotation->value)) {
                         case "xml":
                             $this->__readCall["bodyType"] = "xml";
                             break;
                         case "json":
                             $this->__readCall["bodyType"] = "json";
                             break;
                         case "php":
                             $this->__readCall["bodyType"] = "php";
                             break;
                         default:
                             throw new Exception("Invalid read call " . "body type: " . $annotation->value);
                     }
                     break;
                 case "Update":
                     if ($annotation->value) {
                         $values = preg_split("/\\s+/u", $annotation->value, 2);
                         switch (count($values)) {
                             case 2:
                                 $this->__updateCall["method"] = $values[0];
                                 $this->__updateCall["uri"] = $values[1];
                                 break;
                             case 1:
                                 $this->__updateCall["method"] = $values[0];
                                 $this->__updateCall["uri"] = "";
                                 break;
                         }
                     }
                     break;
                 case "UpdateGetFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__updateCall["get"][] = $property;
                             }
                         }
                     }
                     break;
                 case "UpdatePostFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__updateCall["post"][] = $property;
                             }
                         }
                     }
                     break;
                 case "UpdateBody":
                     switch (strtolower($annotation->value)) {
                         case "xml":
                             $this->__updateCall["bodyType"] = "xml";
                             break;
                         case "json":
                             $this->__updateCall["bodyType"] = "json";
                             break;
                         case "php":
                             $this->__updateCall["bodyType"] = "php";
                             break;
                         default:
                             throw new Exception("Invalid update call " . "body type: " . $annotation->value);
                     }
                     break;
                 case "Delete":
                     if ($annotation->value) {
                         $values = preg_split("/\\s+/u", $annotation->value, 2);
                         switch (count($values)) {
                             case 2:
                                 $this->__deleteCall["method"] = $values[0];
                                 $this->__deleteCall["uri"] = $values[1];
                                 break;
                             case 1:
                                 $this->__deleteCall["method"] = $values[0];
                                 $this->__deleteCall["uri"] = "";
                                 break;
                         }
                     }
                     break;
                 case "DeleteGetFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__deleteCall["get"][] = $property;
                             }
                         }
                     }
                     break;
                 case "DeletePostFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__deleteCall["post"][] = $property;
                             }
                         }
                     }
                     break;
                 case "DeleteBody":
                     switch (strtolower($annotation->value)) {
                         case "xml":
                             $this->__deleteCall["bodyType"] = "xml";
                             break;
                         case "json":
                             $this->__deleteCall["bodyType"] = "json";
                             break;
                         case "php":
                             $this->__deleteCall["bodyType"] = "php";
                             break;
                         default:
                             throw new Exception("Invalid delete call " . "body type: " . $annotation->value);
                     }
                     break;
                 case "Query":
                     if ($annotation->value) {
                         $values = preg_split("/\\s+/u", $annotation->value, 2);
                         switch (count($values)) {
                             case 2:
                                 $this->__queryCall["method"] = $values[0];
                                 $this->__queryCall["uri"] = $values[1];
                                 break;
                             case 1:
                                 $this->__queryCall["method"] = $values[0];
                                 $this->__queryCall["uri"] = "";
                                 break;
                         }
                     }
                     break;
                 case "QueryGetFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__queryCall["get"][] = $property;
                             }
                         }
                     }
                     break;
                 case "QueryPostFields":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__queryCall["post"][] = $property;
                             }
                         }
                     }
                     break;
                 case "QueryBody":
                     switch (strtolower($annotation->value)) {
                         case "xml":
                             $this->__queryCall["bodyType"] = "xml";
                             break;
                         case "json":
                             $this->__queryCall["bodyType"] = "json";
                             break;
                         case "php":
                             $this->__queryCall["bodyType"] = "php";
                             break;
                         default:
                             throw new Exception("Invalid query call " . "body type: " . $annotation->value);
                     }
                     break;
                 case "QueryList":
                     if ($annotation->value) {
                         foreach (preg_split("/\\s+/u", $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__queryProperties[] = $property;
                             } else {
                                 throw new Exception("Specified query property " . $property . " does not exist");
                             }
                         }
                     }
                     break;
                 case "QueryView":
                     if ($annotation->value) {
                         if (array_key_exists($annotation->value, $this->__views)) {
                             $this->__queryView = $annotation->value;
                         }
                     }
                     break;
                 case "NoQuery":
                     # Here for backward compatibility
                     $this->__allowQuery = false;
                     break;
                 case "CachePrefix":
                     if ($annotation->value) {
                         $this->__cachePrefix = $annotation->value;
                     }
                     break;
                 case "CacheTime":
                     if ($annotation->value) {
                         $this->__cacheTime = (int) $annotation->value;
                     }
                     break;
                 case "VoidCacheEntry":
                     if ($annotation->value) {
                         $this->__voidCacheEntries[] = $annotation->value;
                     }
                     break;
                 case "NoCache":
                     $this->__noCache = true;
                     break;
             }
         }
         # Make sure we have a Base URI
         if (!$this->__baseUri) {
             throw new Exception("BaseURI must be specified in " . get_class($this));
         }
         # See if we had query properties
         if (!$this->__queryProperties) {
             $this->__queryProperties = $this->__properties;
         }
         # Store the record properties in the caches
         $parsed_annotations = array("baseUri" => $this->__baseUri, "resourceIds" => $this->__resourceIds, "createCall" => $this->__createCall, "readCall" => $this->__readCall, "updateCall" => $this->__updateCall, "deleteCall" => $this->__deleteCall, "allowCreate" => $this->__allowCreate, "allowRead" => $this->__allowRead, "allowUpdate" => $this->__allowUpdate, "allowDelete" => $this->__allowDelete, "allowQuery" => $this->__allowQuery, "queryProperties" => $this->__queryProperties, "queryView" => $this->__queryView, "readOnly" => $this->__readOnly, "cachePrefix" => $this->__cachePrefix, "cacheTime" => $this->__cacheTime, "voidCacheEntries" => $this->__voidCacheEntries, "noCache" => $this->__noCache);
         $execution_cache->set($cache_key, $parsed_annotations);
         $local_cache->set($cache_key, $parsed_annotations, Annotations::$cacheTime);
     } else {
         # Restore the property values
         $this->__baseUri = $parsed_annotations["baseUri"];
         $this->__resourceIds = $parsed_annotations["resourceIds"];
         $this->__createCall = $parsed_annotations["createCall"];
         $this->__readCall = $parsed_annotations["readCall"];
         $this->__updateCall = $parsed_annotations["updateCall"];
         $this->__deleteCall = $parsed_annotations["deleteCall"];
         $this->__allowCreate = $parsed_annotations["allowCreate"];
         $this->__allowRead = $parsed_annotations["allowRead"];
         $this->__allowUpdate = $parsed_annotations["allowUpdate"];
         $this->__allowDelete = $parsed_annotations["allowDelete"];
         $this->__allowQuery = $parsed_annotations["allowQuery"];
         $this->__queryProperties = $parsed_annotations["queryProperties"];
         $this->__queryView = $parsed_annotations["queryView"];
         $this->__readOnly = $parsed_annotations["readOnly"];
         $this->__cachePrefix = $parsed_annotations["cachePrefix"];
         $this->__cacheTime = $parsed_annotations["cacheTime"];
         $this->__voidCacheEntries = $parsed_annotations["voidCacheEntries"];
         $this->__noCache = $parsed_annotations["noCache"];
     }
     # See if the object we received was an object or array
     # TODO: override the __import class for this
     if (is_array($object) || is_object($object)) {
         # Separate the object's values into primary key and other values
         $id_values = array();
         $values = array();
         foreach ($object as $key => $value) {
             if (array_key_exists($key, $this->__alias)) {
                 if (in_array($this->__alias[$key], $this->__resourceIds)) {
                     # This is a primary key value
                     $id_values[$key] = $value;
                 } else {
                     # This is another value
                     $values[$key] = $value;
                 }
             } else {
                 # Store the value as-is
                 $values[$key] = $value;
             }
         }
         # Load the resource id values
         $this->__enforceReadOnly = false;
         $this->__import($id_values, $view, $strict);
         # Get the record
         $this->getRecord();
         $this->__enforceReadOnly = true;
         # Save the initial values
         foreach ($this->__properties as $property) {
             $this->__defaultValues[$property] = $this->{$property};
         }
         # Set the other properties
         $this->__import($values, $view, $strict);
     } else {
         $this->__createMode = true;
         $this->__enforceReadOnly = false;
         # Save the initial values
         foreach ($this->__properties as $property) {
             $this->__defaultValues[$property] = $this->{$property};
         }
     }
 }
Exemplo n.º 3
0
 /**
  * Initializes the database record. If the object provides values for the
  * primary key properties, then the record is loaded from the database. If
  * no, a new record is created.
  *
  * @history
  * 2013.09.30:
  *   (AT)  Initial release
  * 2013.10.24:
  *   (AT)  Change authorization() call parameter order
  * 2014.02.18:
  *   (AT)  Add support for the unbound annotation
  * 2014.04.02:
  *   (AT)  Switch from using __defaultValues to __previousValues and
  *         __persistenceValues
  * 2014.08.06:
  *   (AT)  Turn the execution cache into a proper memory cache
  *
  * @version 2014.08.06
  * @author (AT) Alberto Trevino, Brigham Young Univ. <*****@*****.**>
  *
  * @param \Cougar\Security\iSecurity $security
  *   Security context
  * @param \Cougar\Cache\iCache $cache
  *   Cache object
  * @param \PDO $pdo
  *   Database connection
  * @param mixed $object
  *   Object or assoc. array of property values
  * @param string $view
  *   Set view on load
  * @param bool $strict
  *  Whether to perform strict property checking (on by default)
  * @throws \Cougar\Exceptions\Exception
  */
 public function __construct(iSecurity $security, iCache $cache, \PDO $pdo, $object = null, $view = null, $strict = true)
 {
     # Get a local cache
     # TODO: Set through static property(?)
     $local_cache = CacheFactory::getLocalCache();
     $execution_cache = CacheFactory::getMemoryCache();
     # Store the object references
     $this->__security = $security;
     $this->__cache = $cache;
     $this->__pdo = $pdo;
     # Add the class name to the default cache prefix
     $this->__cachePrefix .= "." . get_class($this);
     # Create our own cache keys
     $class = get_class($this) . ".PdoModel";
     $cache_key = Annotations::$annotationsCachePrefix . "." . $class;
     # Call the parent constructor
     $this->__constructModel(null, $view);
     # See if the execution cache has the object properties
     $parsed_annotations = $execution_cache->get($cache_key);
     if (!$parsed_annotations) {
         # See if the annotations came from the cache
         if ($this->__annotations->cached) {
             $parsed_annotations = $local_cache->get($cache_key);
         }
     }
     # See if we have pre-parsed annotations
     if ($parsed_annotations === false) {
         # Go through the class annotations
         foreach ($this->__annotations->class as $annotation) {
             switch ($annotation->name) {
                 case "Table":
                     # Only take the first table value
                     if (!$this->__table) {
                         $this->__table = $annotation->value;
                     }
                     break;
                 case "Allow":
                     # Set all the operation to false
                     $this->__allowCreate = false;
                     $this->__allowRead = false;
                     $this->__allowUpdate = false;
                     $this->__allowDelete = false;
                     $this->__allowQuery = false;
                     # See which operations will be allowed
                     foreach (preg_split('/\\s+/u', strtolower($annotation->value)) as $operation) {
                         switch ($operation) {
                             case "create":
                             case "insert":
                                 $this->__allowCreate = true;
                                 break;
                             case "read":
                             case "select":
                                 $this->__allowRead = true;
                                 break;
                             case "update":
                                 $this->__allowUpdate = true;
                                 break;
                             case "delete":
                                 $this->__allowDelete = true;
                                 break;
                             case "query":
                             case "list":
                                 $this->__allowQuery = true;
                         }
                     }
                     break;
                 case "Join":
                 case "JOIN":
                     if ($annotation->value) {
                         # See if the join already has the word JOIN
                         if (stripos($annotation->value, "join") === false) {
                             $this->__joins[] = "JOIN " . $annotation->value;
                         } else {
                             $this->__joins[] = $annotation->value;
                         }
                     }
                     break;
                 case "PrimaryKey":
                     if ($annotation->value) {
                         foreach (preg_split('/\\s+/u', $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__primaryKey[] = $property;
                             } else {
                                 throw new Exception("Specified primary key " . "property " . $property . " does not exist");
                             }
                         }
                     }
                     break;
                 case "ReadOnly":
                     if ($annotation->value) {
                         foreach (preg_split('/\\s+/u', $annotation->value) as $property) {
                             if (array_key_exists($property, $this->__readOnly)) {
                                 $this->__readOnly[$property] = true;
                             } else {
                                 throw new Exception("Specified read-only property " . $property . " does not exist");
                             }
                         }
                     }
                     break;
                 case "DeleteFlag":
                     if ($annotation->value) {
                         $tmp_array = preg_split('/\\s+/u', $annotation->value, 2);
                         if (count($tmp_array) != 2) {
                             throw new Exception("You must specify a " . "property name and value with " . "@DeleteFlag annotation");
                         }
                         if (in_array($tmp_array[0], $this->__properties)) {
                             $this->__deleteProperty = $tmp_array[0];
                             $this->__deletePropertyValue = $tmp_array[1];
                         } else {
                             throw new Exception("Delete flag property ");
                         }
                     }
                     break;
                 case "QueryList":
                     if ($annotation->value) {
                         foreach (preg_split('/\\s+/u', $annotation->value) as $property) {
                             if (in_array($property, $this->__properties)) {
                                 $this->__queryProperties[] = $property;
                             } else {
                                 throw new Exception("Specified query property " . $property . " does not exist");
                             }
                         }
                     }
                     break;
                 case "QueryView":
                     if ($annotation->value) {
                         if (array_key_exists($annotation->value, $this->__views)) {
                             $this->__queryView = $annotation->value;
                         }
                     }
                     break;
                 case "QueryUnique":
                     $this->__queryUnique = true;
                     break;
                 case "NoQuery":
                     # Here for backward compatibility
                     $this->__allowQuery = false;
                     break;
                 case "CachePrefix":
                     if ($annotation->value) {
                         $this->__cachePrefix = $annotation->value;
                     }
                     break;
                 case "CacheTime":
                     if ($annotation->value) {
                         $this->__cacheTime = (int) $annotation->value;
                     }
                     break;
                 case "VoidCacheEntry":
                     if ($annotation->value) {
                         $this->__voidCacheEntries[] = $annotation->value;
                     }
                     break;
                 case "NoCache":
                     $this->__noCache = true;
                     $this->__noQueryCache = true;
                     break;
                 case "NoQueryCache":
                     $this->__noQueryCache = true;
                     break;
             }
         }
         # Make sure the table name has been defined
         if (!$this->__table) {
             throw new Exception("You must specify a table name using the " . "@Table annotation in the class document block");
         }
         # Make sure we have a primary key
         if (!$this->__primaryKey) {
             throw new Exception("You must specify the columns that make " . "up the Primary Key using the @PrimaryKey annotation in " . "the class document block");
         }
         # Go through the properties
         foreach ($this->__annotations->properties as $property_name => $annotations) {
             # Create the property in the column map
             $this->__columnMap[$property_name] = $property_name;
             # Go through the annotations
             foreach ($annotations as $annotation) {
                 switch ($annotation->name) {
                     case "Column":
                         $this->__columnMap[$property_name] = $annotation->value;
                         break;
                     case "Unbound":
                         unset($this->__columnMap[$property_name]);
                         break;
                     case "ReadOnly":
                         $this->__readOnly[$property_name] = true;
                 }
             }
         }
         # See if we had query properties
         if (!$this->__queryProperties) {
             # Declare all properties are queryable
             $this->__queryProperties = array_keys($this->__columnMap);
         }
         # Store the record properties in the caches
         $parsed_annotations = array("table" => $this->__table, "primaryKey" => $this->__primaryKey, "allowSelect" => $this->__allowRead, "allowInsert" => $this->__allowCreate, "allowUpdate" => $this->__allowUpdate, "allowDelete" => $this->__allowDelete, "joins" => $this->__joins, "deleteProperty" => $this->__deleteProperty, "deletePropertyValue" => $this->__deletePropertyValue, "queryProperties" => $this->__queryProperties, "allowQuery" => $this->__allowQuery, "queryView" => $this->__queryView, "queryUnique" => $this->__queryUnique, "cachePrefix" => $this->__cachePrefix, "cacheTime" => $this->__cacheTime, "voidCacheEntries" => $this->__voidCacheEntries, "noCache" => $this->__noCache, "noQueryCache" => $this->__noQueryCache, "columnMap" => $this->__columnMap, "readOnly" => $this->__readOnly);
         $execution_cache->set($cache_key, $parsed_annotations);
         $local_cache->set($cache_key, $parsed_annotations, Annotations::$cacheTime);
     } else {
         # Restore the property values
         $this->__table = $parsed_annotations["table"];
         $this->__primaryKey = $parsed_annotations["primaryKey"];
         $this->__allowRead = $parsed_annotations["allowSelect"];
         $this->__allowCreate = $parsed_annotations["allowInsert"];
         $this->__allowUpdate = $parsed_annotations["allowUpdate"];
         $this->__allowDelete = $parsed_annotations["allowDelete"];
         $this->__joins = $parsed_annotations["joins"];
         $this->__deleteProperty = $parsed_annotations["deleteProperty"];
         $this->__deletePropertyValue = $parsed_annotations["deletePropertyValue"];
         $this->__queryProperties = $parsed_annotations["queryProperties"];
         $this->__allowQuery = $parsed_annotations["allowQuery"];
         $this->__queryView = $parsed_annotations["queryView"];
         $this->__queryUnique = $parsed_annotations["queryUnique"];
         $this->__cachePrefix = $parsed_annotations["cachePrefix"];
         $this->__cacheTime = $parsed_annotations["cacheTime"];
         $this->__voidCacheEntries = $parsed_annotations["voidCacheEntries"];
         $this->__noCache = $parsed_annotations["noCache"];
         $this->__noQueryCache = $parsed_annotations["noQueryCache"];
         $this->__columnMap = $parsed_annotations["columnMap"];
         $this->__readOnly = $parsed_annotations["readOnly"];
     }
     # See if the object we received was an object or array
     if (is_array($object) || is_object($object)) {
         # Separate the object's values into primary key and other values
         $pk_values = array();
         $values = array();
         $has_primary_key_values = false;
         foreach ($object as $key => $value) {
             if ($this->__caseInsensitive) {
                 $key = strtolower($key);
             }
             # See if this is a value we handle
             if (array_key_exists($key, $this->__alias)) {
                 # Resolve the alias
                 $key = $this->__alias[$key];
                 # See if this is a primary key value
                 if (in_array($key, $this->__primaryKey)) {
                     # Add the value to our list of primary key values
                     $pk_values[$key] = $value;
                     # See if the value is not equivalent to default
                     if ($value != $this->{$this->__alias[$key]}) {
                         # This is a primary key value; save the value
                         $has_primary_key_values = true;
                     }
                 } else {
                     # This is another value; store it separately
                     $values[$key] = $value;
                 }
             }
         }
         # See if we have primary key values
         if ($has_primary_key_values) {
             # Set the PK properties
             foreach ($pk_values as $key => $value) {
                 $this->{$key} = $value;
             }
             # Get the record; method will also cast values
             $this->getRecord();
             # Call the authorization method; we call it after we get the
             # record since the authorization may be based on the values
             $this->authorization($this->__security, $this->__allowCreate, $this->__allowRead, $this->__allowUpdate, $this->__allowDelete, $this->__allowQuery, $this->__columnMap, $this->__readOnly, $this->__visible);
             # Make sure the identity is authorized to read the record
             if (!$this->__allowRead) {
                 throw new AccessDeniedException("You do not have access to this record");
             }
         } else {
             # Set up insert mode
             $this->__insertMode = true;
             $this->__enforceReadOnly = false;
             # Set the persistent values from the previous values
             $this->__persistentValues = $this->__previousValues;
         }
         # Set the other properties via the __import method
         $this->__import($values);
     } else {
         # Set the persistent values from the previous (default) values
         $this->__persistentValues = $this->__previousValues;
         # Call the authorization method
         $this->authorization($this->__security, $this->__allowCreate, $this->__allowRead, $this->__allowUpdate, $this->__allowDelete, $this->__allowQuery, $this->__columnMap, $this->__readOnly, $this->__visible);
         $this->__insertMode = true;
         $this->__enforceReadOnly = false;
     }
 }
Exemplo n.º 4
0
 /**
  * Extracts the annotation for the class and parses them into the
  * __-prefixed protected properties.
  *
  * @history
  * 2013.09.30:
  *   (AT)  Initial release
  * 2014.02.26:
  *   (AT)  Extract annotations with extractFromObjectWithInheritance()
  * 2014.03.05:
  *   (AT)  Don't clobber cached annotations when loading parsed annotations
  *         from cache
  *   (AT)  Switch from using __defaultValues to __previousValues
  * 2014.08.06:
  *   (AT)  Turn the execution cache into a proper memory cache
  *
  * @version 2014.08.06
  * @author (AT) Alberto Trevino, Brigham Young Univ. <*****@*****.**>
  *
  * @param mixed $object
  *   Assoc. array or object with initial values
  * @param string $view
  *   Set the given view once values are loaded
  * @param bool $strict
  *   Whether to perform strict property checking (on by default)
  * @throws Exception
  * @throws BadRequestException
  */
 public function __construct($object = null, $view = null, $strict = true)
 {
     # Store the value of the requested view (avoid clobbering later)
     $requested_view = $view;
     # Get a local cache and a memory cache
     # TODO: Set through static property(?)
     $local_cache = CacheFactory::getLocalCache();
     $execution_cache = CacheFactory::getMemoryCache();
     # Create our cache keys
     $class = get_class($this) . ".Model";
     $cache_key = Annotations::$annotationsCachePrefix . "." . $class;
     # See if the execution cache has the object properties
     $parsed_annotations = $execution_cache->get($cache_key);
     if (!$parsed_annotations) {
         # Get the annotations
         $this->__annotations = Annotations::extractFromObjectWithInheritance($this, array(), true, false);
         # See if the annotations came from the cache
         $parsed_annotations = false;
         if ($this->__annotations->cached) {
             $parsed_annotations = $local_cache->get($cache_key);
         }
     }
     # See if we have pre-parsed annotations
     if ($parsed_annotations === false) {
         # Go through the class annotations
         $view_list = array("__default__");
         foreach ($this->__annotations->class as $annotation) {
             switch ($annotation->name) {
                 case "CaseInsensitive":
                     $this->__caseInsensitive = true;
                     break;
                 case "Views":
                     # See which views are defined
                     $views = preg_split('/\\s+/u', $annotation->value, null, PREG_SPLIT_NO_EMPTY);
                     # Create the views (if we have any)
                     foreach ($views as $view) {
                         $this->__views[$view] = $this->__views["__default__"];
                         $view_list[] = $view;
                     }
                     break;
             }
         }
         # Go through the public properties of the object
         foreach (array_keys($this->__annotations->properties) as $property_name) {
             # Add the property to the list of properties
             $this->__properties[] = $property_name;
             # Set the default property options
             $this->__type[$property_name] = "string";
             $this->__readOnly[$property_name] = false;
             $this->__null[$property_name] = true;
             $this->__regex[$property_name] = array();
             $this->__alias[$property_name] = $property_name;
             # See if the properties are case-insensitive
             if ($this->__caseInsensitive) {
                 # Store the lowercase property name as an alias
                 $this->__alias[strtolower($property_name)] = $property_name;
             }
             # Set the view-based values
             foreach ($view_list as $view) {
                 $this->__views[$view]["optional"][$property_name] = false;
                 $this->__views[$view]["visible"][$property_name] = true;
                 $this->__views[$view]["exportAlias"][$property_name] = $property_name;
             }
             # Go through the annotations
             foreach ($this->__annotations->properties[$property_name] as $annotation) {
                 switch ($annotation->name) {
                     case "Alias":
                     case "Column":
                         $this->__alias[$annotation->value] = $property_name;
                         if ($this->__caseInsensitive) {
                             $this->__alias[strtolower($annotation->value)] = $property_name;
                         }
                         break;
                     case "NotNull":
                         $this->__null[$property_name] = false;
                         break;
                     case "Regex":
                         $this->__regex[$property_name][] = $annotation->value;
                         break;
                     case "Optional":
                         # Set the option in all views
                         foreach ($view_list as $view) {
                             $this->__views[$view]["optional"][$property_name] = true;
                         }
                         break;
                     case "DateTimeFormat":
                         $this->__dateTimeFormat[$property_name] = $annotation->value;
                         break;
                     case "View":
                         # Separate the values
                         $view_values = preg_split('/\\s+/u', $annotation->value);
                         # Extract the view (first value)
                         $view = array_shift($view_values);
                         # Make sure the view exists
                         if (!array_key_exists($view, $this->__views)) {
                             throw new Exception($property_name . " property defines \"" . $view . "\" but the view does not exist.");
                         }
                         # Go through the rest of the options
                         $export_alias_set = false;
                         foreach ($view_values as $index => $value) {
                             switch (strtolower($value)) {
                                 case "hidden":
                                     $this->__views[$view]["visible"][$property_name] = false;
                                     break;
                                 case "optional":
                                     $this->__views[$view]["optional"][$property_name] = true;
                                     break;
                                 default:
                                     # Add the real value (not lowercase) as
                                     # the export alias and as an alias
                                     if (!$export_alias_set) {
                                         $this->__views[$view]["exportAlias"][$property_name] = $view_values[$index];
                                         $this->__alias[$view_values[$index]] = $property_name;
                                         if ($this->__caseInsensitive) {
                                             $this->__alias[strtolower($view_values[$index])] = $property_name;
                                         }
                                     }
                                     $export_alias_set = true;
                                     break;
                             }
                         }
                         break;
                     case "var":
                         # Separate the variable name from the comment
                         $var_values = preg_split('/\\s+/u', $annotation->value);
                         switch ($var_values[0]) {
                             case "string":
                             case "":
                                 # Type is already set to string
                                 break;
                             case "int":
                             case "integer":
                                 $this->__type[$property_name] = "int";
                                 break;
                             case "float":
                             case "double":
                                 $this->__type[$property_name] = "float";
                                 break;
                             case "bool":
                             case "boolean":
                                 $this->__type[$property_name] = "bool";
                                 break;
                             case "DateTime":
                                 $this->__type[$property_name] = "DateTime";
                                 if (!array_key_exists($property_name, $this->__dateTimeFormat)) {
                                     $this->__dateTimeFormat[$property_name] = "";
                                 }
                                 break;
                             default:
                                 $this->__type[$property_name] = $var_values[0];
                         }
                         break;
                 }
             }
         }
         # Get the default values
         foreach ($this->__properties as $property) {
             $this->__defaultValues[$property] = $this->{$property};
         }
         # Store the record properties in the caches
         $parsed_annotations = array("annotations" => $this->__annotations, "properties" => $this->__properties, "type" => $this->__type, "readOnly" => $this->__readOnly, "null" => $this->__null, "dateTimeFormat" => $this->__dateTimeFormat, "regex" => $this->__regex, "alias" => $this->__alias, "caseInsensitive" => $this->__caseInsensitive, "view" => $this->__views, "defaultValues" => $this->__defaultValues);
         $execution_cache->set($cache_key, $parsed_annotations);
         $local_cache->set($cache_key, $parsed_annotations, Annotations::$cacheTime);
     } else {
         # Make sure we don't clobber any previous annotations
         #  (otherwise we may lose the cached setting)
         if (!$this->__annotations) {
             $this->__annotations = $parsed_annotations["annotations"];
         }
         # Restore the property values
         $this->__properties = $parsed_annotations["properties"];
         $this->__type = $parsed_annotations["type"];
         $this->__readOnly = $parsed_annotations["readOnly"];
         $this->__null = $parsed_annotations["null"];
         $this->__dateTimeFormat = $parsed_annotations["dateTimeFormat"];
         $this->__regex = $parsed_annotations["regex"];
         $this->__alias = $parsed_annotations["alias"];
         $this->__caseInsensitive = $parsed_annotations["caseInsensitive"];
         $this->__views = $parsed_annotations["view"];
         $this->__defaultValues = $parsed_annotations["defaultValues"];
     }
     # Set the previous values from the default values
     $this->__previousValues = $this->__defaultValues;
     # See if we have an incoming object or array
     if (is_array($object) || is_object($object)) {
         # Load the incoming values
         $this->__import($object, $strict);
     } else {
         if (!is_null($object)) {
             throw new BadRequestException("Casting from object requires an object or array");
         }
     }
     # Set the desired view
     if ($requested_view) {
         $this->__setView($requested_view);
     } else {
         # Point the protected properties to the values in the default view
         $this->__exportAlias =& $this->__views["__default__"]["exportAlias"];
         $this->__optional =& $this->__views["__default__"]["optional"];
         $this->__visible =& $this->__views["__default__"]["visible"];
     }
 }