ATIM cakephp customizations
This page depicts what global changes have been made to cakephp 1.3 to suit the needs of ATiM. Those customizations are preceeded by the comment //ATIM2
There is also a specific page on how to set up customize models, controllers and views.
Contents |
dbo_mysql.php
cake/libs/model/datasources/dbo/dbo_mysql.php
Note: Only the mysql dbo file has been currently modified but other dbos could as easily be changed.
Changes have been made to make the application print an error message when it can't connect to the database. Otherwise it only prints an error page that doesn't give any clue about the situation.
Previously <source lang=php> function connect() { [...] if (!$config['persistent']) { $this->connection = mysql_connect($config['host'] . ':' . $config['port'], $config['login'], $config['password'], true); $config['connect'] = 'mysql_connect'; } else { $this->connection = mysql_pconnect($config['host'] . ':' . $config['port'], $config['login'], $config['password']); }
if (mysql_select_db($config['database'], $this->connection)) { $this->connected = true; } [...] } </source>
After <source lang=php> function connect() { [...] if (!$config['persistent']) { $this->connection = mysql_connect($config['host'] . ':' . $config['port'], $config['login'], $config['password'], true) //ATIM 2 or die("Failed to connect to database"); $config['connect'] = 'mysql_connect'; } else { $this->connection = mysql_pconnect($config['host'] . ':' . $config['port'], $config['login'], $config['password']) //ATIM 2 or die("Failed to connect to database"); }
if (mysql_select_db($config['database'], $this->connection)) { $this->connected = true; }else{ //ATIM 2 die("Failed to select database schema"); } [...] } </source>
i18n.php
cake/libs/i18n.php
Changes have been made to make the application highlight strings that failed to be translated in red when debug is turned on. They are also being logged into the database regardless of the debug level. The modification to the core only implies calling our own handling function.
Previously: <source lang=php> function translate($singular, $plural = null, $domain = null, $category = 6, $count = null) { [...] if (!empty($plurals)) { return $plural; } return $singular; } </source>
After <source lang=php> function translate($singular, $plural = null, $domain = null, $category = 6, $count = null) { [...] if (!empty($plurals)) { return $plural; }else if(empty($_this->__domains[$_this->category][$_this->__lang][$domain][$singular]) && class_exists("AppController")) { AppController::missingTranslation($singular); } return $singular; } </source>
configure.php
cake/libs/configure.php
Changes have been made to allow cake to load ATiM custom controllers if they exist.
Note: There are two ATiM blocks in the following function.
Previously: <source lang=php> function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { [...] if ($name != null && !class_exists($name . $ext['class'])) { if ($load = $_this->__mapped($name . $ext['class'], $type, $plugin)) { if ($_this->__load($load)) { $_this->__overload($type, $name . $ext['class'], $parent);
if ($_this->return) { return include($load); } return true; } else { $_this->__remove($name . $ext['class'], $type, $plugin); $_this->__cache = true; } } if (!empty($search)) { $_this->search = $search; } elseif ($plugin) { $_this->search = $_this->__paths('plugin'); } else { $_this->search = $_this->__paths($type); } $find = $file;
if ($find === null) { $find = Inflector::underscore($name . $ext['suffix']).'.php';
if ($plugin) { $paths = $_this->search; foreach ($paths as $key => $value) { $_this->search[$key] = $value . $ext['path']; } } }
if (strtolower($type) !== 'vendor' && empty($search) && $_this->__load($file)) { $directory = false; } else { $file = $find; $directory = $_this->__find($find, true); }
if ($directory !== null) { $_this->__cache = true; $_this->__map($directory . $file, $name . $ext['class'], $type, $plugin); $_this->__overload($type, $name . $ext['class'], $parent);
if ($_this->return) { return include($directory . $file); } return true; } return false; } return true; } </source>
After: <source lang=php> function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { [...] if ($name != null && !class_exists($name . $ext['class'])) { if ($load = $_this->__mapped($name . $ext['class'], $type, $plugin)) { if ($_this->__load($load)) { $_this->__overload($type, $name . $ext['class'], $parent);
//ATIM2: include custom files, if they exist $atim_custom_file = str_replace(DS."controllers".DS, DS."controllers".DS."customs".DS, $load); if($atim_custom_file != $load && file_exists($atim_custom_file)){ include_once ($atim_custom_file); }
$atim_custom_file = str_replace(DS."models".DS, DS."models".DS."customs".DS, $load);
if($atim_custom_file != $load && file_exists($atim_custom_file)){ include_once ($atim_custom_file); } if ($_this->return) { return include($load); } return true; } else { $_this->__remove($name . $ext['class'], $type, $plugin); $_this->__cache = true; } } if (!empty($search)) { $_this->search = $search; } elseif ($plugin) { $_this->search = $_this->__paths('plugin'); } else { $_this->search = $_this->__paths($type); } $find = $file;
if ($find === null) { $find = Inflector::underscore($name . $ext['suffix']).'.php';
if ($plugin) { $paths = $_this->search; foreach ($paths as $key => $value) { $_this->search[$key] = $value . $ext['path']; } } }
if (strtolower($type) !== 'vendor' && empty($search) && $_this->__load($file)) { $directory = false; } else { $file = $find; $directory = $_this->__find($find, true); }
if ($directory !== null) { $_this->__cache = true; $_this->__map($directory . $file, $name . $ext['class'], $type, $plugin); $_this->__overload($type, $name . $ext['class'], $parent);
// ATiM2: include custom files, if they exist if ( file_exists($directory . 'customs' . DS . $file) ){ include_once $directory . 'customs' . DS . $file; }
if ($_this->return) { return include($directory . $file); } return true; } return false; } return true; } </source>
basics.php
cake/basic.php
Changes have been made to prevent the translator from trying to translate numbers. Without it, a translation for 0 returns nothing and some numbers are transformed into others.
Previously:
<source lang=php>
function __($singular, $return = false) {
if (!$singular) { return; } [...] } </source> After: <source lang=php> function __($singular, $return = false) { if(is_numeric($singular)){ if($return){ return $singular; } echo($singular); return; } if (!$singular) { return; } [...] } </source>
validation.php
cake/libs/validation.php
Remember the y2k bug? Changes have been made to cakephp core so that years with only 2 digits are not accepted as input. The regular expressions need to be changed. The part for the year looks like 1[6-9]|[2-9]\\d)?\\d{2} You need to remove the middle "?" which means that the 2 last digits are optional. It becomes 1[6-9]|[2-9]\\d)\\d{2}
Previously:
function date($check, $format = 'ymd', $regex = null) {
[...]
$regex['dmy'] = '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
$regex['mdy'] = '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
$regex['ymd'] = '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})(\\/|-|\\.|\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]))))$%';
$regex['dMy'] = '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ (((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]\\d)\\d{2})$/';
$regex['Mdy'] = '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/';
$regex['My'] = '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]|[2-9]\\d)\\d{2})$%';
$regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
[...]
}
After:
function date($check, $format = 'ymd', $regex = null) {
[...]
$regex['dmy'] = '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)\\d{2})$%';
$regex['mdy'] = '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)\\d{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)\\d{2})$%';
$regex['ymd'] = '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)\\d{2})(\\/|-|\\.|\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]))))$%';
$regex['dMy'] = '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ (((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]\\d)\\d{2})$/';
$regex['Mdy'] = '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/';
$regex['My'] = '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]|[2-9]\\d)\\d{2})$%';
$regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
[...]
Changes to allow custom controllers/models/views
configure.php
cake/libs/configure.php
Changes have been made to allow cake to load ATiM custom controllers if they exist.
Note: There are two ATiM blocks in the following function.
Previously: <source lang=php> function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { [...] if ($name != null && !class_exists($name . $ext['class'])) { if ($load = $_this->__mapped($name . $ext['class'], $type, $plugin)) { if ($_this->__load($load)) { $_this->__overload($type, $name . $ext['class'], $parent);
if ($_this->return) { return include($load); } return true; } else { $_this->__remove($name . $ext['class'], $type, $plugin); $_this->__cache = true; } } if (!empty($search)) { $_this->search = $search; } elseif ($plugin) { $_this->search = $_this->__paths('plugin'); } else { $_this->search = $_this->__paths($type); } $find = $file;
if ($find === null) { $find = Inflector::underscore($name . $ext['suffix']).'.php';
if ($plugin) { $paths = $_this->search; foreach ($paths as $key => $value) { $_this->search[$key] = $value . $ext['path']; } } }
if (strtolower($type) !== 'vendor' && empty($search) && $_this->__load($file)) { $directory = false; } else { $file = $find; $directory = $_this->__find($find, true); }
if ($directory !== null) { $_this->__cache = true; $_this->__map($directory . $file, $name . $ext['class'], $type, $plugin); $_this->__overload($type, $name . $ext['class'], $parent);
if ($_this->return) { return include($directory . $file); } return true; } return false; } return true; } </source>
After: <source lang=php> function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { [...] if ($name != null && !class_exists($name . $ext['class'])) { if ($load = $_this->__mapped($name . $ext['class'], $type, $plugin)) { if ($_this->__load($load)) { $_this->__overload($type, $name . $ext['class'], $parent);
//ATIM2: include custom files, if they exist $atim_custom_file = str_replace(DS."controllers".DS, DS."controllers".DS."customs".DS, $load); if($atim_custom_file != $load && file_exists($atim_custom_file)){ include_once ($atim_custom_file); }
$atim_custom_file = str_replace(DS."models".DS, DS."models".DS."customs".DS, $load);
if($atim_custom_file != $load && file_exists($atim_custom_file)){ include_once ($atim_custom_file); } if ($_this->return) { return include($load); } return true; } else { $_this->__remove($name . $ext['class'], $type, $plugin); $_this->__cache = true; } } if (!empty($search)) { $_this->search = $search; } elseif ($plugin) { $_this->search = $_this->__paths('plugin'); } else { $_this->search = $_this->__paths($type); } $find = $file;
if ($find === null) { $find = Inflector::underscore($name . $ext['suffix']).'.php';
if ($plugin) { $paths = $_this->search; foreach ($paths as $key => $value) { $_this->search[$key] = $value . $ext['path']; } } }
if (strtolower($type) !== 'vendor' && empty($search) && $_this->__load($file)) { $directory = false; } else { $file = $find; $directory = $_this->__find($find, true); }
if ($directory !== null) { $_this->__cache = true; $_this->__map($directory . $file, $name . $ext['class'], $type, $plugin); $_this->__overload($type, $name . $ext['class'], $parent);
// ATiM2: include custom files, if they exist if ( file_exists($directory . 'customs' . DS . $file) ){ include_once $directory . 'customs' . DS . $file; }
if ($_this->return) { return include($directory . $file); } return true; } return false; } return true; } </source>
dispatcher.php
/cake/dispatcher.php
In the __getController function, the following code is added at approximately line 459 (line 387 in CakePHP 1.3.2) <source lang=php> // ATiM2: load custom controller $ctrlCustom = $ctrlClass.'Custom'; if (class_exists($ctrlCustom)) $controller =& new $ctrlCustom(); </source>
view.php
/cake/libs/view/view.php
In the _getViewFileName function, the following code is added/changed at approximately line 812 (line 865 in CakePHP 1.3.2) <source lang=php> // ATiM2: load custom view $custom_name = explode(DS,$name); $custom_name[ count($custom_name)-1 ] = 'customs'.DS.$custom_name[ count($custom_name)-1 ]; $custom_name = implode(DS,$custom_name);
if (file_exists($path . $custom_name . $ext)) { return $path . $custom_name . $ext; }
else if (file_exists($path . $name . $ext)) { return $path . $name . $ext; } </source>
class_registry.php
/cake/libs/class_registry.php
In the init function, the following code is added at approximately line 141
<source lang=php>
// ATiM2: load custom controller
$modelCustom = $class.'Custom';
if (class_exists($modelCustom)){
${$class} =& new $modelCustom($settings);
// loop through all DEFAULT model's behaviours and properly reattach them to custom model... foreach(${$class}->actsAs as $key => $data){ if ( is_array($data) ) { $behavior = $key; $config = $data; } else { $behavior = $data; $config = null; }
${$class}->Behaviors->attach($behavior, $config); ${$class}->Behaviors->$behavior->setup(${$class},$config); } }else{ ${$class} =& new $class($settings); } </source>