Какие шаги мне нужно предпринять для обновления с Kohana 3.2 до 3.3 в отношении реализации PSR-0 и какие команды нужно выполнить из командной строки?
Как перейти с Kohana 3.2 на 3.3 (реализуя PSR-0)?
Ответы (2)
Командная строка Unix:
Это шаги, которые я предпринял для реализации PSR-0 в своем приложении Kohana.
Я удалил следующую систему / каталог:
rm -rf system
В вашем текущем bootstrap.php единственное изменение состоит в том, чтобы классы начинались с верхнего, поэтому лучше всего сохранить ваш старый бутстрап и просто изменить следующие строки в верхней части файла:
// Load the core Kohana class
require SYSPATH.'classes/Kohana/Core'.EXT;
if (is_file(APPPATH.'classes/Kohana'.EXT))
{
// Application extends the core
require APPPATH.'classes/Kohana'.EXT;
}
else
{
// Load empty core extension
require SYSPATH.'classes/Kohana'.EXT;
}
Удалите bootstrap.php из нового каталога выпуска kohana. Теперь скопируйте и вставьте все файлы версии 3.3 в старое приложение:
cp -R path/to/new/kohana/* .
Теперь переместите все ваши контроллеры и модели в каталоги с заглавными буквами и удалите старые каталоги:
mv application/classes/controller/* application/classes/Controller
mv application/classes/model/* application/classes/Model
rm -rf application/classes/controller application/classes/model
Каталог поставщика имеет фиксированное место в корне каталога kohana. Переместите каталог вашего поставщика из application/vendor (если он у вас есть) в vendor/
mv application/vendor .
Отредактируйте файл конфигурации базы данных (например, application/config/database.php), все свойства типа должны быть написаны с большой буквы:
return array
(
'default' => array
(
'type' => 'MySQL',
Если вы используете драйвер AUTH orm и перезаписали конфигурацию в application/config/auth.php, запишите имя драйвера в верхнем регистре:
return array(
'driver' => 'ORM',
Теперь самое сложное: все имена классов и имена файлов этих классов должны быть написаны с большой буквы. Перейти к занятиям реж.
cd application/classes
И скопируйте и вставьте эту команду:
for SRC in `find . -depth`
do DST=`dirname "${SRC}"`/`basename "${SRC}" | sed -e 's/^./\U&/'`;
if [ "${SRC}" != "${DST}" ]
then
[ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
fi
done
(источник: http://forum.kohanaframework.org/discussion/comment/73089#Comment_73089 а>)
Эта команда рекурсивно проверяет все каталоги и делает имена файлов заглавными. Перейдите в папку приложения.
cd ../
Теперь внутри моделей и контроллеров (и помощников) напишите все имена классов с большой буквы. Таким образом, Controller_template_parent должен стать Controller_Template_Parent. У меня есть несколько очень неэффективных команд для этого (так что, пожалуйста, внесите свой вклад).
find ./ -name \*.php -exec sed -i "s/helper_\([a-zA-Z]\+\)/Helper_\u\1/gI" {} \;
find ./ -name \*.php -exec sed -i "s/helper_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)/Helper_\u\1_\u\2/gI" {} \;
find ./ -name \*.php -exec sed -i "s/helper_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)/Helper_\u\1_\u\2_\u\3/gI" {} \;
./ в начале для всех файлов (рекурсивных каталогов), заканчивающихся на .php. Я добавил «I» после команды sed, чтобы сделать поиск нечувствительным к регистру. (исходная команда: https://askubuntu.com/questions/84007/find-and-replace-text-within-multiple-files)
Первая команда заменит helper_some_thing_here на Helper_Some_thing_here. Вторая команда преобразует helper_some_thing_here в Helper_Some_Thing_here и т. д. Поэтому, если у вас есть имена классов с более чем 3 символами подчеркивания, вы можете создать свою собственную команду.
То же самое нужно сделать для классов, начинающихся с Model_ и Controller_.
find ./ -name \*.php -exec sed -i "s/model_\([a-zA-Z]\+\)/Model_\u\1/gI" {} \;
find ./ -name \*.php -exec sed -i "s/model_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)/Model_\u\1_\u\2/gI" {} \;
find ./ -name \*.php -exec sed -i "s/model_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)/Model_\u\1_\u\2_\u\3/gI" {} \;
find ./ -name \*.php -exec sed -i "s/controller_\([a-zA-Z]\+\)/Controller_\u\1/gI" {} \;
find ./ -name \*.php -exec sed -i "s/controller_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)/Controller_\u\1_\u\2/gI" {} \;
find ./ -name \*.php -exec sed -i "s/controller_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)/Controller_\u\1_\u\2_\u\3/gI" {} \;
Теперь некоторые имена классов, которые раньше использовались только с 1 заглавной буквы, теперь пишутся полностью заглавными (Html, Url, Http, UTF8). Замените их во всем приложении.
Выполните эту команду в каталоге application/:
find ./ -name \*.php -exec sed -i "s/Url::/URL::/gI" {} \;
find ./ -name \*.php -exec sed -i "s/Html::/HTML::/gI" {} \;
find ./ -name \*.php -exec sed -i "s/Http::/HTTP::/gI" {} \;
find ./ -name \*.php -exec sed -i "s/Utf8::/UTF8::/gI" {} \;
Когда вы используете драйвер ORM, все ваши Orm::factory('some_class') должны быть в верхнем регистре и написаны с заглавной буквы ORM::factory('Some_Class'). Я использую одну и ту же команду, чтобы заглавными буквами прописать все классы ORM и использовать заглавные буквы в именах классов в фабрике.
find ./ -name \*.php -exec sed -i "s/orm::factory(\(\"\|'\)\([a-zA-Z_]\+\)\(\"\|'\)\(,[^,]*\)*)/ORM::factory('\u\2'\4)/gI" {} \;
find ./ -name \*.php -exec sed -i "s/orm::factory(\(\"\|'\)\([a-zA-Z]\+\)_\([a-zA-Z]\+\)\(\"\|'\)\(,[^,]*\)*)/ORM::factory('\u\2_\u\3'\5)/gI" {} \;
find ./ -name \*.php -exec sed -i "s/orm::factory(\(\"\|'\)\([a-zA-Z]\+\)_\([a-zA-Z]\+\)_\([a-zA-Z]\+\)\(\"\|'\)\(,[^,]*\)*)/ORM::factory('\u\2_\u\3_\u\4'\6)/gI" {} \;
Теперь мои модули больше не совместимы с 3.3, не все из них обновлены. Если вы хотите обновить их самостоятельно, вам, вероятно, придется проверить их отдельно, перейти в каталог классов каждого модуля, использовать заглавные буквы в его файле и именах классов. Вы можете использовать предыдущие команды.
Для меня это контрольный список при обновлении приложения, как я уже сказал, не стесняйтесь вносить свой вклад, чтобы обновление стало проще.
Основываясь на ответе Даана и многом другом, я написал php-скрипт для обновления Kohana v3.2 до v3.3.
Он доступен на github: https://github.com/Choufourax/upgrade-kohana-3_2-to-3_3
Или ниже:
#!/usr/bin/php -q
<?php
/*
A PHP SCRIPT TO UPGRADE FROM KOHANA 3.2.X TO KOHANA 3.3.X
------------------------------------------------------
Based on the works of :
=> Daan (http://stackoverflow.com/users/987864/daan)
http://stackoverflow.com/questions/13935621/how-to-upgrade-from-kohana-3-2-to-3-3-implementing-psr-0
=> Alex Cartwright <[email protected]>
https://github.com/AlexC/kohana-upgrade-script
This script is designed to do bulk changes to your codebase that can
easily be automated, changes that would otherwise have the potential
to take a very long time for a large project. It does not provide a
fully automated migration, and it is highly recommended that you read
the official Kohana 3.3 upgrade guide before running this script.
http://kohanaframework.org/3.3/guide/kohana/upgrading
------------------------------------------------------
Be smart, be safe :
BACKUP YOUR WEBSITE BEFORE RUNNING THIS SCRIPT
------------------------------------------------------
This script handles :
- Changes in Bootstrap / database config file / auth config file
- PSR-0 support (file/class naming conventions)
- Change the file names
- Change the name of class in all files (including calls, extends...)
- Case sensitive ORM, HTTP, URL, UTF8, HTML classes
- New syntax for Browser cache checking
- New syntax for Redirects (HTTP 300, 301, 302, 303, 307)
- Apply the changes listed above in Modules too
- Moving the vendor folder
This script does not handle :
- HTTP Exceptions
- Custom Error Pages (HTTP 500, 404, 403, 401 etc)
- Query Builder Identifier Escaping
- Route Filters
Things to do :
- improve regex to prevent replacement mistakes between class and functions
HOW TO USE
------------------------------------------------------
This script is to use on your local version of your website
Do not use on your production server (as you will experiment permission issues as your server is not supose to let you modify PHP files dynamically for security reasons)
Once your local site is updated and you test everything, upload files via FTP to your production server.
1/ Backup your site
2/ Download kohana 3.3
3/ Manulay replace the following folders from Kohana 3.3 to the website to upgrade :
- system
- modules/auth
- modules/cache
- modules/codebench
- modules/database
- modules/image
- modules/minion
- modules/orm
- modules/unittest
- modules/userguide
4/ Edit the settings at the begining of the script
5/ Run this file
- if you use a Mac : the best way will be to open the php file with BBedit and chose in the '#!' menu "Run in Terminal"
- you can also open a Terminal, go to the script folder and type ./upgrade-kohana.php
- you can also just run the script from your local webserver http://localhost/website/upgrade-kohana.php but it's not recommended as you may have some permissions problem to modify the PHP files
------------------------------------------------------
AUTHOR
------------------------------------------------------
@author Erwan Dupeux-Maire
www.upyupy.fr
www.bwat.fr
*/
/*
---------------
SETTINGS
---------------
*/
// START OF SETTINGS
// Path to kohana v3.2 website to update
$path = '/Library/WebServer/Documents/work/bwat/bwat/';
// List of folders to process (at least $path.'application' )
// You sould not use this script to upgrade third party modules that already have a v3.3 version.
$dirs = array (
$path.'application',
$path.'modules/a1',
$path.'modules/a2',
$path.'modules/acl',
$path.'modules/admin',
$path.'modules/adminfiles',
$path.'modules/adminnl',
/*
$path.'modules/auth',
$path.'modules/cache',
$path.'modules/codebench',
$path.'modules/database',
$path.'modules/image',
$path.'modules/minion',
$path.'modules/orm',
$path.'modules/unittest',
$path.'modules/userguide'
*/
);
// Search and replace class name in "views" folders to update the case ?
// true => yes | false => no
$checkInViews = true;
// If there is some files you don't want to process, add them to this array
$skip = array('_notes','.DS_Store','lib-mail-phpmailer','lib-rtf');
// Special class rewrinting
// sometimes, captialize is not enought
// Use this array to set special changes()
$specials = array (
'upyupy' =>'UpyUpy',
'gd' => 'GD',
'orm' => 'ORM',
'db' => 'DB',
'mysql' => 'MySQL',
'pdo' => 'PDO',
'html' => 'HTML',
'url' => 'URL',
'http' => 'HTTP',
'utf8' => 'UTF8',
'validurl' => 'ValidURL',
'validcolor' => 'ValidColor',
'userfuncarray' => 'UserFuncArray',
'urlsite' => 'URLSite',
'stripnullbytes' => 'StripNullBytes',
'mddoincludeviews' => 'MDDoIncludeViews',
'mddoimageurl' => 'MDDoImageURL',
'mddobaseurl' => 'MDDoBaseURL',
'ltrimdigits' => 'LtrimDigits',
'gruberurl' => 'GruberURL',
'explodelimit' => 'ExplodeLimit',
'datespan' => 'DateSpan',
'autolinkemails' => 'AutoLinkEmails',
'arrcallback' => 'ArrCallback'
);
// END OF SETTINGS
// Function to remove folders and files
// @author : http://stackoverflow.com/users/1226894/baba
// http://stackoverflow.com/questions/9835492/move-all-files-and-folders-in-a-folder-to-another
function rrmdir($dir) {
if (is_dir($dir)) {
$files = scandir($dir);
foreach ($files as $file)
if ($file != "." && $file != "..") rrmdir("$dir/$file");
rmdir($dir);
}
else if (file_exists($dir)) unlink($dir);
}
// Function to Copy folders and files
// @author : http://stackoverflow.com/users/1226894/baba
function rcopy($src, $dst) {
if (file_exists ( $dst ))
rrmdir ( $dst );
if (is_dir ( $src )) {
mkdir ( $dst );
$files = scandir ( $src );
foreach ( $files as $file )
if ($file != "." && $file != "..")
rcopy ( "$src/$file", "$dst/$file" );
} else if (file_exists ( $src ))
copy ( $src, $dst );
}
// Function to search and replace in a file (not case sensitive)
// @author : Erwan Dupeux-Maire
function replaceInFile($file, $search, $replace)
{
if (!is_file($file))
{
echo $file.' does not exist (replaceInFile)'."<br />\n";
return false;
}
$str = str_ireplace($search, $replace, file_get_contents($file));
return file_put_contents($file, $str);
}
// Function to search and replace in a file with regex
// @author : Erwan Dupeux-Maire
function pregReplaceInFile($file, $search, $replace)
{
if (!is_file($file))
{
echo $file.' does not exist (pregReplaceInFile)'."<br />\n";
return false;
}
$str = preg_replace($search, $replace, file_get_contents($file));
return file_put_contents($file, $str);
}
function rewritteFolderFiles($dir, $shortdir)
{
global $path, $skip, $specials;
//echo $dir."<br />\n";
if (!is_dir($dir))
{
echo $dir.' does not exist (rewritteFolderFiles)'."<br />\n";
return array();
}
// let's start the fun
$ffs = scandir($dir);
$arr = array();
foreach($ffs as $ff){
if($ff != '.' && $ff != '..' && !in_array($ff, $skip))
{
//echo $dir.'/'.$ff."<br />\n";
// Write classname
$filename = str_replace(
'.php',
'',
trim($shortdir.'/'.$ff, '/')
);
$arrPath = explode('/', $filename);
foreach($arrPath as $k => $v)
{
if (isset($specials[strtolower($v)]))
{
// in case u have some custom rewriting to do
$arrPath[$k] = $specials[strtolower($v)];
}
else
{
// just capitalize
$arrPath[$k] = ucfirst($v);
}
}
$classname = join('_',$arrPath);
//echo $classname."<br />\n";
if (is_file($dir.'/'.$ff) && strpos($ff, '.php')!==false)
{
// this array will be use to find/replace all occurences of a class name
// Explanation and limits of this regex : see #NOTE1 at the end of this file.
$arr['/(\(|\s|\t)('.$classname.')(\s)*(\(|\:\:|extends)/i'] = '$1'.$classname.'$3$4';
$key = str_replace('.php', '', $ff);
if (isset($specials[strtolower($key)]))
{
// in case u have some custom rewriting to do
$nn = $specials[strtolower($key)].'.php';
}
else
{
// just capitalize
$nn = ucfirst($ff);
}
// rename file
rename($dir.'/'.$ff, $dir.'/'.$nn);
}
if(is_dir($dir.'/'.$ff))
{
if (isset($specials[strtolower($ff)]))
{
// in case u have some custom rewriting to do
$nn = $specials[strtolower($ff)];
}
else
{
// just capitalize
$nn = ucfirst($ff);
}
// rename folder
rename($dir.'/'.$ff, $dir.'/'.$nn);
// merge without matching keys
$arr = array_merge($arr, rewritteFolderFiles($dir.'/'.$ff, trim($shortdir.'/'.$ff, '/')));
}
}
}
return $arr;
}
function replaceClassNameInFolder($dir, $arrSearch, $arrReplace)
{
global $skip;
//echo $dir."<br />\n";
if (!is_dir($dir))
{
echo $dir.' does not exist (replaceClassNameInFolder)'."<br />\n";
return array();
}
$ffs = scandir($dir);
$arr = array();
foreach($ffs as $ff){
if($ff != '.' && $ff != '..' && !in_array($ff, $skip))
{
if (is_file($dir.'/'.$ff) && strpos($ff, '.php')!==false)
{
$arr[] = $ff;
pregReplaceInFile(
$dir.'/'.$ff,
$arrSearch,
$arrReplace
);
}
if(is_dir($dir.'/'.$ff))
{
$arr[$ff] = replaceClassNameInFolder($dir.'/'.$ff, $arrSearch, $arrReplace);
}
}
}
return $arr;
}
$listOfRegexReplace = array();
foreach ($dirs as $dir)
{
echo 'Processing '.$dir."......<br />\n";
if ($dir == $path.'application')
{
// #1 manage bootstrap
// replace classes/kohana and classes/kohana/core
// by classes/Kohana and classes/Kohana/Core
replaceInFile(
$dir.'/bootstrap.php',
array(
'classes/kohana/core',
'classes/kohana'
),
array(
'classes/Kohana/Core',
'classes/Kohana'
)
);
// #2 move vendors
if (file_exists($dir.'/vendor'))
{
rcopy($dir.'/vendor', $dir.'/../vendor' );
}
// #2bis add ignore_on_delete value in cache config if exists
// (I experiment errors if ignore_on_delete is not an array in Kohana 3.3.0)
if (file_exists($dir.'/config/cache.php'))
{
pregReplaceInFile(
$dir.'/config/cache.php',
array(
'/((\'driver\')(\s)*(\=>)(\s)*(\'file\'))/i',
),
array(
'$1,
\'ignore_on_delete\' => array(
\'.gitignore\',
\'.git\',
\'.svn\'
)'
)
);
}
}
// #3 Edit the database config file, all "type" properties should be capitalised
// should be only in application/config/database.php but may also be in modules/mymodule/config/database.php
if (file_exists($dir.'/config/database.php'))
{
replaceInFile(
$dir.'/config/database.php',
array(
'\'mysql\'',
'"mysql"',
'"pdo"',
'"pdo"'
),
array(
'\'MySQL\'',
'"MySQL"',
'\'PDO\'',
'"PDO"'
)
);
}
// #4 Edit the auth config file if Auth module is used, driver name should be capitalised
// should be only in application/config/auth.php but may also be in modules/mymodule/config/auth.php
if (file_exists($dir.'/config/auth.php'))
{
replaceInFile(
$dir.'/config/auth.php',
array(
'\'orm\'',
'"orm"',
'\'file\'',
'"file"'
),
array(
'\'ORM\'',
'"ORM"',
'\'File\'',
'"File"'
)
);
}
// #5 in /classes and its subdirectories
// rename all php files to match the case sensitive standard PSR-0
$dir .= '/classes';
if (!is_dir($dir))
{
echo $dir.' does not exist'."<br />\n";
continue;
}
// Recursive function to update file and folder files and get back the list of class name to change
$listOfRegexReplace = array_merge(
$listOfRegexReplace,
rewritteFolderFiles($dir, $shortdir='')
);
}
// #10 some class names that were used with only 1 capital, are now written in full capitals (Html, Url, Http, UTF8).
// Add them to the list of class to rewrite
$listOfRegexReplace['/(Html)(\:\:)/i'] = 'HTML$2';
$listOfRegexReplace['/(Url)(\:\:)/i'] = 'URL$2';
$listOfRegexReplace['/(Http)(\:\:)/i'] = 'HTTP$2';
$listOfRegexReplace['/(Utf8)(\:\:)/i'] = 'UTF8$2';
// #11 Replace orm::factory by ORM:factory etc....
$listOfRegexReplace['/(Orm)(\:\:)/i'] = 'ORM$2';
// #12 Update Redirects (HTTP 300, 301, 302, 303, 307)
// ->request->redirect becomes ->redirect
// Request::current()->redirect becomes HTTP::redirect
// Request::initial()->redirect becomes HTTP::redirect
$listOfRegexReplace['/(\->request)(\s)*(\->redirect)(\s)*/i'] = '->redirect';
$listOfRegexReplace['/(Request\:\:current\(\))(\s)*(\->redirect)/i'] = 'HTTP::redirect';
$listOfRegexReplace['/(Request\:\:initial\(\))(\s)*(\->redirect)/i'] = 'HTTP::redirect';
// #13 Browser cache checking (ETags)
// $this->response->check_cache becomes $this->check_cache
$listOfRegexReplace['/(\->response)(\s)*(\->check_cache)(\s)*/i'] = '->check_cache';
// If we want to harmonize the "OR" case
// $listOfRegexReplace['/ or die/i'] = ' OR die';
echo '---DISPLAY ALL REPLACEMENT REGEX ---'."<br />\n";
print_r($listOfRegexReplace);
echo '------'."<br />\n";
// #14 change all class names in php filesName in /classes
echo '---PROCESSING CLASSES---'."<br />\n";
echo '> Processing change class names '.$dir."<br />\n";
foreach ($dirs as $dir)
{
$dir .= '/classes';
echo 'Processing '.$dir."......<br />\n";
echo 'This step can be long.'."<br />\n";
replaceClassNameInFolder(
$dir,
array_keys($listOfRegexReplace),// arrSearch
$listOfRegexReplace // arrSearch
);
}
if ($checkInViews)
{
// #15 change all class names in views files
echo '---PROCESSING VIEWS---'."<br />\n";
foreach ($dirs as $dir)
{
$dir .= '/views';
echo 'Processing '.$dir."......<br />\n";
echo 'This step can be long.'."<br />\n";
replaceClassNameInFolder(
$dir,
array_keys($listOfRegexReplace),// arrSearch
$listOfRegexReplace // arrSearch
);
}
}
/*
// #NOTE1
// Explaination of the regex /(\(|\s|\t)(a1)(\s)*(\(|\:\:|extends)/i
// Find classname in a file :
// - check something that start with space, tab or "("
// - followed by the name of the class (here "a1")
// - followed by one, several or no space
// - followed by "(" or ':' or "extends")
// - not cas sensitive
//
// The limit for now : can not distinct class declaration vs function declaration
// In ne following example, function a1()... should not be replace..
//
$example = ' class a1 extends a1 () {
function a1() {
}
$title=\'a1\';
$comment = "You shoudl take the highway a1! a1 is the fastest.";
a1::doIt();
$b = new a1();
$c = Helper_Example(a1::action());
// with no indent ?
a1();
// aaaa1bbbb
// a1bbbb
// aaa1
}';
$example = preg_replace(
array('/(\(|\s|\t)(a1)(\s)*(\(|\:\:|extends)/i'),
array('$1A1$3$4'),
$example
);
echo '<pre>'.($example).'</pre>';
// -----------------
// Result will be :
// -----------------
// class A1 extends A1 () {
// function A1() {
//
// }
// $title='a1';
// $comment = "You shoudl take the highway a1! a1 is the fastest.";
// A1::doIt();
// $b = new A1();
// $c = Helper_Example(A1::action());
// // with no indent ?
// A1();
// // aaaa1bbbb
// // a1bbbb
// // aaa1
// }
*/
exit();
?>
The requested URL / was not found on this server
.
- person iamjonesy; 04.09.2014