Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • ActiveRecord
  • Cache
  • Configs
  • Core
  • DateTime
  • Debug
  • DeleteOperation
  • Errors
  • Event
  • EventHook
  • Events
  • FileCache
  • FormattedString
  • Helpers
  • I18n
  • Image
  • Inflections
  • Inflector
  • Models
  • Module
  • Modules
  • Object
  • Operation
  • PingOperation
  • Prototype
  • Route
  • Routes
  • SaveOperation
  • Session
  • TimeZone
  • TimeZoneLocation
  • Uploaded
  • Vars
  • VarsIterator

Interfaces

  • StorageInterface
  • ToArray
  • ToArrayRecursive

Traits

  • PrototypeTrait
  • ToArrayRecursiveTrait

Exceptions

  • AlreadyAuthenticated
  • AuthenticationRequired
  • Exception
  • ModuleConstructorMissing
  • ModuleIsDisabled
  • ModuleNotDefined
  • OffsetError
  • OffsetNotDefined
  • OffsetNotReadable
  • OffsetNotWritable
  • PermissionRequired
  • PropertyError
  • PropertyIsReserved
  • PropertyNotDefined
  • PropertyNotReadable
  • PropertyNotWritable
  • RouteNotDefined
  • SecurityException

Constants

  • TOKEN_ALPHA
  • TOKEN_ALPHA_UPCASE
  • TOKEN_NUMERIC
  • TOKEN_SYMBOL
  • TOKEN_SYMBOL_WIDE

