Development

Changeset 6779

You must first sign up to be able to contribute.

Changeset 6779

Show
Ignore:
Timestamp:
12/28/07 15:12:05 (10 months ago)
Author:
fabien
Message:

merged branches 1.1 changes (to r6770)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/UPGRADE

    r6623 r6779  
    8585not singletons. 
    8686 
    87 If you want to get one of those objects in your code, they are still 
     87If you want to get one of those objects in your code, they are 
    8888available from `sfContext`: 
    8989 
     
    9393  sfContext::getInstance()->getLogger() 
    9494 
    95 Here is their default configuration in `factories.yml`: 
    96  
    97   i18n: 
    98     class: sfI18N 
    99     param: 
    100       cache: 
    101         class: sfFileCache 
    102         param: 
    103           automatic_cleaning_factor: 0 
    104           cache_dir:                 %SF_I18N_CACHE_DIR% 
    105           lifetime:                  86400 
    106           prefix:                    %SF_APP_DIR% 
     95Routing 
     96~~~~~~~ 
     97 
     98Here is the default configuration for the routing in `factories.yml`: 
    10799 
    108100  routing: 
     
    110102    param: 
    111103      load_configuration: true 
     104 
     105The `project:upgrade1.1` task makes all the changes for you. 
     106 
     107Logging 
     108~~~~~~~ 
     109 
     110Here is the default configuration for logging in `factories.yml`: 
    112111 
    113112  logger: 
     
    120119          param: 
    121120            condition: %SF_WEB_DEBUG% 
     121            xdebug_logging: true 
    122122        sf_file_debug: 
    123123          class: sfFileLogger 
     
    146146 
    147147The `project:upgrade1.1` task makes all those changes for you. 
     148 
     149i18n 
     150~~~~ 
     151 
     152Here is the default configuration for i18n in `factories.yml`: 
     153 
     154  i18n: 
     155    class: sfI18N 
     156    param: 
     157      source:              XLIFF 
     158      debug:               off 
     159      untranslated_prefix: "[T]" 
     160      untranslated_suffix: "[/T]" 
     161      cache: 
     162        class: sfFileCache 
     163        param: 
     164          automatic_cleaning_factor: 0 
     165          cache_dir:                 %SF_I18N_CACHE_DIR% 
     166          lifetime:                  86400 
     167          prefix:                    %SF_APP_DIR% 
     168 
     169The `i18n.yml` configuration file is not used anymore. 
     170Instead, you can configure i18n in `factories.yml`. 
     171 
     172The only exception is the `default_culture` setting which is now configurable in `settings.yml` 
     173and do not depend on the i18n framework anymore: 
     174 
     175  default_culture: en 
     176 
     177If your project has some specific settings, you must move your current configuration from the `i18n.yml` to 
     178the `factories.yml` and add the default culture in `settings.yml` as shown above. 
    148179 
    149180Cache Framework 
     
    263294  * `->setErrors()` 
    264295  * `->removeError()` 
     296 
     297Deprecated methods in sfWebRequest 
     298---------------------------------- 
     299 
     300The following methods of `sfWebRequest` have been deprecated and throw 
     301a `sfConfigurationException` if `sf_compat_10` is set to `false`: 
     302 
     303  * `->getFile()` 
     304  * `->getFileError()` 
     305  * `->getFileName()` 
     306  * `->getFileNames()` 
     307  * `->getFilePath()` 
     308  * `->getFileSize()` 
     309  * `->getFileType()` 
     310  * `->hasFile()` 
     311  * `->hasFileError()` 
     312  * `->hasFileErrors()` 
     313  * `->hasFiles()` 
     314  * `->getFileValue()` 
     315  * `->getFileValues()` 
     316  * `->getFileExtension()` 
     317  * `->moveFile()` 
    265318 
    266319sfValidator class 
     
    327380--------------- 
    328381 
    329 The `sf_timeout` setting is not used anymore. To change the session timeout, you now have to edit the `factories.yml` instead if the `settings.yml`, and change the parameters of the `user` factory: 
     382The `sf_timeout` setting is not used anymore. To change the session timeout, you now have to edit the 
     383`factories.yml` instead if the `settings.yml`, and change the parameters of the `user` factory: 
    330384 
    331385    all: 
  • trunk/data/config/factories.yml

    r6497 r6779  
    1111  user: 
    1212    class: myUser 
     13    param: 
     14      timeout:  1800 
    1315 
    1416  storage: 
     
    2830    class: sfI18N 
    2931    param: 
    30       load_configuration: true 
     32      source:               XLIFF 
     33      debug:                off 
     34      untranslated_prefix:  "[T]" 
     35      untranslated_suffix:  "[/T]" 
    3136      cache: 
    3237        class: sfFileCache 
  • trunk/data/config/i18n.yml

    r4579 r6779  
    1 default: 
    2   default_culture:     en 
    3   source:              XLIFF 
    4   debug:               off 
    5   untranslated_prefix: "[T]" 
    6   untranslated_suffix: "[/T]" 
  • trunk/data/config/settings.yml

    r5144 r6779  
    6666    # Miscellaneous 
    6767    strip_comments:         on         # Remove comments in core framework classes as defined in the core_compile.yml 
    68     timeout:                1800       # Session timeout, in seconds 
    6968    max_forwards:           5 
    7069    path_info_array:        SERVER 
     
    7877    logging_enabled:        on 
    7978 
     79    # i18n 
     80    default_culture:        en        # default culture for a user 
     81 
    8082    # enable 1.0 compatibility 
    8183    compat_10:              off 
  • trunk/data/skeleton/app/app/config/factories.yml

    r6365 r6779  
    4949#    class: sfI18N 
    5050#    param: 
     51#      source:              XLIFF 
     52#      debug:               off 
     53#      untranslated_prefix: "[T]" 
     54#      untranslated_suffix: "[/T]" 
    5155#      cache: 
    5256#        class: sfFileCache 
  • trunk/data/skeleton/app/app/config/i18n.yml

    r4579 r6779  
    1 #all: 
    2 #  default_culture:     en 
    3 #  source:              XLIFF 
    4 #  debug:               off 
    5 #  untranslated_prefix: "[T]" 
    6 #  untranslated_suffix: "[/T]" 
  • trunk/data/skeleton/app/app/config/settings.yml

    r6128 r6779  
    8787#    # Miscellaneous 
    8888#    strip_comments:         on         # Remove comments in core framework classes as defined in the core_compile.yml 
    89 #    timeout:                1800       # Session timeout, in seconds 
    9089#    max_forwards:           5 
    9190#    path_info_array:        SERVER 
  • trunk/data/skeleton/module/module/actions/components.class.php

    r6221 r6779  
    1 <?php 
    2  
    3 /** 
    4  * ##MODULE_NAME## components. 
    5  * 
    6  * @package    ##PROJECT_NAME## 
    7  * @subpackage ##MODULE_NAME## 
    8  * @author     ##AUTHOR_NAME## 
    9  * @version    SVN: $Id: components.class.php 2823 2006-11-26 08:26:18Z dwhittle $ 
    10  */ 
    11 class ##MODULE_NAME##Components extends sfComponents 
    12 { 
    13  
    14 } 
  • trunk/lib/action/sfAction.class.php

    r6522 r6779  
    55 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com> 
    66 * (c) 2004-2006 Sean Kerr. 
    7  *  
     7 * 
    88 * For the full copyright and license information, please view the LICENSE 
    99 * file that was distributed with this source code. 
     
    3636 
    3737    // include security configuration 
    38     require(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$this->getModuleName().'/'.sfConfig::get('sf_app_module_config_dir_name').'/security.yml', true)); 
     38    if($file = sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$this->getModuleName().'/'.sfConfig::get('sf_app_module_config_dir_name').'/security.yml', true)) 
     39    { 
     40      require($file); 
     41    } 
    3942  } 
    4043 
     
    256259   * and bypasses the built-in view system. 
    257260   * 
     261   * If the vars parameter is omitted, the action's internal variables 
     262   * will be passed, just as it would to a normal template. 
     263   * 
     264   * If the vars parameter is set then only those values are 
     265   * available in the partial. 
     266   * 
    258267   * This method must be called as with a return: 
    259268   * 
     
    261270   * 
    262271   * @param  string partial name 
     272   * @param  array vars 
    263273   * 
    264274   * @return sfView::NONE 
    265275   */ 
    266   public function renderPartial($templateName
     276  public function renderPartial($templateName, $vars = null
    267277  { 
    268278    sfLoader::loadHelpers('Partial'); 
    269279 
    270     return $this->renderText(get_partial($templateName, $this->varHolder->getAll())); 
     280    $vars = $vars ? $vars : $this->varHolder->getAll(); 
     281 
     282    return $this->renderText(get_partial($templateName, $vars)); 
    271283  } 
    272284 
     
    332344           | sfRequest::PUT 
    333345           | sfRequest::DELETE 
    334            | sfRequest::HEAD  
     346           | sfRequest::HEAD 
    335347           | sfRequest::NONE; 
    336348  } 
  • trunk/lib/addon/sfPager.class.php

    r5016 r6779  
    9494  public function haveToPaginate() 
    9595  { 
    96     return (($this->getPage() != 0) && ($this->getNbResults() > $this->getMaxPerPage())); 
     96    return (($this->getMaxPerPage() != 0) && ($this->getNbResults() > $this->getMaxPerPage())); 
    9797  } 
    9898 
  • trunk/lib/config/sfDatabaseConfigHandler.class.php

    r4597 r6779  
    101101 
    102102      // append new data 
    103       $data[] = sprintf("\n\$database = new %s();\n". 
    104                         "\$database->initialize(%s, '%s');\n". 
     103      $data[] = sprintf("\n\$database = new %s(%s, '%s');\n". 
    105104                        "\$this->databases['%s'] = \$database;", 
    106105                        $dbConfig['class'], $parameters, $key, $key); 
  • trunk/lib/config/sfFactoryConfigHandler.class.php

    r6524 r6779  
    106106 
    107107        case 'response': 
     108          $parameters = array_merge(array('charset' => sfConfig::get('sf_charset'), 'logging' => sfConfig::get('sf_logging_enabled')), is_array($parameters) ? $parameters : array()); 
    108109          $instances[] = sprintf("  \$class = sfConfig::get('sf_factory_response', '%s');\n  \$this->factories['response'] = new \$class(\$this->dispatcher, sfConfig::get('sf_factory_response_parameters', %s));", $class, var_export($parameters, true)); 
    109110 
     
    124125 
    125126        case 'user': 
    126           $instances[] = sprintf("  \$class = sfConfig::get('sf_factory_user', '%s');\n  \$this->factories['user'] = new \$class(\$this->dispatcher, \$this->factories['storage'], array_merge(array('auto_shutdown' => false, 'culture' => \$this->factories['request']->getParameter('sf_culture'), 'default_culture' => sfConfig::get('sf_i18n_default_culture'), 'use_flash' => sfConfig::get('sf_use_flash')), sfConfig::get('sf_factory_user_parameters', %s)));", $class, var_export(is_array($parameters) ? $parameters : array(), true)); 
     127          $instances[] = sprintf("  \$class = sfConfig::get('sf_factory_user', '%s');\n  \$this->factories['user'] = new \$class(\$this->dispatcher, \$this->factories['storage'], array_merge(array('auto_shutdown' => false, 'culture' => \$this->factories['request']->getParameter('sf_culture'), 'default_culture' => sfConfig::get('sf_default_culture', 'en'), 'use_flash' => sfConfig::get('sf_use_flash'), 'logging' => sfConfig::get('sf_logging_enabled')), sfConfig::get('sf_factory_user_parameters', %s)));", $class, var_export(is_array($parameters) ? $parameters : array(), true)); 
    127128          break; 
    128129 
     
    151152          } 
    152153 
    153           $configuration = ''; 
    154           if (isset($parameters['load_configuration']) && $parameters['load_configuration']) 
    155           { 
    156             $configuration = "  \$this->factories['i18n']->loadConfiguration();\n"; 
    157           } 
    158154          $instances[] = sprintf("\n  if (sfConfig::get('sf_i18n'))\n  {\n". 
    159155                     "    \$class = sfConfig::get('sf_factory_i18n', '%s');\n". 
    160156                     "%s". 
    161                      "    \$this->factories['i18n'] = new \$class(\$this, \$cache);\n". 
    162                      $configuration. 
     157                     "    \$this->factories['i18n'] = new \$class(\$this->dispatcher, \$cache, %s);\n". 
    163158                     "  }\n" 
    164                      , $class, $cache 
     159                     , $class, $cache, var_export($parameters, true) 
    165160                     ); 
    166161          break; 
    167162 
    168163        case 'routing': 
    169           $instances[] = sprintf("  \$class = sfConfig::get('sf_factory_routing', '%s');\n  \$this->factories['routing'] = new \$class(\$this->dispatcher, array_merge(array('auto_shutdown' => false, 'suffix' => sfConfig::get('sf_suffix'), 'default_module' => sfConfig::get('sf_default_module'), 'default_action' => sfConfig::get('sf_default_action')), sfConfig::get('sf_factory_routing_parameters', %s)));", $class, var_export(is_array($parameters) ? $parameters : array(), true)); 
     164          $instances[] = sprintf("  \$class = sfConfig::get('sf_factory_routing', '%s');\n  \$this->factories['routing'] = new \$class(\$this->dispatcher, array_merge(array('auto_shutdown' => false, 'suffix' => sfConfig::get('sf_suffix'), 'default_module' => sfConfig::get('sf_default_module'), 'default_action' => sfConfig::get('sf_default_action'), 'logging' => sfConfig::get('sf_logging_enabled')), sfConfig::get('sf_factory_routing_parameters', %s)));", $class, var_export(is_array($parameters) ? $parameters : array(), true)); 
    170165          if (isset($parameters['load_configuration']) && $parameters['load_configuration']) 
    171166          { 
  • trunk/lib/config/sfLoader.class.php

    r6509 r6779  
    134134   * Gets the i18n directories to use globally. 
    135135   * 
    136    * Returns null if the current i18n source is not a file based i18n backend (XLIFF or gettext). 
    137    * 
    138136   * @return array An array of i18n directories 
    139137   */ 
    140138  static public function getI18NGlobalDirs() 
    141139  { 
    142     if (!in_array(sfConfig::get('sf_i18n_source'), array('XLIFF', 'gettext'))) 
    143     { 
    144       return null; 
    145     } 
    146  
    147140    $dirs = array(); 
    148141 
     
    166159   * Gets the i18n directories to use for a given module. 
    167160   * 
    168    * Returns null if the current i18n source is not a file based i18n backend (XLIFF or gettext). 
    169    * 
    170161   * @param string The module name 
    171162   * 
     
    174165  static public function getI18NDirs($moduleName) 
    175166  { 
    176     if (!in_array(sfConfig::get('sf_i18n_source'), array('XLIFF', 'gettext'))) 
    177     { 
    178       return null; 
    179     } 
    180  
    181167    $dirs = array(); 
    182168 
  • trunk/lib/config/sfPhpConfigHandler.class.php

    r4938 r6779  
    102102        } 
    103103 
    104         $warning = sprintf('{sfPhpConfigHandler} php.ini "%s" key is better set to "%s" (current value is "%s" - %s)', $key, var_export($value, true), var_export(ini_get($key), true), $this->get_ini_path()); 
     104//        $warning = sprintf('{sfPhpConfigHandler} php.ini "%s" key is better set to "%s" (current value is "%s" - %s)', $key, var_export($value, true), var_export(ini_get($key), true), $this->get_ini_path()); 
    105105// FIXME: sfContext is not yet initialized, so the logger is a sfNoLogger instance. 
    106106//        $data[] = sprintf("if (ini_get('%s') != %s)\n{\n  sfContext::getInstance()->getLogger()->warning('%s');\n}\n", $key, var_export($value, true), str_replace("'", "\\'", $warning)); 
  • trunk/lib/controller/sfController.class.php

    r6499 r6779  
    165165      } 
    166166 
    167       throw new sfControllerException(sprintf('{sfController} controller "%s/%s" does not exist in: %s.', $moduleName, $controllerName, implode(', ', $dirs))); 
     167      throw new sfControllerException(sprintf('Controller "%s/%s" does not exist in: %s.', $moduleName, $controllerName, implode(', ', $dirs))); 
    168168    } 
    169169 
     
    202202      if (sfConfig::get('sf_logging_enabled')) 
    203203      { 
    204         $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Action does not exist'))); 
     204        $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Action "%s/%s" does not exist', $moduleName, $actionName)))); 
    205205      } 
    206206 
     
    251251      $this->context->getEventDispatcher()->notify(new sfEvent($this, 'controller.change_action', array('module' => $moduleName, 'action' => $actionName))); 
    252252 
     253      if ($moduleName == sfConfig::get('sf_error_404_module') && $actionName == sfConfig::get('sf_error_404_action')) 
     254      { 
     255        $this->context->getResponse()->setStatusCode(404); 
     256        $this->context->getResponse()->setHttpHeader('Status', '404 Not Found'); 
     257 
     258        $this->dispatcher->notify(new sfEvent($this, 'controller.page_not_found', array('module' => $moduleName, 'action' => $actionName))); 
     259      } 
     260 
    253261      // process the filter chain 
    254262      $filterChain->execute(); 
     
    403411    if (sfConfig::get('sf_logging_enabled')) 
    404412    { 
    405       $this->dispatcher->notify(new sfEvent($this, 'application.log', array('sendEmail method is deprecated', 'priority' => 'err'))); 
     413      $this->dispatcher->notify(new sfEvent($this, 'application.log', array('sendEmail method is deprecated', 'priority' => sfLogger::ERR))); 
    406414    } 
    407415 
     
    464472      if ($actionEntry->getModuleName() == sfConfig::get('sf_login_module') && $actionEntry->getActionName() == sfConfig::get('sf_login_action')) 
    465473      { 
    466         throw new sfException('Your mail action is secured but the user is not authenticated.'); 
     474        throw new sfException('Your action is secured but the user is not authenticated.'); 
    467475      } 
    468476      else if ($actionEntry->getModuleName() == sfConfig::get('sf_secure_module') && $actionEntry->getActionName() == sfConfig::get('sf_secure_action')) 
    469477      { 
    470         throw new sfException('Your mail action is secured but the user does not have access.'); 
     478        throw new sfException('Your action is secured but the user does not have access.'); 
    471479      } 
    472480    } 
  • trunk/lib/database/sfDatabaseManager.class.php

    r6497 r6779  
    8282 
    8383  /** 
     84   * Returns the names of all database connections. 
     85   * 
     86   * @return array An array containing all database connection names 
     87   */ 
     88  public function getNames() 
     89  { 
     90    return array_keys($this->databases); 
     91  } 
     92 
     93  /** 
    8494   * Executes the shutdown procedure 
    8595   * 
  • trunk/lib/form/sfForm.class.php

    r6590 r6779  
    3636    $isBound         = false, 
    3737    $taintedValues   = array(), 
     38    $taintedFiles    = array(), 
    3839    $values          = null, 
    3940    $defaults        = array(), 
     
    111112   * 
    112113   * @param array An array of input values 
    113    */ 
    114   public function bind($taintedValues) 
     114   * @param array An array of uploaded files (in the $_FILES or $_GET format) 
     115   */ 
     116  public function bind($taintedValues, $taintedFiles = array()) 
    115117  { 
    116118    $this->taintedValues = $taintedValues; 
     119    $this->taintedFiles  = $taintedFiles; 
    117120    $this->isBound = true; 
    118121    $this->resetFormFields(); 
     
    120123    try 
    121124    { 
    122       $this->values = $this->validatorSchema->clean($this->taintedValues); 
     125      $this->values = $this->validatorSchema->clean(array_merge($this->taintedValues, self::convertFileInformation($this->taintedFiles))); 
    123126      $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema); 
    124127 
     
    170173  { 
    171174    return $this->isBound ? $this->values : array(); 
     175  } 
     176 
     177  /** 
     178   * Returns a cleaned value by field name. 
     179   * 
     180   * If the form is not bound, it will return null. 
     181   * 
     182   * @param  string  The name of the value required 
     183   * @return string  The cleaned value 
     184   */ 
     185  public function getValue($field) 
     186  { 
     187    return ($this->isBound && isset($this->values[$field])) ? $this->values[$field] : null; 
    172188  } 
    173189 
     
    604620    } 
    605621  } 
     622 
     623  /** 
     624   * Converts uploaded file array to a format following the $_GET and $POST naming convention. 
     625   * 
     626   * It's safe to pass an already converted array, in which case this method just returns the original array unmodified. 
     627   * 
     628   * @param  array An array representing uploaded file information 
     629   * 
     630   * @return array An array of re-ordered uploaded file information 
     631   */ 
     632  static public function convertFileInformation($taintedFiles) 
     633  { 
     634    return self::pathsToArray(preg_replace('#^(/[^/]+)?(/name|/type|/tmp_name|/error|/size)([^\s]*)( = [^\n]*)#m', '$1$3$2$4', self::arrayToPaths($taintedFiles))); 
     635  } 
     636 
     637  /** 
     638   * Converts a string of paths separated by newlines into an array. 
     639   * 
     640   * Code adapted from http://www.shauninman.com/archive/2006/11/30/fixing_the_files_superglobal 
     641   * @author Shaun Inman (www.shauninman.com) 
     642   * 
     643   * @param  string A string representing an array 
     644   * 
     645   * @return Array  An array 
     646   */ 
     647  static public function pathsToArray($str) 
     648  { 
     649    $array = array(); 
     650    $lines = explode("\n", trim($str)); 
     651 
     652    if (!empty($lines[0])) 
     653    { 
     654      foreach ($lines as $line) 
     655      { 
     656        list($path, $value) = explode(' = ', $line); 
     657 
     658        $steps = explode('/', $path); 
     659        array_shift($steps); 
     660 
     661        $insertion =& $array; 
     662 
     663        foreach ($steps as $step) 
     664        { 
     665          if (!isset($insertion[$step])) 
     666          { 
     667            $insertion[$step] = array(); 
     668          } 
     669          $insertion =& $insertion[$step]; 
     670        } 
     671        $insertion = ctype_digit($value) ? (int) $value : $value; 
     672      } 
     673    } 
     674 
     675    return $array; 
     676  } 
     677 
     678  /** 
     679   * Converts an array into a string containing the path to each of its values separated by a newline. 
     680   * 
     681   * Code adapted from http://www.shauninman.com/archive/2006/11/30/fixing_the_files_superglobal 
     682   * @author Shaun Inman (www.shauninman.com) 
     683   * 
     684   * @param  Array  An array 
     685   * 
     686   * @return string A string representing the array 
     687   */ 
     688  static public function arrayToPaths($array = array(), $prefix = '') 
     689  { 
     690    $str = ''; 
     691    $freshPrefix = $prefix; 
     692 
     693    foreach ($array as $key => $value) 
     694    { 
     695      $freshPrefix .= "/{$key}"; 
     696 
     697      if (is_array($value)) 
     698      { 
     699        $str .= self::arrayToPaths($value, $freshPrefix); 
     700        $freshPrefix = $prefix; 
     701      } 
     702      else 
     703      { 
     704        $str .= "{$prefix}/{$key} = {$value}\n"; 
     705      } 
     706    } 
     707 
     708    return $str; 
     709  } 
    606710} 
  • trunk/lib/i18n/sfI18N.class.php

    r6497 r6779  
    2020{ 
    2121  protected 
    22     $context       = null, 
     22    $dispatcher    = null, 
    2323    $cache         = null, 
    24     $culture       = null, 
     24    $options       = array(), 
     25    $culture       = 'en', 
    2526    $messageSource = null, 
    2627    $messageFormat = null; 
     
    3132   * @see initialize() 
    3233   */ 
    33   public function __construct($context, sfCache $cache = null
    34   { 
    35     $this->initialize($context, $cache); 
     34  public function __construct(sfEventDispatcher $dispatcher, sfCache $cache = null, $options = array()
     35  { 
     36    $this->initialize($dispatcher, $cache, $options); 
    3637  } 
    3738 
     
    3940   * Initializes this class. 
    4041   * 
    41    * @param sfContext A sfContext implementation instance 
    42    */ 
    43   public function initialize($context, sfCache $cache = null) 
    44   { 
    45     $this->context = $context; 
    46     $this->cache   = $cache; 
    47  
    48     $context->getEventDispatcher()->connect('user.change_culture', array($this, 'listenToChangeCultureEvent')); 
    49     $context->getEventDispatcher()->connect('controller.change_action', array($this, 'listenToChangeActionEvent')); 
    50   } 
    51  
    52   /** 
    53    * Loads i18n configuration. 
    54    */ 
    55   public function loadConfiguration() 
    56   { 
    57     include(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_config_dir_name').'/i18n.yml')); 
     42   * @param sfEventDispatcher A sfEventDispatcher implementation instance 
     43   * @param sfCache           A sfCache instance 
     44   * @param array             An array of options 
     45   */ 
     46  public function initialize(sfEventDispatcher $dispatcher, sfCache $cache = null, $options = array()) 
     47  { 
     48    $this->dispatcher = $dispatcher; 
     49    $this->cache      = $cache; 
     50 
     51    if (isset($options['culture'])) 
     52    { 
     53      $this->culture = $options['culture']; 
     54      unset($options['culture']); 
     55    } 
     56 
     57    $this->options = array_merge(array( 
     58      'source'              => 'XLIFF', 
     59      'debug'               => false, 
     60      'database'            => 'default', 
     61      'untranslated_prefix' => '[T]', 
     62      'untranslated_suffix' => '[/T]', 
     63    ), $options); 
     64 
     65    $dispatcher->connect('user.change_culture', array($this, 'listenToChangeCultureEvent')); 
     66    $dispatcher->connect('controller.change_action', array($this, 'listenToChangeActionEvent')); 
    5867  } 
    5968 
     
    6170   * Sets the message source. 
    6271   * 
    63    * @param mixed  An array of i18n directories if message source is XLIFF or gettext, null otherwise 
     72   * @param mixed  An array of i18n directories if message source is a sfMessageSource_File subclass, null otherwise 
    6473   * @param string The culture 
    6574   */ 
     
    101110  public function createMessageSource($dir = null) 
    102111  { 
    103     if (in_array(sfConfig::get('sf_i18n_source'), array('Creole', 'MySQL', 'SQLite'))) 
    104     { 
    105       return sfMessageSource::factory(sfConfig::get('sf_i18n_source'), sfConfig::get('sf_i18n_database', 'default')); 
    106     } 
    107     else 
    108     { 
    109       return sfMessageSource::factory(sfConfig::get('sf_i18n_source'), $dir); 
    110     } 
     112    return sfMessageSource::factory($this->options['source'], self::isMessageSourceFileBased($this->options['source']) ? $dir : $this->options['database']); 
     113  } 
     114 
     115  /** 
     116   * Gets the current culture for i18n format objects. 
     117   * 
     118   * @return string The culture 
     119   */ 
     120  public function getCulture() 
     121  { 
     122    return $this->culture; 
    111123  } 
    112124 
     
    123135    { 
    124136      $this->messageSource->setCulture($culture); 
     137      $this->messageFormat = null; 
    125138    } 
    126139  } 
     
    135148    if (!isset($this->messageSource)) 
    136149    { 
    137       $this->setMessageSource(sfLoader::getI18NGlobalDirs(), $this->context->getUser()->getCulture()); 
     150      $this->setMessageSource(sfLoader::getI18NGlobalDirs(), $this->culture); 
    138151    } 
    139152 
     
    152165      $this->messageFormat = new sfMessageFormat($this->getMessageSource(), sfConfig::get('sf_charset')); 
    153166 
    154       if (sfConfig::get('sf_debug') && sfConfig::get('sf_i18n_debug')
     167      if ($this->options['debug']
    155168      { 
    156         $this->messageFormat->setUntranslatedPS(array(sfConfig::get('sf_i18n_untranslated_prefix'), sfConfig::get('sf_i18n_untranslated_suffix'))); 
     169        $this->messageFormat->setUntranslatedPS(array($this->options['untranslated_prefix'], $this->options['untranslated_suffix'])); 
    157170      } 
    158171    } 
     
    179192   * 
    180193   * @param  string The ISO code 
    181    * @param  string The culture 
     194   * @param  string The culture for the translation 
    182195   * 
    183196   * @return string The country name 
    184197   */ 
    185   public function getCountry($iso, $culture
    186   { 
    187     $c = new sfCultureInfo($culture); 
     198  public function getCountry($iso, $culture = null
     199  { 
     200    $c = new sfCultureInfo(is_null($culture) ? $this->culture : $culture); 
    188201    $countries = $c->getCountries(); 
    189202 
     
    213226   * @return integer The timestamp 
    214227   */ 
    215   public function getTimestampForCulture($date, $culture
    216   { 
    217     list($d, $m, $y) = $this->getDateForCulture($date, $culture); 
    218  
    219     return mktime(0, 0, 0, $m, $d, $y); 
     228  public function getTimestampForCulture($date, $culture = null
     229  { 
     230    list($d, $m, $y) = $this->getDateForCulture($date, is_null($culture) ? $this->culture : $culture); 
     231 
     232    return is_null($d) ? null : mktime(0, 0, 0, $m, $d, $y); 
    220233  } 
    221234 
     
    228241   * @return array   An array with the day, month and year 
    229242   */ 
    230   public function getDateForCulture($date, $culture) 
    231   { 
    232     if (!$date) return 0; 
    233  
    234     $dateFormatInfo = @sfDateTimeFormatInfo::getInstance($culture); 
     243  public function getDateForCulture($date, $culture = null) 
     244  { 
     245    if (!$date) 
     246    { 
     247      return null; 
     248    } 
     249 
     250    $dateFormatInfo = @sfDateTimeFormatInfo::getInstance(is_null($culture) ? $this->culture : $culture); 
    235251    $dateFormat = $dateFormatInfo->getShortDatePattern(); 
    236252 
     
    264280 
    265281  /** 
     282   * Returns true if messages are stored in a file. 
     283   * 
     284   * @param  string  The source name 
     285   * 
     286   * @return Boolean true if messages are stored in a file, false otherwise 
     287   */ 
     288  static public function isMessageSourceFileBased($source)