function smarty_function_calendar($params, &$smarty)
{
    static $_init = false;
    extract($params);
    //check the initialisation
    if (!$_init) {
        //path of the library
        CopixHTMLHeader::addCSSLink(CopixUrl::get() . "js/dynCal/dynCalendar.css", array('media' => 'screen'));
        CopixHTMLHeader::addJSLink(CopixUrl::get() . "js/dynCal/browserSniffer.js");
        CopixHTMLHeader::addJSLink(CopixUrl::get() . "js/dynCal/dynCalendar.js");
        if (empty($lang)) {
            $lang = CopixI18N::getLang();
        }
        CopixHTMLHeader::addJSLink(CopixUrl::get() . "js/dynCal/lang/" . $lang . ".js");
        $_init = true;
    }
    //Calculating the jsCode (kind of silly trick to use a separator as a part of jsCode, but still quick)
    $jsCode = str_replace(array('d', 'm', 'Y'), array('day', 'month', 'year'), CopixI18N::getDateFormat(" + '/' + "));
    CopixHTMLHeader::addJSCode("\n\r" . '
                        function calendarCallback' . $name . '(day, month, year) {
            var tmp;
            if (String(month).length == 1) {
               month = \'0\' + month;
            }
            if (String(day).length == 1) {
               day = \'0\' + day;
            }
            tmp = document.getElementById (\'' . $name . '\');
                                   tmp.value = ' . $jsCode . ';
                        }
    ' . "\n\r");
    //name of the textarea.
    if (empty($name)) {
        $smarty->trigger_error('[smarty_calendar] missing name parameter');
    } else {
        $out = '<input type="text" class="calendar" id="' . $name . '" name="' . $name . '" value="' . $value . '">' . "\n\r";
        $out .= '<script language="javascript" type="text/javascript">' . "\n\r";
        $out .= '<!--' . "\n\r";
        $out .= 'calendar_' . $name . ' = new dynCalendar(\'calendar_' . $name . '\', \'calendarCallback' . $name . '\', \'' . CopixUrl::get() . 'js/dynCal/images/\');' . "\n\r";
        $out .= '//-->' . "\n\r";
        $out .= '</script>' . "\n\r";
    }
    return $out;
}
 /**
  * Construction du code HTML
  * On utilise également les modifications d'en tête HTML
  */
 public function process($pParams, $pContent = null)
 {
     extract($pParams);
     if (empty($name)) {
         throw new CopixTemplateTagException('[calendar] missing name parameter');
     }
     if (empty($image)) {
         $image = '"' . _resource("img/tools/calendar.png") . '"';
     } else {
         $image = '"' . $image . '"';
     }
     if (empty($extra)) {
         $extra = '';
     }
     if (empty($size)) {
         $size = 8;
     }
     if (!isset($mask)) {
         $mask = true;
     }
     _tag('mootools', array('plugin' => array('datepicker')));
     if ($mask) {
         _tag('mootools', array('plugin' => array('imask')));
         CopixHTMLHeader::addJsCode("\n             window.addEvent('domready', function () {\n                    new iMask({\n                         onFocus: function(obj) {\n                         },\n\n                         onBlur: function(obj) {\n                         },\n\n                         onValid: function(event, obj) {\n                         },\n\n                         onInvalid: function(event, obj) {\n                             if(!event.shift) {\n                             }\n                         }\n                     });\n             });\n             ", 'calendarmask');
     }
     if (empty($lang)) {
         $lang = CopixI18N::getLang();
     }
     if (empty($format)) {
         $format = str_replace(array('d', 'm', 'Y'), array('dd', 'mm', 'yyyy'), CopixI18N::getDateFormat('/'));
     } else {
         $format = strtolower($format);
     }
     $maskFormat = str_replace(array('d', 'm', 'y'), array('9', '9', '9'), $format);
     if (!empty($yyyymmdd)) {
         $value = date(str_replace(array('dd', 'mm', 'yyyy'), array('d', 'm', 'Y'), $format), CopixDateTime::yyyymmddToTimestamp($yyyymmdd));
     }
     if (!empty($timestamp)) {
         $value = date(str_replace(array('dd', 'mm', 'yyyy'), array('d', 'm', 'Y'), $format), $timestamp);
     }
     if (empty($sizeday)) {
         $sizeday = 3;
     }
     if (!isset($beforeyear)) {
         $beforeyear = 10;
     }
     if (!isset($afteryear)) {
         $afteryear = 10;
     }
     if (!isset($duration)) {
         $duration = 500;
     }
     if (!isset($closebuttonsrc)) {
         $closebuttonsrc = null;
     } else {
         $closebuttonsrc = _resource($closebuttonsrc);
     }
     if (!isset($draggable)) {
         $draggable = true;
     }
     $draggable = $draggable ? 'true' : 'false';
     if (!isset($title)) {
         $title = null;
     }
     if (empty($value)) {
         if ($mask) {
             $value = str_replace('9', '_', $maskFormat);
         } else {
             $value = null;
         }
     }
     $strMask = '';
     if ($mask) {
         $strMask = 'style="text-align:center" class="iMask" alt="{  type:\'fixed\', mask:\'' . $maskFormat . '\', stripMask: false }"';
     }
     $out = '<input type="text" id="' . $name . '" name="' . $name . '" value="' . _copix_utf8_htmlentities($value) . '" ' . $extra . ' size="' . $size . '" ';
     //name of the input.
     if (!empty($tabindex)) {
         $out .= ' tabindex="' . $tabindex . '" ';
     }
     $out .= $strMask . ' />' . "\n\r";
     $out .= '<script type="text/javascript">' . "\n\r";
     $out .= "\$('" . $name . "').makeDatePicker({draggable:{$draggable}, title: '" . str_replace("'", "\\'", $title) . "', closebuttonsrc: '" . $closebuttonsrc . "', value: '" . $value . "', format: '" . $format . "', language: '" . $lang . "', sizeday:" . $sizeday . ", beforeyear:" . $beforeyear . ", afteryear:" . $afteryear . ", duration:" . $duration . ", imageCalendar:" . $image;
     //class du calendrier.
     if (!empty($classe)) {
         $out .= ', classe:"' . $classe . '"';
     }
     $out .= "});" . "\n\r";
     return $out .= '</script>';
 }
 /**
  * Transform a timestamp into a given date format, according to the current language.
  * @param string timestamp. If timestamp is false,
  *
  * @return string the date. null if no timestamp is given. False is the timestamp is incorrect
  */
 function timestampToDate($timestamp, $separator = '/')
 {
     //check if a timestamp was given
     if ($timestamp !== false && ($timestamp === null || strlen($timestamp = trim($timestamp)) === 0)) {
         return null;
     }
     if (strlen($timestamp) !== 8 || !checkdate(substr($timestamp, 4, 2), substr($timestamp, 6, 2), substr($timestamp, 0, 4)) || ($timestamp = strtotime($timestamp)) === -1) {
         return false;
     }
     return date(CopixI18N::getDateFormat($separator), $timestamp);
 }
 /**
  * Transformation d'une date en timestamp
  * @param date $date Une date
  * @param string $separator Separateur
  * @return int Un timestamp
  */
 public static function dateToTimestamp($pParam, $separator = '/')
 {
     /*
             VERSION COPIX 3
             if (($pParam !== false) && (($pParam === null) || (strlen ($pParam = trim ($pParam)) === 0))){
                 return null;
             }
             if (($yyyymmdd = self::dateToYYYYMMDD ($pParam, $separator)) === false){
                 return false;
             }
             return self::yyyymmddToTimestamp ($yyyymmdd);
     */
     /* VERSION COPIX 2 */
     $date = $pParam;
     if ($date === null || strlen($date = trim($date)) === 0) {
         return null;
     }
     //is the date have exactly 3 parts (day, month, year)
     if (count($tmp = explode($separator, $date)) !== 3) {
         return false;
     }
     foreach ($tmp as $key => $value) {
         $tmp[$key] = intval($value);
     }
     //gets the format & pos of each elements
     $format = CopixI18N::getDateFormat($separator);
     //Very very weird thing to get the date in our requested format.
     //array of positions for day, month and year (D, M, Y) in the tab
     //we wants to order positions to get 0, 1, 2
     $positions = array('d' => strpos($format, 'd'), 'm' => strpos($format, 'm'), 'Y' => strpos($format, 'Y'));
     //we know the first match will be 0 (at least we start with d m or Y)
     switch (array_search(0, $positions)) {
         case 'd':
             if ($positions['m'] > $positions['Y']) {
                 $positions['m'] = 2;
                 $positions['Y'] = 1;
             } else {
                 $positions['m'] = 1;
                 $positions['Y'] = 2;
             }
             break;
         case 'm':
             if ($positions['d'] > $positions['Y']) {
                 $positions['d'] = 2;
                 $positions['Y'] = 1;
             } else {
                 $positions['d'] = 1;
                 $positions['Y'] = 2;
             }
             break;
         case 'Y':
             if ($positions['d'] > $positions['m']) {
                 $positions['d'] = 2;
                 $positions['m'] = 1;
             } else {
                 $positions['d'] = 1;
                 $positions['m'] = 2;
             }
             break;
     }
     if (!checkdate($tmp[$positions['m']], $tmp[$positions['d']], $tmp[$positions['Y']])) {
         return false;
     }
     //the timestamp (YYYMMDD)
     return $tmp[$positions['Y']] . sprintf("%02d", $tmp[$positions['m']]) . sprintf("%02d", $tmp[$positions['d']]);
 }
 public function testComplexTypeValidator()
 {
     $personneValidate = _ctValidator()->attachTo(_validator('preg', '/[a-zA-Z]+$/'), array('nom', 'prenom'))->attachTo(_validator('date', array('max' => date(CopixI18N::getDateFormat()))), 'datenaissance');
     $personne = array('nom' => 'Nom', 'prenom' => 'prenom', 'datenaissance' => '01/01/1978');
     $this->assertTrue($personneValidate->check($personne));
     $personne = array('nom' => 'Nom3', 'prenom' => 'prenom1', 'datenaissance' => '01/01/9978');
     $this->assertTrue($personneValidate->check($personne) !== true);
     $this->assertTrue(count($personneValidate->check($personne)->asArray()) === 3);
 }