b6a7e5c10277c243fc5825f9256c9217c753b2dc
[tine20] / tine20 / build.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <!-- ============================================  -->
4 <!-- Build Definition for Tine 2.0                 -->
5 <!--                                               -->
6 <!-- http://www.tine20.org                         -->
7 <!-- http://www.phing.info                         -->
8 <!-- ============================================  -->
9 <project name="tine20" description="Tine 2.0 build file" default="build">
10     
11     <property name="builddir" value="${project.basedir}/build" override="true" />
12     <property name="localedir" value="Tinebase/js/Locale" override="true" />
13     
14     <!-- ============================================  -->
15     <!-- Target: prepare                               -->
16     <!-- ============================================  -->
17     <target name="prepare">
18         <echo msg="$buildDate: ${project.basedir}" />
19         <init />
20         
21         <php expression="getDevelopmentRevision();" returnProperty="buildRevision" />
22         <echo msg="$buildRevision: ${buildRevision}" />
23         
24         <php expression="date_create('now')->format('Y-m-d H:i:s');" returnProperty="buildDate" />
25         <echo msg="$buildDate: ${buildDate}" />
26         
27         <echo msg="Making build directory" />
28         <mkdir dir="${builddir}" />
29         <mkdir dir="${builddir}/${localedir}/build" />
30         <mkdir dir="${builddir}/${localedir}/static" />
31     </target>
32     
33     <!-- ============================================  -->
34     <!-- Target: build                                 -->
35     <!-- ============================================  -->
36     <target name="build" depends="prepare">
37         <foreach param="name" absparam="path" target="build-module">
38             <fileset dir=".">
39                 <type type="dir" />
40                 <include name="*" />
41                 <exclude name="/" />
42                 <exclude name="*.*" />
43                 <exclude name=".tx" />
44                 <exclude name="build" />
45                 <exclude name="docs" />
46                 <exclude name="fonts" />
47                 <exclude name="images" />
48                 <exclude name="library" />
49                 <exclude name="styles" />
50                 <exclude name="themes" />
51                 <exclude name="vendor" />
52                 <exclude name="Tool" />
53                 <exclude name="Zend" />
54             </fileset>
55         </foreach>
56     </target>
57     
58     <!-- ============================================  -->
59     <!-- Target: phpdoc                                -->
60     <!-- ============================================  -->
61     <target name="phpdoc">
62         <echo msg="Building Tine 2.0 PHP API Documentation..." />
63         
64         <includepath classpath="${project.basedir}/vendor/phpdocumentor" />
65         
66         <mkdir dir="${builddir}/apidocs" />
67         
68         <phpdoc2 title="Tine 2.0 PHP API Documentation" destdir="${builddir}/apidocs" template="responsive-twig">
69             <fileset dir=".">
70                 <include name="**/*.php" />
71                 <exclude name="Zend/**.php" />
72                 <exclude name="library/**.php" />
73                 <exclude name="vendor/**.php" />
74             </fileset>
75         </phpdoc2>
76     </target>
77     
78     <!-- ============================================  -->
79     <!-- Target: phpunit                               -->
80     <!-- ============================================  -->
81     <target name="phpunit">
82         <echo msg="Starting Tests..." />
83         
84         <if>
85             <isset property="configPath" />
86             <then>
87                 <includepath classpath = "${configPath}" />
88             </then>
89         </if>
90         
91         <delete dir="${builddir}/reports"/>
92         <mkdir dir="${builddir}/reports" />
93         
94         <phpunit configuration="../tests/tine20/phpunit.xml" haltonfailure="true" haltonerror="true" printsummary="true">
95             <formatter type="plain" usefile="false"/>
96             <formatter type="xml" todir="${builddir}/reports"/>
97             <batchtest>
98                 <fileset dir="../tests/tine20">
99                   <include name="**/*Test.php"/>
100                   <exclude name="Tinebase/AccountTest.php"/>
101                 </fileset>
102             </batchtest>
103         </phpunit>
104         
105         <phpunitreport infile="${builddir}/reports/testsuites.xml" format="frames" todir="${builddir}/reports/tests"/>
106     </target>
107     
108     <!-- ============================================  -->
109     <!-- Target: report                                -->
110     <!-- ============================================  -->
111     <target name="report">
112         <echo msg="Starting Tests..." />
113         
114         <delete dir="${builddir}/reports"/>
115         <mkdir dir="${builddir}/reports/tests"/>
116         <mkdir dir="${builddir}/reports/coverage"/>
117         <coverage-setup database="${builddir}/reports/coverage.db">
118             <fileset dir=".">
119                 <include name="**/*.php" />
120                 <exclude name="Zend/**.php" />
121                 <exclude name="library/**.php" />
122                 <exclude name="vendor/**.php" />
123             </fileset>
124         </coverage-setup>
125         <phpunit configuration="../tests/tine20/phpunit.xml" haltonfailure="true" haltonerror="true" printsummary="true" codecoverage="true">
126             <formatter type="xml" todir="${builddir}/reports"/>
127             <batchtest>
128                 <fileset dir="../tests/tine20">
129                   <include name="**/*Test.php"/>
130                   <exclude name="Tinebase/AccountTest.php"/>
131                 </fileset>
132             </batchtest>
133         </phpunit>
134         <phpunitreport infile="${builddir}/reports/testsuites.xml" format="frames" todir="${builddir}/reports/tests"/>
135         <coverage-report outfile="${builddir}/reports/coverage.xml">
136             <report todir="${builddir}/reports/coverage" title="Tine 2.0"/>
137         </coverage-report>  
138     </target>
139     
140     <!-- ============================================  -->
141     <!-- Target: build-module                          -->
142     <!-- ============================================  -->
143     <target name="build-module" description="build single module" depends="prepare">
144         <echo msg="Building ${name}" />
145         
146         <!-- do jsb2tk build -->
147         <jsb2tk-build appName="${name}" />
148         
149         <!-- replace buildstuff -->
150         <reflexive>
151             <filterchain>
152                 <replaceregexp>
153                     <regexp pattern="Tine\.clientVersion\.buildType\s*=[^=]{1}[^;]*" replace='Tine.clientVersion.buildType="RELEASE"' modifiers="i" />
154                     <regexp pattern="Tine\.clientVersion\.buildDate\s*=[^=]{1}[^;]*" replace='Tine.clientVersion.buildDate="${buildDate}"' modifiers="i"/>
155                     <regexp pattern="Tine\.clientVersion\.buildRevision\s*=[^=]{1}[^;]*" replace='Tine.clientVersion.codeName="${buildRevision}"' modifiers="i"/>
156                 </replaceregexp>
157             </filterchain>
158             
159             <fileset dir="${builddir}">
160                 <include name="${name}/js/*-FAT*" />
161             </fileset>
162         </reflexive>
163         
164         <!-- debug mode for debug files -->
165         <reflexive>
166             <filterchain>
167                 <replaceregexp>
168                     <regexp pattern="Tine\.clientVersion\.buildType\s*=[^=]{1}[^;]*" replace="Tine.clientVersion.buildType = 'DEBUG'"/>
169                 </replaceregexp>
170             </filterchain>
171             
172             <fileset dir="${builddir}">
173                 <include name="${name}/js/*-FAT-debug*" />
174             </fileset>
175         </reflexive>
176         
177         <!-- original jsb2 builds -->
178         <!-- NOTE as jsb2tk has no path adoption yet we need to do it here -->
179         <copy toDir="${project.basedir}">
180             <fileset dir="${builddir}">
181                 <include name="${name}/*/*" />
182             </fileset>
183             
184             <filterchain>
185                 <replaceregexp>
186                     <regexp pattern="(\.\.\/){2,}images" replace="../../images" modifiers="i"/>
187                     <regexp pattern="(\.\.\/){2,}library" replace="../../library" modifiers="i"/>
188                 </replaceregexp>
189             </filterchain>
190             
191         </copy>
192         
193         <!-- adopt path for getJS/getCSS -->
194         <!-- TODO add deploymode GETTER and move this to jsb2tk -->
195         <copy toDir="${project.basedir}">
196             <mapper type="regexp" from="^(.*\.(js|css))" to="\1.inc"/>
197             
198             <filterchain>
199                 <replaceregexp>
200                     <regexp pattern="(\.\.\/)+images" replace="images" modifiers="i"/>
201                     <regexp pattern="(\.\.\/)+library" replace="library" modifiers="i"/>
202                 </replaceregexp>
203             </filterchain>
204
205             <fileset dir="${builddir}">
206                 <include name="${name}/*/*" />
207             </fileset>
208             
209         </copy>
210         
211         <!-- translations -->
212         <translation-build appName="${name}" />
213         <jsMin targetDir="${builddir}/${name}/js" failOnError="false">
214             <fileset dir="${builddir}/${name}/js">
215                 <include name="*-lang-*-debug.js"/>
216             </fileset>
217         </jsMin>
218         
219         <copy toDir="${project.basedir}/${name}/js">
220             <fileset dir="${builddir}/${name}/js">
221                 <include name="*-lang-*-debug.js" />
222             </fileset>
223         </copy>
224         
225         <copy toDir="${project.basedir}/${name}/js">
226             <fileset dir="${builddir}/${name}/js">
227                 <include name="*-lang-*-debug-min.js" />
228             </fileset>
229             
230             <mapper type="regexp" from="^(.*)-debug-min.js" to="\1.js"/>
231         </copy>
232         
233     </target>
234     
235     <!-- ============================================  -->
236     <!-- Target: clean                                 -->
237     <!-- ============================================  -->
238     <target name="clean">
239         <delete dir="${builddir}" includeemptydirs="true" verbose="false" failonerror="false" />
240         <delete>
241             <fileset dir=".">
242                 <include name="*/*/*-FAT*" />
243                 <include name="*/js/*-lang-*" />
244                 <include name="${project.basedir}/${localedir}/build/*" />
245             </fileset>
246         </delete>
247     </target>
248     
249     <!-- ============================================  -->
250     <!-- Target: mimetypes                                 -->
251     <!-- ============================================  -->
252     <target name="mimetypes">
253         <build-mimetypes appName="${name}" />
254     </target>
255     
256     <!-- ============================================  -->
257     <!-- Target: tx-pull                               -->
258     <!-- ============================================  -->
259     <target name="tx-pull">
260         <echo msg="pull translations from transifex" />
261         <exec command="tx pull -a -f --skip" passthru="true" />
262         <echo msg="commit updated strings now:" />
263         <echo msg="git add */translations" />
264         <echo msg="git commit -m '#7086: update translation files'" />
265         <echo msg="git push gerrit HEAD:refs/heads/master" />
266     </target>
267
268     <!-- ============================================  -->
269     <!-- Target: tx-push                               -->
270     <!-- ============================================  -->
271     <target name="tx-push">
272         <echo msg="updating templates" />
273         <exec command="./langHelper.php --pot" passthru="true" />
274         <echo msg="push translations to transifex" />
275         <exec command="tx push -s" passthru="true" />
276         <echo msg="commit updated strings now:" />
277         <echo msg="git commit -a -m 'update lang templates'" />
278         <echo msg="git push gerrit HEAD:refs/heads/master" />
279     </target>
280     
281     <!-- ============================================  -->
282     <!-- Task: init                                    -->
283     <!-- ============================================  -->
284     <adhoc-task name="init"><![CDATA[
285         class initTask extends Task {
286             function main() {
287                 echo `composer install`;
288                 require_once 'vendor/autoload.php';
289             }
290         }
291     ]]></adhoc-task>
292     
293     <!-- ============================================  -->
294     <!-- Task: jsb2tk-build                            -->
295     <!-- ============================================  -->
296     <adhoc-task name="jsb2tk-build"><![CDATA[
297         class jsb2tkTask extends Task {
298             private $appName;
299             
300             function setAppName($appName) {
301                 $this->appName = $appName;
302             }
303             
304             function main() {
305                 $jsb2 = "${project.basedir}/{$this->appName}/{$this->appName}.jsb2";
306                 if (file_exists($jsb2)) {
307                     $this->log("In jsb2tkTask: " . $this->appName);
308                     
309                     require_once('${project.basedir}/library/jsb2tk/jsb2tk.php');
310                     
311                     $tk = new jsb2tk(array(
312                         'homeDir' => '${builddir}'
313                     ));
314                     
315                     $tk->register($jsb2);
316                     $tk->buildAll();
317                 }
318             }
319         }
320     ]]></adhoc-task>
321     
322     <!-- ============================================  -->
323     <!-- Task: translation-build                       -->
324     <!-- ============================================  -->
325     <adhoc-task name="translation-build"><![CDATA[
326         class translationTask extends Task {
327             private $appName;
328         
329             function setAppName($appName) {
330                 $this->appName = $appName;
331             }
332             
333             function main() {
334                 if (! file_exists('${builddir}/' . "{$this->appName}/js")) return;
335                 $availableTranslations = Tinebase_Translation::getAvailableTranslations();
336                 
337                 foreach ($availableTranslations as $translation) {
338                     $localeString = $translation['locale'];
339                     $locale = new Zend_Locale($localeString);
340                     
341                     $jsTranslation = Tinebase_Translation::getJsTranslations($locale, $this->appName);
342                     
343                     if ($this->appName == 'Tinebase' && file_exists('${project.basedir}/langstatistics.json')) {
344                         $langstatistics = json_decode(file_get_contents('${project.basedir}/langstatistics.json'), TRUE);
345                         $localeStats = array_values(array_filter($langstatistics['langStats'], function($stats) use ($localeString) {return $stats['locale'] == $localeString;}));
346                         $jsTranslation .= ("Locale.translationStats=" . json_encode($localeStats[0]) . ";\n");
347                     }
348                     
349                     file_put_contents('${builddir}/' . "{$this->appName}/js/{$this->appName}-lang-{$locale}-debug.js", $jsTranslation);
350                 }
351                 
352                 foreach (Tinebase_Translation::getTranslationDirs() as $appName => $translationPath) {
353                     foreach (scandir($translationPath) as $poFile) {
354                         if (substr($poFile, -3) == '.po') {
355                             $langName = substr($poFile, 0, -3);
356                             `cd "$translationPath"
357                             msgfmt -o $langName.mo $poFile`;
358                         }
359                     }
360                 }
361             }
362         }
363     ]]></adhoc-task>
364     
365     
366     <!-- ============================================  -->
367     <!-- Task: build-mimetypes                         -->
368     <!-- ============================================  -->
369     <adhoc-task name="build-mimetypes"><![CDATA[
370         class mimetypeTask extends Task {
371             private $appName;
372         
373             function setAppName($appName) {
374                 $this->appName = $appName;
375             }
376                                   
377             function buildMimeTypesStyleFile($resolution, &$styleSheet) {
378             
379                 $relatedImgPath = '/images/oxygen/'.$resolution.'/mimetypes/';
380                 $imgPath = '${project.basedir}'.$relatedImgPath;
381                 if (! file_exists($imgPath) || ! is_dir($imgPath)) {
382                         echo 'Mimetype images no found!';
383                         return;
384                 }
385  
386                                 
387                         // √∂ffnen des Verzeichnisses
388                         if ( $handle = opendir($imgPath) ) {
389                         
390                         fwrite($styleSheet, ".standardFileClass_".$resolution." .x-grid3-cell-inner {\n");
391                                 fwrite($styleSheet, "    background-image: url(../..".$relatedImgPath."application-octet-stream.png);\n");
392                                 fwrite($styleSheet, "    background-repeat:  no-repeat;\n");
393                                 fwrite($styleSheet, "    padding-left: 19px;\n");
394                                 fwrite($styleSheet, "}\n\n");
395                 
396                             // einlesen der Verzeichnisses
397                                 while (($file = readdir($handle)) !== false)
398                                 {       
399                                         $fileName = basename($file, '.png');
400                                         
401                                         $addToStyle = strcmp($fileName, "..") + strcmp($fileName, "..");
402                                         if($addToStyle > 0) {
403                                         
404                                                 fwrite($styleSheet, ".".$fileName."_".$resolution." .x-grid3-cell-inner {\n");
405                                                 fwrite($styleSheet, "    background-image: url(../..".$relatedImgPath.$file.") !important;\n");
406                                                 fwrite($styleSheet, "    background-repeat:  no-repeat;\n");
407                                                 fwrite($styleSheet, "    padding-left: 19px;\n");
408                                                 fwrite($styleSheet, "}\n\n");
409                                         }
410                                 }
411                                 
412                                 closedir($handle);
413                         }
414             
415             }
416             
417             function main() {
418                                 $styleSheet = fopen('Tinebase/css/mimetypes.css', 'w+');
419                         $this->buildMimeTypesStyleFile('16x16', $styleSheet);
420                                         $this->buildMimeTypesStyleFile('22x22', $styleSheet);
421                                         $this->buildMimeTypesStyleFile('32x32', $styleSheet);                   
422                                         fclose($styleSheet);
423                 }       
424         }
425     ]]></adhoc-task>
426     
427     
428     
429     <!-- ============================================  -->
430     <!-- Task: manifest-build                          -->
431     <!-- TODO  make it working (just a codestore)      -->
432     <!-- ============================================  -->
433     <adhoc-task name="manifest-build"><![CDATA[
434         class manifestBuildTask extends Task {
435             private $appName;
436         
437             function setAppName($appName) {
438                 $this->appName = $appName;
439             }
440             
441             function main() {
442                 $defaultFiles = "CACHE MANIFEST\n# Build by $build\nCACHE:\n";
443                 
444                 $manifest = fopen('${project.basedir}/tine20.manifest', 'w+');
445                 fwrite($manifest, $defaultFiles . "\n");
446                 
447                 $files = array(
448                     'Tinebase/css/tine-all.css',                               
449                     'Tinebase/js/tine-all.js',
450                     'styles/tine20.css',                             
451                     'library/ExtJS/ext-all.js',
452                     'library/ExtJS/adapter/ext/ext-base.js',   
453                     'library/ExtJS/resources/css/ext-all.css',
454                     'images/oxygen/16x16/actions/knewstuff.png' // ???
455                 );
456                 
457                 // no subdirs! => solaris does not know find -maxdeps 1
458                 exec("cd \"$tine20path\"; ls images/* | grep images/ | egrep '\.png|\.gif|\.jpg'", $baseImages);
459                 $files = array_merge($files, $baseImages);
460                 
461                 $tineCSS = file_get_contents($tine20path . '/Tinebase/css/tine-all-debug.css');
462                 preg_match_all('/url\(..\/..\/(images.*)\)/U', $tineCSS, $matches);
463                 $files = array_merge($files, $matches[1]);
464                 
465                 $tineCSS = file_get_contents($tine20path . '/Tinebase/css/tine-all-debug.css');
466                 preg_match_all('/url\(..\/..\/(library.*)\)/U', $tineCSS, $matches);
467                 $files = array_merge($files, $matches[1]);
468                     
469                 $tineJs = file_get_contents($tine20path . '/Tinebase/js/tine-all-debug.js');
470                 preg_match_all('/labelIcon: [\'|"](.*png)/U', $tineJs, $matches);
471                 $files = array_merge($files, $matches[1]);
472                 
473                 $tineJs = file_get_contents($tine20path . '/Tinebase/js/tine-all-debug.js');
474                 preg_match_all('/labelIcon: [\'|"](.*gif)/U', $tineJs, $matches);
475                 $files = array_merge($files, $matches[1]);
476                 
477                 $tineJs = file_get_contents($tine20path . '/Tinebase/js/tine-all-debug.js');
478                 preg_match_all('/src=[\'|"](.*png)/U', $tineJs, $matches);
479                 $files = array_merge($files, $matches[1]);
480                 
481                 $tineJs = file_get_contents($tine20path . '/Tinebase/js/tine-all-debug.js');
482                 preg_match_all('/src=[\'|"](.*gif)/U', $tineJs, $matches);
483                 $files = array_merge($files, $matches[1]);
484                 
485                 exec("cd \"$tine20path\"; find library/ExtJS/resources/images -type f -name *.gif", $extImages);
486                 $files = array_merge($files, $extImages);
487                 exec("cd \"$tine20path\"; find library/ExtJS/resources/images -type f -name *.png", $extImages);
488                 $files = array_merge($files, $extImages);
489                 
490                 exec("cd \"$tine20path\"; find styles -type f", $tine20Styles);
491                 $files = array_merge($files, $tine20Styles);
492                 
493                 $files = array_unique($files);
494                 
495                 foreach($files as $file) {
496                     if (! is_file("$tine20path/$file")) {
497                         echo "WARNING $file not found, removing it from manifest.\n";
498                     } else if (substr(basename($file), 0, 1) == '.' || ! preg_match('/(js|css|gif|png|jpg)$/', $file))  {
499                         echo "INFO $file is unwanted, removing it from manifest.\n";
500                     } else {
501                         fwrite($manifest, $file . "\n");
502                     }
503                 }
504                 
505                 fclose($manifest);
506             }
507         }
508     ]]></adhoc-task>
509     
510     <!-- ============================================  -->
511     <!-- Task: zend-translation-build                  -->
512     <!-- TODO  make a target for this                  -->
513     <!-- ============================================  -->
514     <adhoc-task name="zend-translation-build"><![CDATA[
515         class zendTranslationTask extends Task {
516             function main() {
517                 // dump one langfile for every locale
518                 $localelist = Zend_Locale::getLocaleList();
519                 foreach ($localelist as $locale => $something) {
520                     try {   
521                         $js = $this->createJsTranslationLists($locale);
522                         file_put_contents('${builddir}/${localedir}/static/' . "generic-$locale-debug.js", $js);
523                     } catch (Exception $e) {
524                         echo "WARNING: could not create translation file for '$locale': '{$e->getMessage()}'\n";
525                     }
526                 }
527             }
528             
529             /**
530              * creates translation lists js files for locale with js object
531              *
532              * @param   string $_locale
533              * @return  string the file contents
534              */
535             function createJsTranslationLists($_locale) {
536                 $jsContent = "Locale.prototype.TranslationLists = {\n";
537             
538                 $types = array(
539                     'Date'           => array('path' => 'Date'),
540                     'Time'           => array('path' => 'Time'),
541                     'DateTime'       => array('path' => 'DateTime'),
542                     'Month'          => array('path' => 'Month'),
543                     'Day'            => array('path' => 'Day'),
544                     'Symbols'        => array('path' => 'Symbols'),
545                     'Question'       => array('path' => 'Question'),
546                     'Language'       => array('path' => 'Language'),
547                     'CountryList'    => array('path' => 'Territory', 'value' => 2),
548                     'Territory'      => array('path' => 'Territory', 'value' => 1),
549                     'CityToTimezone' => array('path' => 'CityToTimezone'),
550                 );
551                 
552                 $zendLocale = new Zend_Locale($_locale);
553                 
554                 foreach ( $types as $name => $path) {
555                     $list = $zendLocale->getTranslationList($path['path'], $_locale, array_key_exists('value', $path) ? $path['value'] : false);
556                     //print_r ( $list );
557                     
558                     if ( is_array($list) ) {
559                         $jsContent .= "\n\t$name: {";                
560                             
561                         foreach ( $list as $key => $value ) {    
562                             // convert ISO -> PHP for date formats
563                             if ( in_array($name, array('Date', 'Time', 'DateTime')) ) {
564                                 $value = $this->convertIsoToPhpFormat($value);
565                             }
566                             $value = preg_replace("/\"/", '\"', $value);        
567                             $jsContent .= "\n\t\t'$key': \"$value\",";
568                         }
569                         // remove last comma
570                         $jsContent = chop($jsContent, ",");
571                                 
572                         $jsContent .= "\n\t},";
573                     }
574                 }    
575                 $jsContent = chop($jsContent, ",");
576                 
577                 $jsContent .= "\n};\n";
578                 return $jsContent;
579             }
580             
581             /**
582              * Converts a format string from ISO to PHP format
583              * reverse the functionality of Zend's convertPhpToIsoFormat()
584              * 
585              * @param  string  $format  Format string in PHP's date format
586              * @return string           Format string in ISO format
587              */
588             function convertIsoToPhpFormat($format) {
589                 $convert = array(
590                     'c' => '/yyyy-MM-ddTHH:mm:ssZZZZ/',
591                     '$1j$2' => '/([^d])d([^d])/',
592                     'j$1' => '/^d([^d])/', 
593                     '$1j' => '/([^d])d$/', 
594                     't' => '/ddd/', 
595                     'd' => '/dd/', 
596                     'l' => '/EEEE/', 
597                     'D' => '/EEE/', 
598                     'S' => '/SS/',
599                     'w' => '/eee/', 
600                     'N' => '/e/', 
601                     'z' => '/D/', 
602                     'W' => '/w/', 
603                     '$1n$2' => '/([^M])M([^M])/', 
604                     'n$1' => '/^M([^M])/', 
605                     '$1n' => '/([^M])M$/', 
606                     'F' => '/MMMM/', 
607                     'M' => '/MMM/',
608                     'm' => '/MM/', 
609                     'L' => '/l/', 
610                     'o' => '/YYYY/', 
611                     'Y' => '/yyyy/', 
612                     'y' => '/yy/',
613                     'a' => '/a/', 
614                     'A' => '/a/', 
615                     'B' => '/B/', 
616                     'h' => '/hh/',
617                     'g' => '/h/', 
618                     '$1G$2' => '/([^H])H([^H])/', 
619                     'G$1' => '/^H([^H])/', 
620                     '$1G' => '/([^H])H$/', 
621                     'H' => '/HH/', 
622                     'i' => '/mm/', 
623                     's' => '/ss/', 
624                     'e' => '/zzzz/', 
625                     'I' => '/I/', 
626                     'P' => '/ZZZZ/', 
627                     'O' => '/Z/',
628                     'T' => '/z/', 
629                     'Z' => '/X/', 
630                     'r' => '/r/', 
631                     'U' => '/U/',
632                 );
633                 
634                 //echo "pre:".$format."\n";
635                 
636                 $patterns = array_values($convert);
637                 $replacements = array_keys($convert);
638                 $format = preg_replace($patterns, $replacements, $format);
639                 
640                 //echo "post:".$format."\n";
641                 //echo "---\n";
642                 
643                 return $format;
644             }
645         }
646     ]]></adhoc-task>
647 </project>