root/trunk/lib/SGL/Inflector.php

Revision 3125, 10.4 kB (checked in by demian, 3 weeks ago)

bugfix to trunk merge -3

  • Property svn:eol-style set to native
Line 
1 <?php
2 /* Reminder: always indent with 4 spaces (no tabs). */
3 // +---------------------------------------------------------------------------+
4 // | Copyright (c) 2006, Demian Turner                                         |
5 // | All rights reserved.                                                      |
6 // |                                                                           |
7 // | Redistribution and use in source and binary forms, with or without        |
8 // | modification, are permitted provided that the following conditions        |
9 // | are met:                                                                  |
10 // |                                                                           |
11 // | o Redistributions of source code must retain the above copyright          |
12 // |   notice, this list of conditions and the following disclaimer.           |
13 // | o Redistributions in binary form must reproduce the above copyright       |
14 // |   notice, this list of conditions and the following disclaimer in the     |
15 // |   documentation and/or other materials provided with the distribution.    |
16 // | o The names of the authors may not be used to endorse or promote          |
17 // |   products derived from this software without specific prior written      |
18 // |   permission.                                                             |
19 // |                                                                           |
20 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
21 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         |
22 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     |
23 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT      |
24 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     |
25 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT          |
26 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     |
27 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
28 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
29 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     |
30 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      |
31 // |                                                                           |
32 // +---------------------------------------------------------------------------+
33 // | Seagull 0.6                                                               |
34 // +---------------------------------------------------------------------------+
35 // | Inflector.php                                                             |
36 // +---------------------------------------------------------------------------+
37 // | Author:   Demian Turner <demian@phpkitchen.com>                           |
38 // +---------------------------------------------------------------------------+
39
40 /**
41  * Performs transformations on resource names, ie, urls, classes, methods, variables.
42  *
43  */
44 class SGL_Inflector
45 {
46     /**
47     * Returns true if querystring has been simplified.
48     *
49     * This happens when a manager name is the same as its module name, ie
50     * UserManger in the 'user' module would become user/user which gets
51     * reduced to user
52     *
53     * $querystring does not include the frontScriptName, ie, index.php
54     *
55     * @param string $querystring    From the querystring fragment onwards, ie /user/account/userid/2/
56     * @param string $sectionName    From the database
57     * @return boolean
58     */
59     function isUrlSimplified($querystring, $sectionName)
60     {
61         if (!(empty($querystring))) {
62             if (SGL_Inflector::urlContainsDuplicates($querystring)) {
63                 $ret = false;
64             } else {
65                 $aUrlPieces = explode('/', $querystring);
66                 $moduleName = $aUrlPieces[0];
67                 $aSections explode('/', $sectionName);
68                 $ret = in_array($moduleName, $aSections)
69                     && (SGL_Inflector::urlContainsDuplicates($sectionName));
70             }
71         } else {
72             $ret = false;
73         }
74         return $ret;
75     }
76
77     /**
78      * Returns true if manager name is the same of module name, ie, index.php/faq/faq/.
79      *
80      * @param string $url
81      * @return boolean
82      */
83     function urlContainsDuplicates($url)
84     {
85         if (!empty($url)) {
86             $aPieces = explode('/', $url);
87             $initial = count($aPieces);
88             $unique = count(array_unique($aPieces));
89             $ret = $initial != $unique;
90         } else {
91             $ret = false;
92         }
93         return $ret;
94     }
95
96     /**
97      * Determine if a simplified notation is being used.
98      *
99      * If the url was of the form example.com/index.php/contactus/contactus/
100      * and it got simplifeid too example.com/index.php/contactus/ it is important
101      * to determine if that simplification happened, so subsequent parameters
102      * don't get interpreted as 'managerName'
103      *
104      * @param array $aParsedUri
105      * @return boolean
106      */
107     function isMgrNameOmitted($aParsedUri)
108     {
109         $fullMgrName = SGL_Inflector::getManagerNameFromSimplifiedName(
110             $aParsedUri['managerName']);
111
112         //  compensate for case-sensitivity
113         $corrected = SGL_Inflector::caseFix($fullMgrName, true);
114         $path = SGL_MOD_DIR . '/'. $aParsedUri['moduleName'] . '/classes/' . $corrected . '.php';
115
116         //  if the file exists, mgr name is valid and has not been omitted
117         if (!is_file($path)) {
118             //  so before we can be sure of simplification, let's check for presence of simplified Manager,
119             //  ie, that has same name of module, so if module is foo, look for FooMgr
120             $mgrName = SGL_Inflector::getManagerNameFromSimplifiedName($aParsedUri['moduleName']);
121             $corrected = SGL_Inflector::caseFix($mgrName, true);
122             $pathToMgr = SGL_MOD_DIR . '/'. $aParsedUri['moduleName'] . '/classes/' . $corrected . '.php';
123             //  if a default mgr can be loaded, then we assume that mgr name was omitted in request
124             $ret = is_file($pathToMgr);
125         } else {
126             $ret = false;
127         }
128         return $ret;
129     }
130
131     /**
132      * Returns the full Manager name given the short name, ie, faq becomes FaqMgr.
133      *
134      * @static
135      * @param string $name
136      * @return string
137      */
138     function getManagerNameFromSimplifiedName($name)
139     {
140         //  if Mgr suffix has been left out, append it
141         if (strtolower(substr($name, -3)) != 'mgr') {
142             $name .= 'Mgr';
143         }
144         return SGL_Inflector::caseFix(ucfirst($name), $force = true);
145     }
146
147     /**
148      * Returns the short name given the full Manager name, ie FaqMgr becomes faq.
149      *
150      * @static
151      * @param string $name
152      * @return string
153      */
154     function getSimplifiedNameFromManagerName($name)
155     {
156         //  strip file extension if exists
157         if (substr($name, -4) == '.php') {
158             $name = substr($name, 0, -4);
159         }
160
161         //  strip 'Mgr' if exists
162         if (strtolower(substr($name, -3)) == 'mgr') {
163             $name = substr($name, 0, -3);
164         }
165         return strtolower($name);
166     }
167
168    /**
169     * Converts "string with spaces" to "camelCase" string.
170     *
171     * @access  public
172     * @param   string $s
173     * @return  string
174     *
175     * @author Julien Casanova <julien_casanova AT yahoo DOT fr>
176     */
177     function camelise($s)
178     {
179         $ret = '';
180         $i = 0;
181
182         $s = preg_replace('!\s+!', ' ', $s);
183         $s = trim($s);
184         $aString = explode(' ', $s);
185         foreach ($aString as $value) {
186             if ($i == 0) {
187                 $ret .= strtolower($value);
188             } else {
189                 $ret .= ucfirst(strtolower($value));
190             }
191             $i++;
192         }
193         return $ret;
194     }
195
196     function getTitleFromCamelCase($camelCaseWord)
197     {
198         if (!SGL_Inflector::isCamelCase($camelCaseWord)) {
199             return $camelCaseWord;
200         }
201         $ret = '';
202         for ($x = 0; $x < strlen($camelCaseWord); $x ++) {
203             if (preg_match("/[A-Z]/", $camelCaseWord{$x})) {
204                 $ret .= ' ';
205             }
206             $ret .= $camelCaseWord{$x};
207         }
208         return ucfirst($ret);
209     }
210
211     function isCamelCase($str)
212     {
213         //  ensure no non-alpha chars
214         if (preg_match("/[^a-z].*/i", $str)) {
215             return false;
216         }
217         //  and at least 1 capital not including first letter
218         for ($x = 1; $x < strlen($str)-1; $x ++) {
219             if (preg_match("/[A-Z]/", $str{$x})) {
220                 return true;
221             }
222         }
223     }
224
225     function isConstant($str)
226     {
227         if (empty($str)) {
228             return false;
229         }
230         if (preg_match('/sessid/i', $str)) {
231             return false;
232         }
233         $pattern = '@^[A-Z_\']*$@';
234         if (!preg_match($pattern, $str)) {
235             return false;
236         }
237         return true;
238     }
239
240     /**
241      * Returns a human-readable string from $lower_case_and_underscored_word,
242      * by replacing underscores with a space, and by upper-casing the initial characters.
243      *
244      * @param string $lower_case_and_underscored_word String to be made more readable
245      * @return string Human-readable string
246      */
247     function humanise($lowerCaseAndUnderscoredWord)
248     {
249         $replace = ucwords(str_replace("_", " ", $lowerCaseAndUnderscoredWord));
250         return $replace;
251     }
252
253     /**
254      * Makes up for case insensitive classnames in php4 with get_class().
255      *
256      * @access   public
257      * @static
258      * @param    string     $str    Classname
259      * @param    boolean    $force  Force the operation regardless of php version
260      * @return   mixed              Either correct case classname or original classname if no key found
261      */
262     function caseFix($str, $force = false)
263     {
264         if (!$force && (($phpVersion{0} = PHP_VERSION) == 5)) {
265             return $str;
266         }
267         $c = &SGL_Config::singleton();
268         $conf = $c->getAll();
269         $aConfValues = array_keys($conf);
270         $aConfValuesLowerCase = array_map('strtolower', $aConfValues);
271         $isFound = array_search(strtolower($str), $aConfValuesLowerCase);
272         //  iterate through unloaded config files until key is found (not implemented)
273         if (!$isFound) {
274             #crude hack, avoid mgrs with interior bumpy caps
275             if ($str == 'ArticleviewMgr') {
276                 $str = 'ArticleViewMgr';
277             }
278         }
279         return ($isFound !== false) ? $aConfValues[$isFound] : $str;
280     }
281 }
282 ?>
Note: See TracBrowser for help on using the browser.