Functions

  • array_flatten
  • array_insert
  • array_merge_recursive
  • camelize
  • capitalize
  • downcase
  • dump
  • escape
  • escape_all
  • exact_array_merge_recursive
  • excerpt
  • format
  • generate_token
  • generate_token_wide
  • generate_v4_uuid
  • get_autoconfig
  • humanize
  • hyphenate
  • log
  • log_error
  • log_info
  • log_success
  • log_time
  • normalize
  • normalize_namespace_part
  • normalize_url_path
  • pbkdf2
  • pluralize
  • remove_accents
  • shorten
  • singularize
  • sort_by_weight
  • stable_sort
  • strip_root
  • titleize
  • unaccent_compare
  • unaccent_compare_ci
  • underscore
  • upcase
  1 <?php
  2 
  3 /*
  4  * This file is part of the ICanBoogie package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
  7  *
  8  * For the full copyright and license information, please view the LICENSE
  9  * file that was distributed with this source code.
 10  */
 11 
 12 namespace ICanBoogie;
 13 
 14 /**
 15  * Accessor for the variables stored as files in the "/repository/var" directory.
 16  */
 17 class Vars implements \ArrayAccess, \IteratorAggregate
 18 {
 19     /**
 20      * Magic pattern used to recognized automatically serialized values.
 21      *
 22      * @var string
 23      */
 24     const MAGIC = "VAR\0SLZ\0";
 25 
 26     /**
 27      * Length of the magic pattern {@link MAGIC}.
 28      *
 29      * @var int
 30      */
 31     const MAGIC_LENGTH = 8;
 32 
 33     static private $release_after;
 34 
 35     /**
 36      * Absolute path to the vars directory.
 37      *
 38      * @var string
 39      */
 40     protected $path;
 41 
 42     /**
 43      * Constructor.
 44      *
 45      * @param string $path Absolute path to the vars directory.
 46      *
 47      * @throws Exception when the path is not writable.
 48      */
 49     public function __construct($path)
 50     {
 51         $this->path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
 52 
 53         if (self::$release_after === null)
 54         {
 55             self::$release_after = strpos(PHP_OS, 'WIN') === 0 ? false : true;
 56         }
 57 
 58         if (!is_writable($this->path))
 59         {
 60             throw new Exception('The directory %directory is not writable.', [ 'directory' => $this->path ]);
 61         }
 62     }
 63 
 64     /**
 65      * Stores the value of a var using the {@link store()} method.
 66      *
 67      * @see \ArrayAccess::offsetSet()
 68      */
 69     public function offsetSet($name, $value)
 70     {
 71         $this->store($name, $value);
 72     }
 73 
 74     /**
 75      * Checks if the var exists.
 76      *
 77      * @param string $name Name of the variable.
 78      *
 79      * @return bool true if the var exists, false otherwise.
 80      *
 81      * @see \ArrayAccess::offsetExists()
 82      */
 83     public function offsetExists($name)
 84     {
 85         $pathname = $this->path . $name;
 86 
 87         return file_exists($pathname);
 88     }
 89 
 90     /**
 91      * Deletes a var.
 92      *
 93      * @see \ArrayAccess::offsetUnset()
 94      */
 95     public function offsetUnset($name)
 96     {
 97         $pathname = $this->path . $name;
 98 
 99         if (!file_exists($pathname))
100         {
101             return;
102         }
103 
104         unlink($pathname);
105     }
106 
107     /**
108      * Returns the value of the var using the {@link retrieve()} method.
109      *
110      * @see \ArrayAccess::offsetGet()
111      */
112     public function offsetGet($name)
113     {
114         return $this->retrieve($name);
115     }
116 
117     /**
118      * Cache a variable in the repository.
119      *
120      * If the value is an array or a string it is serialized and prepended with a magic
121      * identifier. This magic identifier is used to recognized previously serialized values when
122      * they are read back.
123      *
124      * @param string $key The key used to identify the value. Keys are unique, so storing a second
125      * value with the same key will overwrite the previous value.
126      * @param mixed $value The value to store for the key.
127      * @param int $ttl The time to live in seconds for the stored value. If no _ttl_ is supplied
128      * (or if the _tll_ is __0__), the value will persist until it is removed from the cache
129      * manually or otherwise fails to exist in the cache.
130      *
131      * @throws Exception when a file operation fails.
132      */
133     public function store($key, $value, $ttl=0)
134     {
135         $pathname = $this->path . $key;
136         $ttl_mark = $pathname . '.ttl';
137 
138         if ($ttl)
139         {
140             $future = time() + $ttl;
141 
142             touch($ttl_mark, $future, $future);
143         }
144         else if (file_exists($ttl_mark))
145         {
146             unlink($ttl_mark);
147         }
148 
149         $dir = dirname($pathname);
150 
151         if (!file_exists($dir))
152         {
153             mkdir($dir, 0705, true);
154         }
155 
156         $uniq_id = uniqid(mt_rand(), true);
157         $tmp_pathname = $dir . '/var-' . $uniq_id;
158         $garbage_pathname = $dir . '/garbage-var-' . $uniq_id;
159 
160         #
161         # If the value is an array or a string it is serialized and prepended with a magic
162         # identifier.
163         #
164 
165         if (is_array($value) || is_object($value))
166         {
167             $value = self::MAGIC . serialize($value);
168         }
169 
170         if ($value === true)
171         {
172             touch($pathname);
173         }
174         else if ($value === false || $value === null)
175         {
176             $this->offsetUnset($key);
177         }
178         else
179         {
180             #
181             # We lock the file create/update, but we write the data in a temporary file, which is then
182             # renamed once the data is written.
183             #
184 
185             $fh = fopen($pathname, 'a+');
186 
187             if (!$fh)
188             {
189                 throw new Exception('Unable to open %pathname: :message', [ 'pathname' => $pathname, 'message' => Debug::$last_error_message ]);
190             }
191 
192             if (self::$release_after && !flock($fh, LOCK_EX))
193             {
194                 throw new Exception('Unable to get to exclusive lock on %pathname: :message', [ 'pathname' => $pathname, 'message' => Debug::$last_error_message ]);
195             }
196 
197             file_put_contents($tmp_pathname, $value);
198 
199             #
200             # Windows, this is for you
201             #
202             if (!self::$release_after)
203             {
204                 fclose($fh);
205             }
206 
207             if (!rename($pathname, $garbage_pathname))
208             {
209                 throw new Exception('Unable to rename %old as %new.', [ 'old' => $pathname, 'new' => $garbage_pathname ]);
210             }
211 
212             if (!rename($tmp_pathname, $pathname))
213             {
214                 throw new Exception('Unable to rename %old as %new.', [ 'old' => $tmp_pathname, 'new' => $pathname ]);
215             }
216 
217             if (!unlink($garbage_pathname))
218             {
219                 throw new Exception('Unable to delete %pathname: :message', [ 'pathname' => $garbage_pathname, 'message' => Debug::$last_error_message ]);
220             }
221 
222             if (self::$release_after)
223             {
224                 flock($fh, LOCK_UN);
225                 fclose($fh);
226             }
227         }
228     }
229 
230     /**
231      * Returns the value of variable.
232      *
233      * If the value is marked with the magic identifier it is not serialized.
234      *
235      * @param string $name
236      * @param mixed $default The value returned if the variable does not exists. Defaults to null.
237      *
238      * @return mixed
239      */
240     public function retrieve($name, $default=null)
241     {
242         $pathname = $this->path . $name;
243         $ttl_mark = $pathname . '.ttl';
244 
245         if (file_exists($ttl_mark) && fileatime($ttl_mark) < time() || !file_exists($pathname))
246         {
247             return $default;
248         }
249 
250         $value = file_get_contents($pathname);
251 
252         if (substr($value, 0, self::MAGIC_LENGTH) == self::MAGIC)
253         {
254             $value = unserialize(substr($value, self::MAGIC_LENGTH));
255         }
256 
257         return $value;
258     }
259 
260     /**
261      * Returns a directory iterator for the variables.
262      *
263      * @return VarsIterator
264      *
265      * @see IteratorAggregate::getIterator()
266      */
267     public function getIterator()
268     {
269         $iterator = new \DirectoryIterator($this->path);
270 
271         return new VarsIterator($iterator);
272     }
273 
274     /**
275      * Returns a file iterator for variables matching a regex.
276      *
277      * @param string $regex
278      *
279      * @return \ICanBoogie\VarsIterator
280      */
281     public function matching($regex)
282     {
283         $dir = new \DirectoryIterator($this->path);
284         $filter = new \RegexIterator($dir, $regex);
285 
286         return new VarsIterator($filter);
287     }
288 }
289 
290 /**
291  * Iterates through variables.
292  *
293  * The iterator is usually created using the Vars::matching() method.
294  *
295  * The iterator can also be used to delete matching variables.
296  */
297 class VarsIterator implements \Iterator
298 {
299     /**
300      * Iterator.
301      *
302      * @var \Iterator
303      */
304     protected $iterator;
305 
306     public function __construct(\Iterator $iterator)
307     {
308         $this->iterator = $iterator;
309     }
310 
311     /**
312      * Returns the directory iterator.
313      *
314      * Dot files are skipped.
315      *
316      * @return \DirectoryIterator
317      */
318     public function current()
319     {
320         $file = $this->iterator->current();
321 
322         if ($file->isDot())
323         {
324             $this->iterator->next();
325 
326             $file = $this->current();
327         }
328 
329         return $file;
330     }
331 
332     public function next()
333     {
334         $this->iterator->next();
335     }
336 
337     /**
338      * Returns the pathname of the variable, which is the same as its key.
339      *
340      * @return string
341      */
342     public function key()
343     {
344         return $this->iterator->current()->getFilename();
345     }
346 
347     public function valid()
348     {
349         return $this->iterator->valid();
350     }
351 
352     public function rewind()
353     {
354         $this->iterator->rewind();
355     }
356 
357     /**
358      * Deletes the variables found by the iterator.
359      */
360     public function delete()
361     {
362         foreach ($this->iterator as $file)
363         {
364             unlink($file->getPathname());
365         }
366     }
367 }
Autodoc API documentation generated by ApiGen 2.8.0