[ Index ]

PHP Cross Reference of Akelos Framework

title

Body

[close]

/ -> Ak.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   3  
   4  // +----------------------------------------------------------------------+
   5  // | Akelos Framework - http://www.akelos.org                             |
   6  // +----------------------------------------------------------------------+
   7  // | Copyright (c) 2002-2006, Akelos Media, S.L.  & Bermi Ferrer Martinez |
   8  // | Released under the GNU Lesser General Public License, see LICENSE.txt|
   9  // +----------------------------------------------------------------------+
  10  
  11  /**
  12   * @package ActiveSupport
  13   * @subpackage Base
  14   * @author Bermi Ferrer <bermi a.t akelos c.om>
  15   * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
  16   * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
  17   */
  18  
  19  /**
  20  * Define LOG Levels
  21  * @todo Log events
  22  */
  23  define('AK_LOG_NOTICE', 0);
  24  define('AK_LOG_WARNING', 1);
  25  define('AK_LOG_ERROR', 2);
  26  
  27  defined('AK_FRAMEWORK_LANGUAGE') ? null : define('AK_FRAMEWORK_LANGUAGE', 'en');
  28  defined('AK_DEV_MODE') ? null : define('AK_DEV_MODE', false);
  29  defined('AK_AUTOMATIC_CONFIG_VARS_ENCRYPTION') ? null : define('AK_AUTOMATIC_CONFIG_VARS_ENCRYPTION', false);
  30  
  31  
  32  /**
  33  * Akelos Framework static functions
  34  *
  35  * Ak contains all the Akelos Framework static functions. This
  36  * class acts like a name space to avoid naming collisions
  37  * when PHP gets new functions into its core. And also to provide 
  38  * additional functionality to existing PHP functions mantaining the same interface  
  39  *
  40  * @author Bermi Ferrer <bermi at akelos com>
  41  * @copyright Copyright (c) 2002-2005, Akelos Media, S.L. http://www.akelos.org
  42  * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
  43  */
  44  class Ak
  45  {
  46  
  47      /**
  48      * Gets an instance of AkDbAdapter
  49      *
  50      * Whenever a database connection is required you can get a
  51      * reference to the default database connection by doing:
  52      *
  53      * $db =& Ak::db(); // get an adodb instance
  54      * 
  55      * AdoDB manual can be found at http://phplens.com/adodb/
  56      *
  57      * @access public
  58      * @param    string    $dns    A string containing Data Source Name (information
  59      * regarding database connection)
  60      * http://phplens.com/adodb/code.initialization.html#dsnsupport
  61      * @static
  62      * @return resource Php AdoDb instance.
  63      */
  64      function &db($dsn = null)
  65      {
  66          require_once (AK_LIB_DIR.DS.'AkActiveRecord'.DS.'AkDbAdapter.php');
  67          return AkDbAdapter::getInstance($dsn);
  68      }
  69  
  70      /**
  71       * @param string $message
  72       * @param [OPTIONAL] $fatal triggers even in production-mode
  73       */
  74      function deprecateWarning($message, $fatal=false)
  75      {
  76          if (!$fatal && AK_ENVIRONMENT == 'production'){
  77              return;
  78          }
  79          if (is_array($message)){
  80              trigger_error(Ak::t("DEPRECATED WARNING: ".array_shift($message),$message), E_USER_NOTICE);
  81          } else {
  82              trigger_error(Ak::t("DEPRECATED WARNING: ".$message), E_USER_NOTICE);
  83          }
  84      }
  85  
  86      /**
  87      * Gets a cache object singleton instance
  88      */
  89      function &cache()
  90      {
  91          static $cache;
  92          if(!isset($cache)){
  93              require_once (AK_LIB_DIR.DS.'AkCache.php');
  94              $cache = new AkCache();
  95          }
  96          return $cache;
  97      }
  98  
  99  
 100      function toUrl($options, $set_routes = false)
 101      {
 102          static $Map;
 103          if(empty($Map)){
 104              if($set_routes){
 105                  $Map = $options;
 106                  return;
 107              }else{
 108                  require_once (AK_LIB_DIR.DS.'AkRouter.php');
 109                  $Map = new AkRouter();
 110                  if(is_file(AK_ROUTES_MAPPING_FILE)){
 111                      include(AK_ROUTES_MAPPING_FILE);
 112                  }
 113              }
 114          } else if (is_a($options,'akrouter') && $set_routes) {
 115              $Map = $options;
 116              return;
 117          }
 118          return $Map->toUrl($options);
 119      }
 120  
 121  
 122      /**
 123      * Translate strings to the current locale.
 124      *
 125      * When using Ak::t(), try to put entire sentences and strings
 126      * in one Ak::t() call.
 127      * This makes it easier for translators. HTML markup within
 128      * translation strings
 129      * is acceptable, if necessary. The suggested syntax for a
 130      * link embedded
 131      * within a translation string is:
 132      *
 133      * @access public
 134      * @static
 135      * @param    string    $string    A string containing the English string to
 136      * translate.
 137      * @param    array    $args    An associative array of replacements to make after
 138      * translation. Incidences of any key in this array
 139      * are replaced with the corresponding value.
 140      * @return string The translated string.
 141      */
 142      function t($string, $args = null, $controller = null)
 143      {
 144          static $framework_dictionary = array(), $lang, $_dev_shutdown = true;
 145  
 146          if(AK_AUTOMATICALLY_UPDATE_LANGUAGE_FILES && !empty($string) && is_string($string)){
 147              require_once (AK_LIB_DIR.DS.'AkLocaleManager.php');
 148              // This adds used strings to a stack for storing new entries on the locale file after shutdown
 149              AkLocaleManager::getUsedLanguageEntries($string, $controller);
 150              if($_dev_shutdown){
 151                  register_shutdown_function(array('AkLocaleManager','updateLocaleFiles'));
 152                  $_dev_shutdown = false;
 153              }
 154          }
 155  
 156          if(!isset($lang)){
 157              if(!empty($_SESSION['lang'])){
 158                  $lang =  $_SESSION['lang'];
 159              }else{
 160                  $lang = Ak::lang();
 161              }
 162              if(is_file(AK_CONFIG_DIR.DS.'locales'.DS.$lang.'.php')){
 163                  require(AK_CONFIG_DIR.DS.'locales'.DS.$lang.'.php');
 164                  $framework_dictionary = array_merge($framework_dictionary,$dictionary);
 165              }
 166              if(!defined('AK_LOCALE')){
 167                  define('AK_LOCALE', $lang);
 168              }
 169              if(!empty($locale) && is_array($locale)){
 170                  Ak::locale(null, $lang, $locale);
 171              }
 172          }
 173  
 174          if(!empty($string) && is_array($string)){
 175              if(!empty($string[$lang])){
 176                  return $string[$lang];
 177              }
 178              $try_whith_lang = $args !== false && empty($string[$lang]) ? Ak::base_lang() : $lang;
 179              if(empty($string[$try_whith_lang]) && $args !== false){
 180                  foreach (Ak::langs() as $try_whith_lang){
 181                      if(!empty($string[$try_whith_lang])){
 182                          return $string[$try_whith_lang];
 183                      }
 184                  }
 185              }
 186              return @$string[$try_whith_lang];
 187          }
 188  
 189          if(isset($controller) && !isset($framework_dictionary[$controller.'_dictionary']) && is_file(AK_APP_DIR.DS.'locales'.DS.$controller.DS.$lang.'.php')){
 190              require(AK_APP_DIR.DS.'locales'.DS.$controller.DS.$lang.'.php');
 191              $framework_dictionary[$controller.'_dictionary'] = (array)$dictionary;
 192          }
 193  
 194          if(isset($controller) && isset($framework_dictionary[$controller.'_dictionary'][$string])){
 195              $string = $framework_dictionary[$controller.'_dictionary'][$string];
 196          }else {
 197              $string = isset($framework_dictionary[$string]) ? $framework_dictionary[$string] : $string;
 198          }
 199  
 200          if(isset($args) && is_array($args)){
 201              $string = @str_replace(array_keys($args), array_values($args),$string);
 202          }
 203  
 204          /**
 205          * @todo Prepare for multiple locales by inspecting AK_DEFAULT_LOCALE
 206          */
 207  
 208          return $string;
 209      }
 210  
 211  
 212  
 213      /**
 214       * Gets information about current locale from the locale settings on config/locales/LOCALE.php 
 215       * 
 216       * This are common settings on the locale file:
 217       * 'description' // Locale description Example. Spanish
 218       * 'charset' // 'ISO-8859-1';
 219       * 'date_time_format' // '%d/%m/%Y %H:%i:%s';
 220       * 'date_format' // '%d/%m/%Y';
 221       * 'long_date_format' // '%d/%m/%Y';
 222       * 'time_format' // '%H:%i';
 223       * 'long_time_format' // '%H:%i:%s';
 224       */
 225      function locale($locale_setting, $locale = null)
 226      {
 227          static $settings;
 228  
 229          // We initiate the locale settings
 230          Ak::t('Akelos');
 231  
 232          $locale = empty($locale) ? (defined('AK_LOCALE') ? AK_LOCALE : (Ak::t('Akelos') && Ak::locale($locale_setting))) : $locale;
 233  
 234          if (empty($settings[$locale])) {
 235              if(func_num_args() != 3){ // First time we ask for something using this locale so we will load locale details
 236                  $requested_locale = $locale;
 237                  if(@include(AK_CONFIG_DIR.DS.'locales'.DS.Ak::sanitize_include($requested_locale).'.php')){
 238                      $locale = !empty($locale) && is_array($locale) ? $locale : array();
 239                      Ak::locale(null, $requested_locale, $locale);
 240                      return Ak::locale($locale_setting, $requested_locale);
 241                  }
 242              }else{
 243                  $settings[$locale] = func_get_arg(2);
 244                  if(isset($settings[$locale]['charset'])){
 245                      defined('AK_CHARSET') ? null : (define('AK_CHARSET',$settings[$locale]['charset']) && @ini_set('default_charset', AK_CHARSET));
 246                  }
 247              }
 248          }
 249  
 250          return isset($settings[$locale][$locale_setting]) ? $settings[$locale][$locale_setting] : false;
 251      }
 252  
 253  
 254      function lang($set_language = null)
 255      {
 256          static $lang;
 257          $lang = empty($set_language) ? (empty($lang) ? AK_FRAMEWORK_LANGUAGE : $lang) : $set_language;
 258          return $lang;
 259      }
 260  
 261  
 262      function get_url_locale($set_locale = null)
 263      {
 264          static $locale;
 265          if(!empty($locale)){
 266              return $locale;
 267          }
 268          $locale = empty($set_locale) ? '' : $set_locale;
 269          return $locale;
 270      }
 271  
 272  
 273  
 274      function langs()
 275      {
 276          static $langs;
 277          if(!empty($lang)){
 278              return $lang;
 279          }
 280          $lang = Ak::lang();
 281          if(defined('AK_APP_LOCALES')){
 282              $langs = array_diff(explode(',',AK_APP_LOCALES.','),array(''));
 283          }
 284          $langs = empty($langs) ? array($lang) : $langs;
 285          return $langs;
 286      }
 287  
 288      function base_lang()
 289      {
 290          return array_shift(Ak::langs());
 291      }
 292  
 293  
 294  
 295      function dir($path, $options = array())
 296      {
 297          $result = array();
 298  
 299          $path = rtrim($path, '/\\');
 300          $default_options = array(
 301          'files' => true,
 302          'dirs' => true,
 303          'recurse' => false,
 304          );
 305  
 306          $options = array_merge($default_options, $options);
 307  
 308          if(is_file($path)){
 309              $result = array($path);
 310          }elseif(is_dir($path)){
 311              if ($id_dir = opendir($path)){
 312                  while (false !== ($file = readdir($id_dir))){
 313                      if ($file != "." && $file != ".." && $file != '.svn'){
 314                          if(!empty($options['files']) && !is_dir($path.DS.$file)){
 315                              $result[] = $file;
 316                          }elseif(!empty($options['dirs'])){
 317                              $result[][$file] = !empty($options['recurse']) ? Ak::dir($path.DS.$file, $options) : $file;
 318                          }
 319                      }
 320                  }
 321                  closedir($id_dir);
 322              }
 323          }
 324  
 325          return array_reverse($result);
 326      }
 327  
 328  
 329      function file_put_contents($file_name, $content, $options = array())
 330      {
 331  
 332          $default_options = array(
 333          'ftp' => defined('AK_UPLOAD_FILES_USING_FTP') && AK_UPLOAD_FILES_USING_FTP,
 334          'base_path' => AK_BASE_DIR,
 335          );
 336          $options = array_merge($default_options, $options);
 337  
 338          if(!function_exists('file_put_contents')){
 339              include_once(AK_CONTRIB_DIR.DS.'pear'.DS.'PHP'.DS.'Compat.php');
 340              PHP_Compat::loadFunction(array('file_put_contents'));
 341          }
 342  
 343          $file_name = trim(str_replace($options['base_path'], '',$file_name),DS);
 344  
 345          if($options['ftp']){
 346              require_once (AK_LIB_DIR.DS.'AkFtp.php');
 347              $file_name = trim(str_replace(array(DS,'//'),array('/','/'),$file_name),'/');
 348              if(!AkFtp::is_dir(dirname($file_name))){
 349                  AkFtp::make_dir(dirname($file_name));
 350              }
 351  
 352              return AkFtp::put_contents($file_name, $content);
 353          }else{
 354              if(!is_dir(dirname($options['base_path'].DS.$file_name))){
 355                  Ak::make_dir(dirname($options['base_path'].DS.$file_name), $options);
 356              }
 357  
 358              if(!$result = file_put_contents($options['base_path'].DS.$file_name, $content)){
 359                  if(!empty($content)){
 360                      Ak::trace("Could not write to file: \"".$options['base_path'].DS."$file_name\". Please change file/dir permissions or enable FTP file handling by".
 361                      " setting the following on your config/".AK_ENVIRONMENT.".php file \n<pre>define('AK_UPLOAD_FILES_USING_FTP', true);\n".
 362                      "define('AK_READ_FILES_USING_FTP', false);\n".
 363                      "define('AK_DELETE_FILES_USING_FTP', true);\n".
 364                      "define('AK_FTP_PATH', 'ftp://username:password@example.com/path_to_the_framework');\n".
 365                      "define('AK_FTP_AUTO_DISCONNECT', true);\n</pre>");
 366                  }
 367              }
 368              return $result;
 369          }
 370      }
 371  
 372  
 373      function file_get_contents($file_name, $options = array())
 374      {
 375          $default_options = array(
 376          'ftp' => defined('AK_READ_FILES_USING_FTP') && AK_READ_FILES_USING_FTP,
 377          'base_path' => AK_BASE_DIR,
 378          );
 379          $options = array_merge($default_options, $options);
 380  
 381          $file_name = trim(str_replace($options['base_path'], '',$file_name),DS);
 382          if($options['ftp']){
 383              require_once (AK_LIB_DIR.DS.'AkFtp.php');
 384              $file_name = trim(str_replace(array(DS,'//'),array('/','/'),$file_name),'/');
 385              return AkFtp::get_contents($file_name);
 386          }else{
 387              return file_get_contents($options['base_path'].DS.$file_name);
 388          }
 389      }
 390  
 391      /**
 392       * @todo Optimize this code (dirty add-on to log command line interpreter results)
 393       */
 394      function file_add_contents($file_name, $content, $options = array())
 395      {
 396          $original_content = @Ak::file_get_contents($file_name, $options);
 397          return Ak::file_put_contents($file_name, $original_content.$content, $options);
 398      }
 399  
 400      function file_delete($file_name, $options = array())
 401      {
 402          $default_options = array(
 403          'ftp' => defined('AK_DELETE_FILES_USING_FTP') && AK_DELETE_FILES_USING_FTP,
 404          'base_path' => AK_BASE_DIR,
 405          );
 406          $options = array_merge($default_options, $options);
 407  
 408          $file_name = trim(str_replace($options['base_path'], '',$file_name),DS);
 409          if($options['ftp']){
 410              require_once (AK_LIB_DIR.DS.'AkFtp.php');
 411              $file_name = trim(str_replace(array(DS,'//'),array('/','/'),$file_name),'/');
 412              return AkFtp::delete($file_name, true);
 413          }else{
 414              return unlink($options['base_path'].DS.$file_name);
 415          }
 416      }
 417  
 418      function directory_delete($dir_name, $options = array())
 419      {
 420          $default_options = array(
 421          'ftp' => defined('AK_DELETE_FILES_USING_FTP') && AK_DELETE_FILES_USING_FTP,
 422          'base_path' => AK_BASE_DIR,
 423          );
 424          $options = array_merge($default_options, $options);
 425  
 426          $sucess = true;
 427          $dir_name = Ak::_getRestrictedPath($dir_name, $options);
 428  
 429          if(empty($dir_name)){
 430              return false;
 431          }
 432  
 433          if($options['ftp']){
 434              require_once (AK_LIB_DIR.DS.'AkFtp.php');
 435              return AkFtp::delete($dir_name);
 436          }else{
 437              $items = glob($options['base_path'].DS.$dir_name."/*");
 438              $hidden_items = glob($options['base_path'].DS.$dir_name."/.*");
 439              $fs_items = $items || $hidden_items ? array_merge((array)$items, (array)$hidden_items) : false;
 440              if($fs_items){
 441                  $items_to_delete = array('directories'=>array(), 'files'=>array());
 442                  foreach($fs_items as $fs_item) {
 443                      if($fs_item[strlen($fs_item)-1] != '.'){
 444                          $items_to_delete[ (is_dir($fs_item) ? 'directories' : 'files') ][] = $fs_item;
 445                      }
 446                  }
 447                  foreach ($items_to_delete['files'] as $file){
 448                      Ak::file_delete($file, $options);
 449                  }
 450                  foreach ($items_to_delete['directories'] as $directory){
 451                      $sucess = $sucess ? Ak::directory_delete($directory, $options) : $sucess;
 452                  }
 453              }
 454              return $sucess ? @rmdir($options['base_path'].DS.$dir_name) : $sucess;
 455          }
 456      }
 457  
 458      function make_dir($path, $options = array())
 459      {
 460          $default_options = array(
 461          'ftp' => defined('AK_UPLOAD_FILES_USING_FTP') && AK_UPLOAD_FILES_USING_FTP,
 462          'base_path' => AK_BASE_DIR
 463          );
 464          $options = array_merge($default_options, $options);
 465  
 466          $path = trim(str_replace($options['base_path'], '',$path),DS);
 467          if($options['ftp']){
 468              require_once(AK_LIB_DIR.DS.'AkFtp.php');
 469              $path = trim(str_replace(array(DS,'//'),array('/','/'),$path),'/');
 470              return AkFtp::make_dir($path);
 471          }else{
 472              $path = $options['base_path'].DS.$path;
 473              if (!file_exists($path)){
 474                  Ak::make_dir(dirname($path), $options);
 475                  return mkdir($path);
 476              }
 477          }
 478          return false;
 479      }
 480  
 481      /**
 482      * This static method will copy recursively all the files or directories from one
 483      * path within an Akelos application to another.
 484      * 
 485      * It uses current installation settings, so it can perform copies via the filesystem or via FTP
 486      */
 487      function copy($origin, $target, $options = array())
 488      {
 489          $default_options = array(
 490          'ftp' => defined('AK_UPLOAD_FILES_USING_FTP') && AK_UPLOAD_FILES_USING_FTP,
 491          'base_path' => AK_BASE_DIR,
 492          );
 493          $options = array_merge($default_options, $options);
 494  
 495          $sucess = true;
 496  
 497          $origin = Ak::_getRestrictedPath($origin, $options);
 498          $target = Ak::_getRestrictedPath($target, $options);
 499  
 500          if(empty($origin) || empty($target)){
 501              return false;
 502          }
 503  
 504          if($options['ftp']){
 505              require_once (AK_LIB_DIR.DS.'AkFtp.php');
 506          }
 507          $destination = str_replace($origin, $target, $origin);
 508          if(is_file($options['base_path'].DS.$origin)){
 509              return Ak::file_put_contents($options['base_path'].DS.$destination, Ak::file_get_contents($options['base_path'].DS.$origin, $options), $options);
 510          }
 511          Ak::make_dir($options['base_path'].DS.$destination);
 512          if($fs_items = glob($options['base_path'].DS.$origin."/*")){
 513              $items_to_copy = array('directories'=>array(), 'files'=>array());
 514              foreach($fs_items as $fs_item) {
 515                  $items_to_copy[ (is_dir($fs_item) ? 'directories' : 'files') ][] = $fs_item;
 516              }
 517              foreach ($items_to_copy['files'] as $file){
 518                  $destination = str_replace($origin, $target, $file);
 519                  $sucess = $sucess ? Ak::file_put_contents($destination, Ak::file_get_contents($file, $options), $options) : $sucess;
 520              }
 521              foreach ($items_to_copy['directories'] as $directory){
 522                  $destination = str_replace($origin, $target, $directory);
 523                  $sucess = $sucess ? Ak::copy($directory, $destination, $options) : $sucess;
 524              }
 525          }
 526          return $sucess;
 527      }
 528  
 529      /**
 530       * Returns a path restricting it to a base location
 531       * 
 532       * This is used by Akelos to prevent functions namespaced under Ak
 533       * from writing out of the Akelos base directory for security reasons.
 534       */
 535      function _getRestrictedPath($path, $options = array())
 536      {
 537          $default_options = array(
 538          'ftp' => false,
 539          'base_path' => AK_BASE_DIR,
 540          );
 541          $options = array_merge($default_options, $options);
 542  
 543          $path = str_replace('..','', rtrim($path,'\\/. '));
 544          $path = trim(str_replace($options['base_path'], '',$path),DS);
 545  
 546          if($options['ftp']){
 547              $path = trim(str_replace(array(DS,'//'),array('/','/'), $path),'/');
 548          }
 549  
 550          return $path;
 551      }
 552  
 553  
 554      /**
 555       * Perform a web request
 556       * 
 557       * @param string $url URL we are going to request.
 558       * @param array $options Options for current request.
 559       *  Options are:
 560       * * referer: URL that will be set as referer url. Default is current url
 561       * * params: Parameter for the request. Can be an array of key=>values or a url params string like key=value&key2=value2
 562       * * method: In case params are given the will be requested using get method by default. Specify post if get is not what you need.
 563       * @return string
 564       */
 565      function url_get_contents($url, $options = array())
 566      {
 567          include_once (AK_LIB_DIR.DS.'AkHttpClient.php');
 568          $Client =& new AkHttpClient();
 569          $method = empty($options['method']) ? 'get' : strtolower($options['method']);
 570          if(empty($method) || !in_array($method, array('get','post','put','delete'))){
 571              trigger_error(Ak::t('Invalid HTTP method %method', array('%method'=>$options['method'])), E_USER_ERROR);
 572          }
 573          return $Client->$method($url, $options);
 574      }
 575  
 576  
 577      /**
 578      * Trace helper function for development purposes
 579      *
 580      * @access public
 581      * @static
 582      * @param    string    $text    Helper text
 583      * @param    string    $line    Helper line
 584      * @param    string    $file    Helper file
 585      * @return echoes result to screen
 586      */
 587      function trace($text = null, $line = null, $file = null)
 588      {
 589          static $counter = 0;
 590          if(!AK_DEBUG){
 591              //return;
 592          }
 593  
 594          $line = isset($line) ? "Line: $line".(AK_CLI?"\n":"<br />") : "";
 595          $file = isset($file) ? "File: $file".(AK_CLI?"\n":"<br />") : "";
 596  
 597          if(!isset($text)){
 598              $counter++;
 599              $text = '';
 600          }else {
 601              $text = AK_CLI?'---> '.$text:'<b>---&gt;</b>'.$text;
 602          }
 603  
 604          echo AK_CLI?"----------------\n$line $file $text\n----------------\n":"<hr /><div>$line $file $text</div><hr />\n";
 605  
 606      }
 607  
 608  
 609  
 610  
 611      /**
 612      * Outputs debug info given a PHP resource (vars, objects,
 613      * arrays...)
 614      *
 615      * @access public
 616      * @static
 617      * @param    mixed    $data    Data to debug. It can be an object, array,
 618      * resource..
 619      * @return void Prints debug info.
 620      */
 621      function debug ($data, $_functions=0)
 622      {
 623          if(!AK_DEBUG && !AK_DEV_MODE){
 624              return;
 625          }
 626  
 627          if($_functions!=0) {
 628              $sf=1;
 629          } else {
 630              $sf=0 ;
 631          }
 632          if(is_object($data) && method_exists($data, 'debug')){
 633              echo AK_CLI ?
 634              "\n------------------------------------\nEntering on ".get_class($data)." debug() method\n\n":
 635              "<hr /><h2>Entering on ".get_class($data)." debug() method</h2>";
 636              if(!empty($data->__activeRecordObject)){
 637                  $data->toString(true);
 638              }
 639              $data->debug();
 640              return ;
 641          }
 642          if (isset ($data)) {
 643              if (is_array($data) || is_object($data)) {
 644  
 645                  if (count ($data)) {
 646                      echo AK_CLI ? "/--\n" : "<ol>\n";
 647                      while (list ($key,$value) = each ($data)) {
 648                          $type=gettype($value);
 649                          if ($type=="array" || $type == "object") {
 650                              ob_start();
 651                              Ak::debug ($value,$sf);
 652                              $lines = explode("\n",ob_get_clean()."\n");
 653                              foreach ($lines as $line){
 654                                  echo "\t".$line."\n";
 655                              }
 656                          } elseif (eregi ("function", $type)) {
 657                              if ($sf) {
 658                                  AK_CLI ? printf ("\t* (%s) %s:\n",$type, $key, $value) :
 659                                  printf ("<li>(%s) <b>%s</b> </li>\n",$type, $key, $value);
 660                              }
 661                          } else {
 662                              if (!$value) {
 663                                  $value="(none)";
 664                              }
 665                              AK_CLI ? printf ("\t* (%s) %s = %s\n",$type, $key, $value) :
 666                              printf ("<li>(%s) <b>%s</b> = %s</li>\n",$type, $key, $value);
 667                          }
 668                      }
 669                      echo AK_CLI ? "\n--/\n" : "</ol>fin.\n";
 670                  } else {
 671                      echo "(empty)";
 672                  }
 673              }
 674          }
 675      }
 676  
 677  
 678  
 679  
 680  
 681      /**
 682      * Gets information about given object
 683      *
 684      * @access public
 685      * @static
 686      * @uses Ak::get_this_object_methods
 687      * @uses Ak::get_this_object_attributes
 688      * @param    object    &$object    Object to get info from
 689      * @param    boolean    $include_inherited_info    By setting this to true, parent Object properties
 690      * and methods will be included.
 691      * @return string html output with Object info
 692      */
 693      function get_object_info($object, $include_inherited_info = false)
 694      {
 695          $object_name = get_class($object);
 696          $methods = $include_inherited_info ? get_class_methods($object) : Ak::get_this_object_methods($object);
 697          $vars = $include_inherited_info ? get_class_vars($object_name) : Ak::get_this_object_attributes($object);
 698          $var_desc = '';
 699          if(is_array($vars)){
 700              $var_desc = '<ul>';
 701              foreach ($vars as $varname=>$var_value){
 702                  $var_desc .= "<li>$varname = $var_value (". gettype($var_value) .")</li>\n";
 703              }
 704              $var_desc .= "</ul>";
 705          }
 706          return Ak::t('Object <b>%object_name</b> information:<hr> <b>object Vars:</b><br>%var_desc <hr> <b>object Methods:</b><br><ul><li>%methods</li></ul>',array('%object_name'=>$object_name,'%var_desc'=>$var_desc,'%methods'=>join("();</li>\n<li>",$methods) .'();'));
 707      }
 708  
 709  
 710  
 711  
 712      /**
 713      * Gets selected object methods.
 714      *
 715      * WARNING: Inherited methods are not returned by this
 716      * function. You can fetch them by using PHP native function
 717      * get_class_methods
 718      *
 719      * @access public
 720      * @static
 721      * @see get_this_object_attributes
 722      * @see get_object_info
 723      * @param    object    &$object    Object to inspect
 724      * @return array Returns an array with selected object methods. It
 725      * does not return inherited methods
 726      */
 727      function get_this_object_methods($object)
 728      {
 729          $array1 = get_class_methods($object);
 730          if($parent_object = get_parent_class($object)){
 731              $array2 = get_class_methods($parent_object);
 732              $array3 = array_diff($array1, $array2);
 733          }else{
 734              $array3 = $array1;
 735          }
 736          return array_values((array)$array3);
 737      }
 738  
 739  
 740  
 741  
 742      /**
 743      * Get selected objects default attributes
 744      *
 745      * WARNING: Inherited attributes are not returned by this
 746      * function. You can fetch them by using PHP native function
 747      * get_class_vars
 748      *
 749      * @access public
 750      * @static
 751      * @see get_this_object_methods
 752      * @see get_object_info
 753      * @param    object    &$object    Object to inspect
 754      * @return void Returns an array with selected object attributes.
 755      * It does not return inherited attributes
 756      */
 757      function get_this_object_attributes($object)
 758      {
 759          $object = get_class($object);
 760          $array1 = get_class_vars($object);
 761          if($parent_object = get_parent_class($object)){
 762              $array2 = get_class_vars($parent_object);
 763              $array3 = array_diff_assoc($array1, $array2);
 764          }else{
 765              $array3 = $array1;
 766          }
 767          return (array)$array3;
 768      }
 769  
 770  
 771  
 772      function &getLogger()
 773      {
 774          static $Logger;
 775          if(empty($Logger)){
 776              require_once (AK_LIB_DIR.DS.'AkLogger.php');
 777              $Logger = new AkLogger();
 778          }
 779          $return =& $Logger;
 780          return $Logger;
 781      }
 782  
 783  
 784      function get_constants()
 785      {
 786          $constants = get_defined_constants();
 787          $keys = array_keys($constants);
 788          foreach ($keys as $k){
 789              if(substr($k,0,3) != 'AK_'){
 790                  unset($constants[$k]);
 791              }
 792          }
 793          return $constants;
 794      }
 795  
 796  
 797      /**
 798      * @todo Use timezone time
 799      */
 800      function time()
 801      {
 802          return time()+(defined('AK_TIME_DIFERENCE') ? AK_TIME_DIFERENCE*3600 : 0);
 803      }
 804  
 805      function gmt_time()
 806      {
 807          return Ak::time()+(AK_TIME_DIFERENCE_FROM_GMT*3600);
 808      }
 809  
 810  
 811      /**
 812      * Gets a timestamp for input date provided in one of this formats: "year-month-day hour:min:sec", "year-month-day", "hour:min:sec"
 813      */
 814      function getTimestamp($iso_date_or_hour = null)
 815      {
 816          if(empty($iso_date_or_hour)){
 817              return Ak::time();
 818          }
 819          if (!preg_match("/^
 820              ([0-9]{4})[-\/\.]? # year
 821              ([0-9]{1,2})[-\/\.]? # month
 822              ([0-9]{1,2})[ -]? # day
 823              (
 824                  ([0-9]{1,2}):? # hour
 825                  ([0-9]{2}):? # minute
 826                  ([0-9\.]{0,4}) # seconds
 827              )?/x", ($iso_date_or_hour), $rr)){
 828          if (preg_match("|^(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($iso_date_or_hour), $rr)){
 829              return empty($rr[0]) ? Ak::time() : mktime($rr[2],$rr[3],$rr[4]);
 830          }
 831              }else{
 832                  if($rr[1]>=2038 || $rr[1]<=1970){
 833                      require_once(AK_CONTRIB_DIR.DS.'adodb'.DS.'adodb-time.inc.php');
 834                      return isset($rr[5]) ? adodb_mktime($rr[5],$rr[6],(int)$rr[7],$rr[2],$rr[3],$rr[1]) : adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]);
 835                  }else{
 836                      return isset($rr[5]) ? mktime($rr[5],$rr[6],(int)$rr[7],$rr[2],$rr[3],$rr[1]) : mktime(0,0,0,$rr[2],$rr[3],$rr[1]);
 837                  }
 838              }
 839              trigger_error(Ak::t('Invalid ISO date. You must supply date in one of the following formats: "year-month-day hour:min:sec", "year-month-day", "hour:min:sec"'));
 840              return false;
 841      }
 842  
 843      /**
 844      * Return formatted date.
 845      * 
 846      * You can supply a format as defined at http://php.net/date
 847      * 
 848      * Default date is in ISO format 
 849      */
 850      function getDate($timestamp = null, $format = null)
 851      {
 852          $timestamp = !isset($timestamp) ? Ak::time() : $timestamp;
 853          $use_adodb = $timestamp <= -3600 || $timestamp >= 2147468400;
 854          if($use_adodb){
 855              require_once(AK_CONTRIB_DIR.DS.'adodb'.DS.'adodb-time.inc.php');
 856          }
 857          if(!isset($format)){
 858              return $use_adodb ? adodb_date('Y-m-d H:i:s', $timestamp) : date('Y-m-d H:i:s', $timestamp);
 859          }elseif (!empty($format)){
 860              return $use_adodb ? adodb_date($format, $timestamp) : date($format, $timestamp);
 861          }
 862          trigger_error(Ak::t('You must supply a valid UNIX timetamp. You can get the timestamp by calling Ak::getTimestamp("2006-09-27 20:45:57")'));
 863          return false;
 864      }
 865  
 866  
 867      /**
 868      *   mail function substitute. Uses the PEAR::Mail() function API.
 869      *
 870      *   Messaging subsystem for user communication. See PEAR::Mail() function in PHP
 871      *   documentation for information.
 872      *
 873      *   User must declare any of these variables for specify the outgoing method. Currently,
 874      *   only Sendmail and STMP methods are available . Variables
 875      *   for using any of these methods are:
 876      *
 877      *   AK_SENDMAIL = 0
 878      *   AK_SMTP = 1
 879      *
 880      *   For future upgrades, you must define which constants must be declared and add 
 881      *   the functionality.
 882      *
 883      *   NOTE: If messaging method is SMTP, you must declare in config file (/config/config.php)
 884      *   the outgoing SMTP server and the authentication pair user/password as constants
 885      *   AK_SMTP_SERVER, AK_SMTP_USER and AK_SMTP_PASSWORD, respectively.
 886      *
 887      * 
 888      *   @param $from
 889      *   
 890      *   User who sends the mail.
 891      *   
 892      *   @param $to
 893      *
 894      *   Receiver, or receivers of the mail.
 895      *
 896      *   The formatting of this string must comply with RFC 2822. Some examples are:
 897      *
 898      *   user@example.com
 899      *   user@example.com, anotheruser@example.com
 900      *   User <user@example.com>
 901      *   User <user@example.com>, Another User <anotheruser@example.com>
 902      *    
 903      *   @param $subject
 904      *
 905      *   Subject of the email to be sent.  This must not contain any newline
 906      *   characters, or the mail may not be sent properly.
 907      *    
 908      *   @param $body
 909      *
 910      *   Message to be sent.
 911      *           
 912      *   @param additional_headers (optional)   
 913      *
 914      *   Array to be inserted at the end of the email header.
 915      *
 916      *   This is typically used to add extra headers (Bcc) in an associative array, where the 
 917      *   array key is the header name (i.e., 'Bcc'), and the array value is the header value 
 918      *   (i.e., 'test'). The header produced from those values would be 'Bcc: test'.
 919      *    
 920      *   @return boolean whether message has been sent or not.
 921      *
 922      */
 923      function mail ($from, $to, $subject, $body, $additional_headers = array())
 924      {
 925          require_once(AK_CONTRIB_DIR.DS.'pear'.DS.'Mail.php');
 926  
 927          static $mail_connector;
 928  
 929          if(!isset($mail_connector)){
 930              if (defined('AK_SENDMAIL')) {
 931                  // Using Sendmail daemon without parameters.
 932                  $mail_connector = Mail::factory('sendmail');
 933              } else if (defined('AK_SMTP') && AK_SMTP) {
 934                  // Using external SMTP server.
 935                  $params['host'] = AK_SMTP_SERVER;
 936                  $params['username'] = AK_SMTP_USER;
 937                  $params['password'] = AK_SMTP_PASSWORD;
 938  
 939                  $mail_connector = Mail::factory('smtp', $params);
 940              } else {
 941                  // Using PHP mail() function thru PEAR. Factory without parameters.
 942                  $mail_connector = Mail::factory('mail');
 943              }
 944          }
 945  
 946          $recipients['To'] = $to;
 947  
 948          if (!empty($additional_headers)) {
 949              foreach ($additional_headers as $k=>$v) {
 950  
 951                  if (strtolower($k)=='cc' || strtolower($k)=='cc:') {
 952                      $recipients['cc'] = $v;
 953                      unset($additional_headers['cc']);
 954                  }
 955  
 956                  if (strtolower($k)=='bcc' || strtolower($k)=='bcc:') {
 957                      $recipients['bcc'] = $v;
 958                      unset($additional_headers['bcc']);
 959                  }
 960              }
 961          }
 962  
 963          $headers['From'] = $from;
 964          $headers['Subject'] = $subject;
 965          $headers['Content-Type'] = empty($headers['Content-Type']) ? 'text/plain; charset='.Ak::locale('charset').'; format=flowed' : $headers['Content-Type'];
 966  
 967          $headers = array_merge($headers, $additional_headers);
 968  
 969          return $mail_connector->send($recipients, $headers, $body) == true;
 970      }
 971  
 972  
 973      /**
 974      * @todo move this out of here and use Pear Benchmark instead
 975      */
 976      function profile($message = '')
 977      {
 978          static $profiler;
 979          if(AK_DEV_MODE && AK_ENABLE_PROFILER){
 980              if(!isset($profiler)){
 981                  @require_once (AK_LIB_DIR.DS.'AkProfiler.php');
 982                  $profiler = new AkProfiler();
 983                  $profiler->init();
 984                  register_shutdown_function(array(&$profiler,'showReport'));
 985              }else {
 986                  $profiler->setFlag($message);
 987              }
 988          }
 989      }
 990  
 991  
 992      /**
 993      * Gets the size of given element. Counts arrays, returns numbers, string length or executes size() method on given object
 994      */
 995      function size($element)
 996      {
 997          if(is_array($element)){
 998              return count($element);
 999          }elseif (is_numeric($element) && !is_string($element)){
1000              return $element;
1001          }elseif (is_string($element)){
1002              return strlen($element);
1003          }elseif (is_object($element) && method_exists($element,'size')){
1004              return $element->size();
1005          }else{
1006              return 0;
1007          }
1008      }
1009  
1010  
1011      /**
1012       * Select is a function for selecting items from double depth array.
1013       * This is useful when you just need some fields for generating 
1014       * tables, select lists with only desired fields.
1015       *
1016       *   $People = array(
1017       *    array('name'=>'Jose','email'=>'jose@example.com','address'=>'Colon, 52'),
1018       *    array('name'=>'Alicia','email'=>'alicia@example.com','address'=>'Mayor, 45'),
1019       *    array('name'=>'Hilario','email'=>'hilario@example.com','address'=>'Carlet, 78'),
1020       *    array('name'=>'Bermi','email'=>'bermi@example.com','address'=>'Vilanova, 33'),
1021       *   );
1022       * 
1023       *    $people_for_table_generation = Ak::select($People,'name','email');
1024       *    
1025       *    Now $people_for_table_generation will hold an array with
1026       *    array (
1027       *        array ('name' => 'Jose','email' => 'jose@example.com'),
1028       *        array ('name' => 'Alicia','email' => 'alicia@example.com'),
1029       *        array ('name' => 'Hilario','email' => 'hilario@example.com'),
1030       *        array ('name' => 'Bermi','email' => 'bermi@example.com')
1031       *    );
1032       */
1033  
1034      function select(&$source_array)
1035      {
1036          $resulting_array = array();
1037          if(!empty($source_array) && is_array($source_array) && func_num_args() > 1) {
1038              $args = array_slice(func_get_args(),1);
1039              foreach ($source_array as $source_item){
1040                  $item_fields = array();
1041                  foreach ($args as $arg){
1042                      if(is_object($source_item) && isset($source_item->$arg)){
1043                          $item_fields[$arg] = $source_item->$arg;
1044                      }elseif(is_array($source_item) && isset($source_item[$arg])){
1045                          $item_fields[$arg] = $source_item[$arg];
1046                      }
1047                  }
1048                  if(!empty($item_fields)){
1049                      $resulting_array[] = $item_fields;
1050                  }
1051              }
1052          }
1053          return $resulting_array;
1054      }
1055  
1056      function collect(&$source_array, $key_index, $value_index)
1057      {
1058          $resulting_array = array();
1059          if(!empty($source_array) && is_array($source_array)) {
1060              foreach ($source_array as $source_item){
1061                  if(is_object($source_item)){
1062                      $resulting_array[@$source_item->$key_index] = @$source_item->$value_index;
1063                  }elseif(is_array($source_item)){
1064                      $resulting_array[@$source_item[$key_index]] = @$source_item[$value_index];
1065                  }
1066              }
1067          }
1068          return $resulting_array;
1069      }
1070  
1071      function delete($source_array, $attributes_to_delete_from_array)
1072      {
1073          $resulting_array = (array)$source_array;
1074          $args = array_slice(func_get_args(),1);
1075          $args = count($args) == 1 ? Ak::toArray($args[0]) : $args;
1076          foreach ($args as $arg){
1077              unset($resulting_array[$arg]);
1078          }
1079          return $resulting_array;
1080      }
1081  
1082      function &singleton($class_name, &$arguments)
1083      {
1084          static $instances;
1085          if(!isset($instances[$class_name])) {
1086              if(is_object($arguments)){
1087                  $instances[$class_name] =& new $class_name($arguments);
1088              }else{
1089                  if(Ak::size($arguments) > 0){
1090                      eval("\$instances[\$class_name] =& new \$class_name(".var_export($arguments, true)."); ");
1091                  }else{
1092                      $instances[$class_name] =& new $class_name();
1093                  }
1094              }
1095              $instances[$class_name]->__singleton_id = md5(microtime().rand(1000,9000));
1096          }
1097          return $instances[$class_name];
1098      }
1099  
1100  
1101      function xml_to_array ($xml_data)
1102      {
1103          $xml_parser = xml_parser_create ();
1104          xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
1105          xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1);
1106          xml_parse_into_struct ($xml_parser, $xml_data, $vals, $index);
1107          xml_parser_free ($xml_parser);
1108          $params = array();
1109          $ptrs[0] = & $params;
1110          foreach ($vals as $xml_elem) {
1111              $level = $xml_elem['level'] - 1;
1112              switch ($xml_elem['type']) {
1113                  case 'open':
1114                      $tag_or_id = (array_key_exists ('attributes', $xml_elem)) ? @$xml_elem['attributes']['ID'] : $xml_elem['tag'];
1115                      $ptrs[$level][$tag_or_id][] = array ();
1116                      $ptrs[$level+1] = & $ptrs[$level][$tag_or_id][count($ptrs[$level][$tag_or_id])-1];
1117                      break;
1118                  case 'complete':
1119                      $ptrs[$level][$xml_elem['tag']] = (isset ($xml_elem['value'])) ? $xml_elem['value'] : '';
1120                      break;
1121              }
1122          }
1123          return ($params);
1124      }
1125  
1126      function array_to_xml($array, $header = "<?xml version=\"1.0\"?>\r\n", $parent = 'EMPTY_TAG')
1127      {
1128          static $_tags = array();
1129          $xml = $header;
1130          foreach ($array as $key => $value) {
1131              $key = is_numeric($key) ? $parent : $key;
1132              $value = is_array($value) ? "\r\n".Ak::array_to_xml($value, '', $key) : $value;
1133              $_tags[$key] = $key;
1134              $xml .= sprintf("<%s>%s</%s>\r\n", $key, $value, $key);
1135              $parent = $key;
1136          }
1137          foreach ($_tags as $_tag){
1138              $xml = str_replace(array("<$_tag>\r\n<$_tag>","</$_tag>\r\n</$_tag>"),array("<$_tag>","</$_tag>"),$xml);
1139          }
1140          return $xml;
1141      }
1142  
1143  
1144      function encrypt($data, $key = null)
1145      {
1146          $key = empty($key) ? md5(AK_SESSION_NAME) : $key;
1147          srand((double)microtime() *1000000);
1148          $k2 = md5(rand(0, 32000));
1149          $c = 0;
1150          $m = '';
1151          for ($i = 0 ; $i < strlen($data) ; $i++) {
1152              if ($c == strlen($k2)) $c = 0;
1153              $m.= substr($k2, $c, 1) .(substr($data, $i, 1) ^substr($k2, $c, 1));
1154              $c++;
1155          }
1156          $k = md5($key);
1157          $c = 0;
1158          $t = $m;
1159          $m = '';
1160          for ($i = 0 ; $i < strlen($t) ; $i++) {
1161              if ($c == strlen($k)) {
1162                  $c = 0;
1163              }
1164              $m.= substr($t, $i, 1) ^substr($k, $c, 1);
1165              $c++;
1166          }
1167          return base64_encode($m);
1168      }
1169  
1170      function decrypt($encrypted_data, $key = null)
1171      {
1172          $key = empty($key) ? md5(AK_SESSION_NAME) : $key;
1173          $t = base64_decode($encrypted_data);
1174          $k = md5($key);
1175          $c = 0;
1176          $m = '';
1177          for ($i = 0 ; $i < strlen($t) ; $i++) {
1178              if ($c == strlen($k)) $c = 0;
1179              $m.= substr($t, $i, 1) ^substr($k, $c, 1);
1180              $c++;
1181          }
1182          $t = $m;
1183          $m = '';
1184          for ($i = 0 ; $i < strlen($t) ; $i++) {
1185              $d = substr($t, $i, 1);
1186              $i++;
1187              $m.= (substr($t, $i, 1) ^$d);
1188          }
1189          return $m;
1190      }
1191  
1192  
1193      function blowfishEncrypt($data, $key = null)
1194      {
1195          $key = empty($key) ? md5(AK_SESSION_NAME) : $key;
1196          $key = substr($key,0,56);
1197          require_once(AK_CONTRIB_DIR.DS.'pear'.DS.'Crypt'.DS.'Blowfish.php');
1198          $Blowfish =& Ak::singleton('Crypt_Blowfish', $key);
1199          $Blowfish->setKey($key);
1200          return $Blowfish->encrypt(base64_encode($data));
1201      }
1202  
1203      function blowfishDecrypt($encrypted_data, $key = null)
1204      {
1205          $key = empty($key) ? md5(AK_SESSION_NAME) : $key;
1206          $key = substr($key,0,56);
1207          require_once(AK_CONTRIB_DIR.DS.'pear'.DS.'Crypt'.DS.'Blowfish.php');
1208          $Blowfish =& Ak::singleton('Crypt_Blowfish', $key);
1209          $Blowfish->setKey($key);
1210          return base64_decode($Blowfish->decrypt($encrypted_data));
1211      }
1212  
1213  
1214      function randomString($max_length = 8)
1215      {
1216          $randomString = '';
1217          srand((double)microtime()*1000000);
1218          for($i=0;$i<$max_length;$i++){
1219              $randnumber = rand(48,120);
1220              while (($randnumber >= 58 && $randnumber <= 64) || ($randnumber >= 91 && $randnumber <= 96)){
1221                  $randnumber = rand(48,120);
1222              }
1223              $randomString .= chr($randnumber);
1224          }
1225          return $randomString;
1226      }
1227  
1228  
1229      function compress($data, $format = 'gzip')
1230      {
1231          $key = Ak::randomString(15);
1232          $compressed_file = AK_TMP_DIR.DS.'d'.$key;
1233          $uncompressed_file = AK_TMP_DIR.DS.'s'.$key;
1234          if(Ak::file_put_contents($uncompressed_file, $data, array('base_path'=>AK_TMP_DIR))){
1235              $compressed = gzopen($compressed_file,'w9');
1236              $uncompressed = fopen($uncompressed_file, 'rb');
1237              while(!feof($uncompressed)){
1238                  $string = fread($uncompressed, 1024*512);
1239                  gzwrite($compressed, $string, strlen($string));
1240              }
1241              fclose($uncompressed);
1242              gzclose($compressed);
1243          }else{
1244              trigger_error(Ak::t('Could not write to temporary directory for generating compressed file using Ak::compress(). Please provide write access to %dirname', array('%dirname'=>AK_TMP_DIR)), E_USER_ERROR);
1245          }
1246          $result = Ak::file_get_contents($compressed_file, array('base_path'=>AK_TMP_DIR));
1247          return $result;
1248      }
1249  
1250      function uncompress($compressed_data, $format = 'gzip')
1251      {
1252          $key = Ak::randomString(15);
1253          $compressed_file = AK_TMP_DIR.DS.'s'.$key;
1254          $uncompressed_file = AK_TMP_DIR.DS.'d'.$key;
1255  
1256          if(Ak::file_put_contents($compressed_file, $compressed_data, array('base_path'=>AK_TMP_DIR))){
1257              $compressed = gzopen($compressed_file, "r");
1258              $uncompressed = fopen($uncompressed_file, "w");
1259              while(!gzeof($compressed)){
1260                  $string = gzread($compressed, 4096);
1261                  fwrite($uncompressed, $string, strlen($string));
1262              }
1263              gzclose($compressed);
1264              fclose($uncompressed);
1265          }else{
1266              trigger_error(Ak::t('Could not write to temporary directory for generating uncompressing file using Ak::uncompress(). Please provide write access to %dirname', array('%dirname'=>AK_TMP_DIR)), E_USER_ERROR);
1267          }
1268          $result = Ak::file_get_contents($uncompressed_file, array('base_path'=>AK_TMP_DIR));
1269          return $result;
1270      }
1271  
1272  
1273      function unzip($file_to_unzip, $destination_folder)
1274      {
1275          require_once (AK_LIB_DIR.DS.'AkZip.php');
1276          $ArchiveZip =& new AkZip($file_to_unzip);
1277          $ArchiveZip->extract(array('add_path'=>str_replace(DS,'/',$destination_folder)));
1278      }
1279  
1280  
1281      function decompress($compressed_data, $format = 'gzip')
1282      {
1283          return Ak::uncompress($compressed_data, $format);
1284      }
1285  
1286  
1287      function handleStaticCall()
1288      {
1289          if (AK_PHP5) {
1290              trigger_error(Ak::t('Static calls emulation is not supported by PHP5 < 5.4'));
1291              die();
1292          }
1293          $static_call = array_slice(debug_backtrace(),1,1);
1294          return  call_user_func_array(array(new $static_call[0]['class'](),$static_call[0]['function']),$static_call[0]['args']);
1295      }
1296  
1297  
1298      /**
1299       * Gets an array or a comma separated list of models. Then it includes its 
1300       * respective files and returns an array of available models.
1301       *
1302       * @return array available models
1303       */
1304      function import()
1305      {
1306          $args = func_get_args();
1307          $args = is_array($args[0]) ? $args[0] : (func_num_args() > 1 ? $args : Ak::stringToArray($args[0]));
1308          $models = array();
1309          foreach ($args as $arg){
1310              $model_name = AkInflector::camelize($arg);
1311              if (class_exists($model_name)){
1312                  $models[] = $model_name;
1313                  continue;
1314              }
1315              $model = AkInflector::toModelFilename($model_name);
1316              if (file_exists($model)){
1317                  $models[] = $model_name;
1318                  include_once($model);
1319                  continue;
1320              }
1321              // Shouldn't we trigger an user-error?: Unknown Model or could not find the Model
1322          }
1323  
1324          return $models;
1325      }
1326      
1327      function import_mailer()
1328      {
1329          require_once (AK_LIB_DIR.DS.'AkActionMailer.php');
1330          $args = func_get_args();
1331          return call_user_func_array(array('Ak','import'),$args);
1332      }
1333  
1334      function uses()
1335      {
1336          $args = func_get_args();
1337          return call_user_func_array(array('Ak','import'),$args);
1338      }
1339  
1340      function stringToArray($string)
1341      {
1342          $args = $string;
1343          if(count($args) == 1 && !is_array($args)){
1344          (array)$args = array_unique(array_map('trim',array_diff(explode(',',strtr($args.',',';|-',',,,')),array(''))));
1345          }
1346          return $args;
1347      }
1348  
1349  
1350      function toArray()
1351      {
1352          $args = func_get_args();
1353          return is_array($args[0]) ? $args[0] : (func_num_args() === 1 ? Ak::stringToArray($args[0]) : $args);
1354      }
1355      
1356      /**
1357       * Returns an array including only the elements with provided keys.
1358       * 
1359       * This is useful to limit the parameters of an array used by a method.
1360       *
1361       * This utility can be used for modifying arrays which is useful for securing record creation/updating.
1362       *
1363       * If you have this code on a controller
1364       * 
1365       *     $this->user->setAttributes($this->params['user']);
1366       * 
1367       * and your users table has a column named is_admin. All it would take to a malicious user is to modify the page html to add the need field and gain admin privileges.
1368       * 
1369       * You could avoid by using the new Ak::pick method which will return and array with desired keys.
1370       * 
1371       *     $this->user->setAttributes(Ak::pick('name,email', $this->params['user']));
1372       * 
1373       */
1374      function pick($keys, $source_array)
1375      {
1376          $result = array();
1377          foreach (Ak::toArray($keys) as $k){
1378              $result[$k] = isset($source_array[$k]) ? $source_array[$k] : null;
1379          }
1380          return $result;
1381      }
1382      
1383      /**
1384       * Gets a copy of the first element of an array. Similar to array_shift but it does not modify the original array 
1385       */
1386      function first()
1387      {
1388          $args = func_get_args();
1389          return array_shift(array_slice(is_array($args[0]) ? $args[0] : $args , 0));
1390      }
1391      
1392      /**
1393       * Gets a copy of the last element of an array. Similar to array_pop but it does not modify the original array 
1394       */
1395      function last()
1396      {
1397          $args = func_get_args();
1398          return array_shift(array_slice(is_array($args[0]) ? $args[0] : $args , -1));
1399      }
1400  
1401      /**
1402       * Includes PHP functions that are not available on current PHP version
1403       */
1404      function compat($function_name)
1405      {
1406          ak_compat($function_name);
1407      }
1408  
1409  
1410      /**
1411      * The Akelos Framework has an standardized way to convert between formats.
1412      * You can find available converters on AkConverters
1413      * 
1414      * Usage Example: In order to convert from HTML to RTF you just need to call.
1415      * $rtf = Ak::convert('html','rtf', $my_html_file, array('font_size'=> 24));
1416      * 
1417      * Where the last option is an array of options for selected converter.
1418      * 
1419      * Previous example is the same as.
1420      * 
1421      * $rtf = Ak::convert(array('from'=>'html','to'=>'rtf', 'source' => $my_html_file, 'font_size'=> 24));
1422      * 
1423      * In order to create converters, you just need to name them "SourceFormatName + To + DestinationFormatName".
1424      * Whenever you need to call the, you need to specify the "path" option where your converter is located.
1425      * The only thing you converter must implement is a convert function. Passes options will be made available
1426      * as attributes on the converter.
1427      * If your converter needs to prepare something before the convert method is called, you just need to implement
1428      * a "init" method. You can avoid this by inspecting passed attributes to your constructor
1429      */
1430      function convert()
1431      {
1432          $args = func_get_args();
1433          $number_of_arguments = func_num_args();
1434          if($number_of_arguments > 1){
1435              $options = array();
1436              if($number_of_arguments > 3 && is_array($args[$number_of_arguments-1])){
1437                  $options = array_pop($args);
1438              }
1439              $options['from'] = $args[0];
1440              $options['to'] = $args[1];
1441              $options['source'] = $args[2];
1442          }else{
1443              $options = $args;
1444          }
1445          if ($options['from'] == $options['to']) {
1446              return $options['source'];
1447          }
1448          $options['class_prefix'] = empty($options['class_prefix']) && empty($options['path']) ? 'Ak' : $options['class_prefix'];
1449          $options['path'] = rtrim(empty($options['path']) ? AK_LIB_DIR.DS.'AkConverters' : $options['path'], DS."\t ");
1450  
1451          $converter_class_name = $options['class_prefix'].AkInflector::camelize($options['from']).'To'.AkInflector::camelize($options['to']);
1452          if(!class_exists($converter_class_name)){
1453              $file_name = $options['path'].DS.$converter_class_name.'.php';
1454              if(!file_exists($file_name)){
1455                  if(defined('AK_REMOTE_CONVERTER_URI')){
1456                      require_once (AK_LIB_DIR.DS.'AkConverters'.DS.'AkRemoteConverter.php');
1457                      $result = AkRemoteConverter::convert($options['from'], $options['to'], $options['source']);
1458                      if($result !== false){
1459                          return $result;
1460                      }
1461                  }
1462                  trigger_error(Ak::t('Could not locate %from to %to converter on %file_name',array('%from'=>$options['from'],'%to'=>$options['to'],'%file_name'=>$file_name)),E_USER_NOTICE);
1463                  return false;
1464              }
1465              require_once($file_name);
1466          }
1467          if(!class_exists($converter_class_name)){
1468              trigger_error(Ak::t('Could not load %converter_class_name converter class',array('%converter_class_name'=>$converter_class_name)),E_USER_NOTICE);
1469              return false;
1470          }
1471  
1472          $converter = new $converter_class_name($options);
1473          foreach ($options as $option=>$value){
1474              $option[0] != '_' ? $converter->$option = $value : null;
1475          }
1476  
1477          if(method_exists($converter, 'init')){
1478              $converter->init();
1479          }
1480          return $converter->convert();
1481      }
1482  
1483  
1484      /**
1485       * Converts given string to UTF-8
1486       *
1487       * @param string $text 
1488       * @param string $input_string_encoding
1489       * @return string UTF-8 encoded string
1490       */
1491      function utf8($text, $input_string_encoding = null)
1492      {
1493          $input_string_encoding = empty($input_string_encoding) ? Ak::encoding() : $input_string_encoding;
1494          require_once (AK_LIB_DIR.DS.'AkCharset.php');
1495          $Charset =& Ak::singleton('AkCharset',$text);
1496          return $Charset->RecodeString($text,'UTF-8',$input_string_encoding);
1497      }
1498  
1499      function recode($text, $output_string_encoding = null, $input_string_encoding = null, $recoding_engine = null)
1500      {
1501          $input_string_encoding = empty($input_string_encoding) ? Ak::encoding() : $input_string_encoding;
1502          require_once (AK_LIB_DIR.DS.'AkCharset.php');
1503          $Charset =& Ak::singleton('AkCharset',$text);
1504          return $Charset->RecodeString($text,$output_string_encoding,$input_string_encoding, $recoding_engine);
1505      }
1506  
1507      function encoding()
1508      {
1509          static $encoding;
1510          if(empty($encoding)){
1511              // This will force system language settings
1512              Ak::t('Akelos');
1513              $encoding = Ak::locale('charset', Ak::lang());
1514              $encoding = empty($encoding) ? 'UTF-8' : $encoding;
1515          }
1516          return $encoding;
1517      }
1518  
1519      /**
1520       * Get the encoding in which current user is sending the request
1521       */
1522      function userEncoding()
1523      {
1524          static $encoding;
1525  
1526          if(!isset($encoding)){
1527              $encoding = Ak::encoding();
1528              if(!empty($_SERVER['HTTP_ACCEPT_CHARSET'])){
1529                  $accepted_charsets = array_map('strtoupper', array_diff(explode(';',str_replace(',',';',$_SERVER['HTTP_ACCEPT_CHARSET']).';'), array('')));
1530                  if(!in_array($encoding,$accepted_charsets)){
1531                      $encoding = array_shift($accepted_charsets);
1532                  }
1533              }
1534          }
1535          return $encoding;
1536      }
1537  
1538      /**
1539       * strlen for UTF-8 strings
1540       * Taken from anpaza at mail dot ru post at http://php.net/strlen
1541       */
1542      function strlen_utf8($str)
1543      {
1544          $i = $count = 0;
1545          $len = strlen ($str);
1546          while ($i < $len){
1547              $chr = ord ($str[$i]);
1548              $count++;
1549              $i++;
1550              if ($i >= $len){
1551                  break;
1552              }
1553              if ($chr & 0x80){
1554                  $chr <<= 1;
1555                  while ($chr & 0x80){
1556                      $i++;
1557                      $chr <<= 1;
1558                  }
1559              }
1560          }
1561          return $count;
1562      }
1563  
1564      /**
1565       * Convert an arbitrary PHP value into a JSON representation string.
1566       * 
1567       * For AJAX driven pages, JSON can come in handy – you can return send JavaScript objects 
1568       * directly from your actions.
1569       */
1570      function toJson($php_value)
1571      {
1572          require_once(AK_VENDOR_DIR.DS.'pear'.DS.'Services'.DS.'JSON.php');
1573          $use = 0;
1574          $json =& Ak::singleton('Services_JSON', $use);
1575          return $json->encode($php_value);
1576      }
1577  
1578      /**
1579       * Converts a JSON representation string into a PHP value.
1580       */    
1581      function fromJson($json_string)
1582      {
1583          require_once(AK_VENDOR_DIR.DS.'pear'.DS.'Services'.DS.'JSON.php');
1584          $use = 0;
1585          $json =& Ak::singleton('Services_JSON', $use);
1586          return $json->decode($json_string);
1587      }
1588  
1589      function &memory_cache($key, &$value)
1590      {
1591          static $memory, $md5;
1592          if($value === false){
1593              // remove the object from cache
1594              $memory[$key] = null;
1595              $md5[$key] = null;
1596          }elseif($value === true){
1597              //check if the object is on cache or unaltered
1598              $result = !empty($memory[$key]) ? $md5[$key] == Ak::getStatusKey($memory[$key]) : false;
1599              return $result;
1600          }elseif ($value === null){
1601              //get the object
1602              return $memory[$key];
1603          }else{
1604              //set the object
1605              $md5[$key] = Ak::getStatusKey($value);
1606              $memory[$key] =& $value;
1607          }
1608  
1609          return $value;
1610      }
1611  
1612      function getStatusKey($element)
1613      {
1614          if(AK_PHP5){
1615              $element = clone($element);
1616          }
1617          if(isset($element->___status_key)){
1618              unset($element->___status_key);
1619          }
1620          return md5(serialize($element));
1621      }
1622  
1623      function logObjectForModifications(&$object)
1624      {
1625          $object->___status_key = empty($object->___status_key) ? Ak::getStatusKey($object) : $object->___status_key;
1626          return $object->___status_key;
1627      }
1628  
1629      function resetObjectModificationsWacther(&$object)
1630      {
1631          unset($object->___status_key);
1632      }
1633  
1634      function objectHasBeenModified(&$object)
1635      {
1636          if(isset($object->___status_key)){
1637              $old_status = $object->___status_key;
1638              $new_key = Ak::getStatusKey($object);
1639              return $old_status != $new_key;
1640          }else{
1641              Ak::logObjectForModifications($object);
1642              return false;
1643          }
1644          return true;
1645      }
1646  
1647      function &call_user_func_array($function_name, $parameters)
1648      {
1649          if(AK_PHP5){
1650              $result = call_user_func_array($function_name, $parameters);
1651              return $result;
1652          }
1653          $user_function_name = is_string($function_name) ? $function_name : (is_object($function_name[0]) ? '$function_name[0]->'.$function_name[1] : $function_name[0].'::'.$function_name[1]);
1654          $arguments = array();
1655          $argument_keys = array_keys($parameters);
1656          foreach($argument_keys as $k){
1657              $arguments[] = '$parameters['.$argument_keys[$k].']';
1658          }
1659          eval('$_result =& '.$user_function_name.'('.implode($arguments, ', ').');');
1660          // Dirty hack for avoiding pass by reference warnings.
1661          $result =& $_result;
1662          return $result;
1663      }
1664  
1665  
1666      function &array_sort_by($array,  $key = null, $direction = 'asc')
1667      {
1668          $array_copy = $sorted_array = array();
1669          foreach (array_keys($array) as $k) {
1670              $array_copy[$k] =& $array[$k][$key];
1671          }
1672  
1673          natcasesort($array_copy);
1674          if(strtolower($direction) == 'desc'){
1675              $array_copy = array_reverse($array_copy, true);
1676          }
1677  
1678          foreach (array_keys($array_copy) as $k){
1679              $sorted_array[$k] =& $array[$k];
1680          }
1681  
1682          return $sorted_array;
1683      }
1684    
1685      function mime_content_type($file)
1686      {
1687          static $mime_types;
1688          ak_compat('mime_content_type');
1689          empty($mime_types) ? require (AK_LIB_DIR.DS.'utils'.DS.'mime_types.php') : null;
1690          $file_extension = substr($file,strrpos($file,'.')+1);
1691          return !empty($mime_types[$file_extension]) ? $mime_types[$file_extension] : false;
1692      }
1693  
1694      function stream($path, $buffer_size = 4096)
1695      {
1696          ob_implicit_flush();
1697          $len = empty($buffer_size) ? 4096 : $buffer_size;
1698          $fp = fopen($path, "rb");
1699          while (!feof($fp)) {
1700              echo fread($fp, $len);
1701          }
1702      }
1703  
1704      function _nextPermutation($p, $size)
1705      {
1706          for ($i = $size - 1; isset($p[$i]) && isset($p[$i+1]) && $p[$i] >= $p[$i+1]; --$i) { }
1707          if ($i == -1) { return false; }
1708          for ($j = $size; $p[$j] <= $p[$i]; --$j) { }
1709          $tmp = $p[$i]; $p[$i] = $p[$j]; $p[$j] = $tmp;
1710          for (++$i, $j = $size; $i < $j; ++$i, --$j) {
1711              $tmp = $p[$i]; $p[$i] = $p[$j]; $p[$j] = $tmp;
1712          }
1713          return $p;
1714      }
1715  
1716      /**
1717       * Returns all the possible permutations of given array
1718       */
1719      function permute($array, $join_with = false)
1720      {
1721          $size = count($array) - 1;
1722          $perm = range(0, $size);
1723          $j = 0;
1724          do {
1725              foreach ($perm as $i) {
1726                  $perms[$j][] = $array[$i];
1727              }
1728          } while ($perm = Ak::_nextPermutation($perm, $size) AND ++$j);
1729  
1730          if($join_with){
1731              foreach ($perms as $perm){
1732                  $joined_perm[] = join(' ',$perm);
1733              }
1734              return $joined_perm;
1735          }
1736          return $perms;
1737      }
1738  
1739      /**
1740       * Generates a Universally Unique IDentifier, version 4.
1741       *
1742       * RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt) defines a special type of Globally
1743       * Unique IDentifiers (GUID), as well as several methods for producing them. One
1744       * such method, described in section 4.4, is based on truly random or pseudo-random
1745       * number generators, and is therefore implementable in a language like PHP.
1746       *
1747       * We choose to produce pseudo-random numbers with the Mersenne Twister, and to always
1748       * limit single generated numbers to 16 bits (ie. the decimal value 65535). That is
1749       * because, even on 32-bit systems, PHP's RAND_MAX will often be the maximum *signed*
1750       * value, with only the equivalent of 31 significant bits. Producing two 16-bit random
1751       * numbers to make up a 32-bit one is less efficient, but guarantees that all 32 bits
1752       * are random.
1753       *
1754       * The algorithm for version 4 UUIDs (ie. those based on random number generators)
1755       * states that all 128 bits separated into the various fields (32 bits, 16 bits, 16 bits,
1756       * 8 bits and 8 bits, 48 bits) should be random, except : (a) the version number should
1757       * be the last 4 bits in the 3rd field, and (b) bits 6 and 7 of the 4th field should
1758       * be 01. We try to conform to that definition as efficiently as possible, generating
1759       * smaller values where possible, and minimizing the number of base conversions.
1760       *
1761       * @copyright  Copyright (c) CFD Labs, 2006. This function may be used freely for
1762       *              any purpose ; it is distributed without any form of warranty whatsoever.
1763       * @author      David Holmes <dholmes@cfdsoftware.net>
1764       *
1765       * @return  string  A UUID, made up of 32 hex digits and 4 hyphens.
1766       */
1767      function uuid()
1768      {
1769  
1770          // The field names refer to RFC 4122 section 4.1.2
1771          return sprintf('%04x%04x-%04x-%03x4-%04x-%04x%04x%04x',
1772          mt_rand(0, 65535), mt_rand(0, 65535), // 32 bits for "time_low"
1773          mt_rand(0, 65535), // 16 bits for "time_mid"
1774          mt_rand(0, 4095),  // 12 bits before the 0100 of (version) 4 for "time_hi_and_version"
1775          bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)),
1776          // 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res"
1777          // (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d)
1778          // 8 bits for "clk_seq_low"
1779          mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) // 48 bits for "node"
1780          );
1781      }
1782  
1783  
1784      function test($test_case_name, $use_sessions = false)
1785      {
1786          ak_test($test_case_name, $use_sessions);
1787      }
1788  
1789      /**
1790       * Use this function for securing includes. This way you can prevent file inclusion attacks
1791       */
1792      function sanitize_include($include, $mode = 'normal')
1793      {
1794          $rules = array(
1795          'paranoid' => '/([^A-Z^a-z^0-9^_^-^ ]+)/',
1796          'high' => '/([^A-Z^a-z^0-9^_^-^ ^\/^\\\^:]+)/',
1797          'normal' => '/([^A-Z^a-z^0-9^_^-^ ^\.^\/^\\\]+)/'
1798          );
1799          $mode = array_key_exists($mode,$rules) ? $mode : 'normal';
1800          return preg_replace($rules[$mode],'',$include);
1801      }
1802  
1803      /**
1804       * Returns a PHP Object from an API resource
1805       * 
1806       */
1807      function client_api($resource, $options = array())
1808      {
1809          $default_options = array(
1810          'protocol' => 'xml_rpc',
1811          'build' => true
1812          );
1813          $options = array_merge($default_options, $options);
1814  
1815          require (AK_LIB_DIR.DS.'AkActionWebService'.DS.'AkActionWebServiceClient.php');
1816          $Client =& new AkActionWebServiceClient($options['protocol']);
1817          $Client->init($resource, $options);
1818          return $Client;
1819      }
1820  
1821  
1822      /**
1823       * Cross PHP version replacement for html_entity_decode. Emulates PHP5 behaviour on PHP4 on UTF-8 entities
1824       */
1825      function html_entity_decode($html, $translation_table_or_quote_style = null)
1826      {
1827          if(AK_PHP5){
1828              return html_entity_decode($html,empty($translation_table_or_quote_style) ? ENT_QUOTES : $translation_table_or_quote_style,'UTF-8');
1829          }
1830          require_once (AK_LIB_DIR.DS.'AkCharset.php');
1831          $html = preg_replace('~&#x([0-9a-f]+);~ei', 'AkCharset::_CharToUtf8(hexdec("\\1"))', $html);
1832          $html = preg_replace('~&#([0-9]+);~e', 'AkCharset::_CharToUtf8("\\1")', $html);
1833          if(empty($translation_table_or_quote_style)){
1834              $translation_table_or_quote_style = get_html_translation_table(HTML_ENTITIES);
1835              $translation_table_or_quote_style = array_flip($translation_table_or_quote_style);
1836          }
1837          return strtr($html, $translation_table_or_quote_style);
1838      }
1839  
1840      /**
1841      * Loads the plugins found at app/vendor/plugins
1842      */
1843      function &loadPlugins()
1844      {
1845          require_once (AK_LIB_DIR.DS.'AkPlugin.php');
1846          $PluginManager =& new AkPluginLoader();
1847          $PluginManager->loadPlugins();
1848          return $PluginManager;
1849      }
1850      
1851      function setStaticVar($name,&$value)
1852      {
1853          $refhack =& Ak::_staticVar($name,$value);
1854          return $refhack;
1855      }
1856      
1857      /**
1858      * Strategy for unifying in-function static vars used mainly for performance improvements framework-wide.
1859      *
1860      * Before we had
1861      *
1862      *     class A{
1863      *       function b($var){
1864      *         static $chache;
1865      *         if(!isset($cache[$var])){
1866      *           $cache[$var] = some_heavy_function($var);
1867      *         }
1868      *         return $cache[$var]; 
1869      *       } 
1870      *     }
1871      *
1872      * Now imagine we want to create an application server which handles multiple requests on a single instantiation, with the showcased implementation this is not possible as we can't reset $cache, unless we hack badly every single method that uses this strategy.
1873      *
1874      * We can refresh this static values the new Ak::getStaticVar method. So from previous example we will have to replace 
1875      *
1876      *     static $chache;
1877      */
1878      function &getStaticVar($name)
1879      {
1880          $refhack =& Ak::_staticVar($name,$refhackvar = null);
1881          return $refhack;
1882      }
1883      
1884      function &unsetStaticVar($name)
1885      {
1886          $refhack =& Ak::_staticVar($name,$refhackvar = null,true);
1887          return $refhack;
1888      }
1889      
1890      function &_staticVar($name, &$value, $destruct = false)
1891      {
1892          static $_memory;
1893          $null = null;
1894          $true = true;
1895          $false = false;
1896          $return = $null;
1897          if ($value === null && $destruct === false) {
1898              /**
1899               * GET mode
1900               */
1901              if (isset($_memory[$name])) {
1902                  $return = &$_memory[$name];
1903              }
1904          } else if ($value !== null) {
1905              /**
1906               * SET mode
1907               */
1908              if (is_string($name)) {
1909                  $_memory[$name] = &$value;
1910                  $return = $true;
1911              } else {
1912                  $return = $false;
1913              }
1914              
1915          } else if ($destruct === true) {
1916              if ($name !== null) {
1917                  $value = isset($_memory[$name])?$_memory[$name]:$null;
1918                  if (is_object($value) && method_exists($value,'__destruct')) {
1919                      $value->__destruct();
1920                  }
1921                  unset($value);
1922                  unset($_memory[$name]);
1923              } else {
1924                  foreach ($_memory as $name => $value) {
1925                      Ak::unsetStaticVar($name);
1926                  }
1927              }
1928          }
1929          return $return;
1930      }
1931      
1932      /**
1933       *
1934       * @param array $options
1935       * @param array $default_options
1936       * @param array $available_options
1937       * @param boolean $walk_keys
1938       */
1939      function parseOptions(&$options, $default_options = array(), $parameters = array(), $walk_keys=false)
1940      {
1941          if ($walk_keys) {
1942              foreach ($options as $key=>$value) {
1943                  if (!is_array($value)) {
1944                      unset($options[$key]);
1945                      $options[$value] = $default_options;
1946                  } else {
1947                      Ak::parseOptions($value, $default_options, $parameters);
1948                      $options[$key] = $value;
1949                  }
1950              }
1951              return;
1952          }
1953          
1954          $options = array_merge($default_options, $options);
1955          foreach($options as $key => $value) {
1956              if(isset($parameters['available_options'])) {
1957                 if (!isset($parameters['available_options'][$key])) {
1958                     continue;
1959                 }
1960              }
1961              $options[$key] = $value;
1962              
1963          }
1964      }
1965      
1966      /**
1967       * Returns YAML settings from config/$namespace.yml
1968       */
1969      function getSettings($namespace, $raise_error_if_config_file_not_found = true, $environment = AK_ENVIRONMENT)
1970      {
1971          static $_config;
1972          if (!in_array($environment,Ak::toArray(AK_AVAILABLE_ENVIRONMENTS))) {
1973              trigger_error('The environment '.$environment.' is not allowed. Allowed environments: '.AK_AVAILABLE_ENVIRONMENTS);
1974              return false;
1975          }
1976          if (!isset($_config)) {
1977              require_once (AK_LIB_DIR.DS.'AkConfig.php');
1978              $_config = new AkConfig();
1979          }
1980          return $_config->get($namespace,$environment,$raise_error_if_config_file_not_found);
1981      }
1982      
1983      function getSetting($namespace, $variable, $default_value = null)
1984      {
1985          if($settings = Ak::getSettings($namespace)){
1986              return isset($settings[$variable]) ? $settings[$variable] : $default_value;
1987           }
1988          return $default_value;
1989      }
1990      
1991      function _parseSettingsConstants($settingsStr)
1992      {
1993          return preg_replace_callback('/\$\{(AK_.*?)\}/',array('Ak','_getConstant'),$settingsStr);
1994      }
1995      
1996      function _getConstant($name)
1997      {
1998          return defined($name[1])?constant($name[1]):'';
1999      }
2000  }
2001  
2002  Ak::profile('Ak.php class included'.__FILE__);
2003  
2004  ?>