![]() |
|
Snippets |
|
or apply transformation on sfGuard tables into your main schema
When you generate a schema with sf_guard tables from your main database with the following command, the schema contains all the tables included the sf_guard tables (it's normal).
symfony propel-build-schema xml
Then after, when you build the model classes, the sfGuardPlugin classes have a wrong name and are in a wrong place (lib/). There is a post on this problem, how to correctly use propel-build-schema after sfGuardPlugin installation?
symfony propel-build-model
To correct the schema, apply the transformation on the XML schema after the schema generation :
symfony transform-schema-sfguard xml
The script add in the schema for all sf_guard_* tables, the package and the phpName with the camelcase used by the plugin.
Also you have to switch off the schema in the plugin to don't have twice declaration :
mv ./plugins/sfGuardPlugin/config/schema.yml ./plugins/sfGuardPlugin/config/schema.yml.off
The script: myPakeTransformSchemaSfguard.php
pake_desc( 'apply transformation on sfGuard tables into your main schema' ); pake_task( 'transform-schema-sfguard', 'project_exists' ); function run_transform_schema_sfguard($task, $args) { // Check params // -- missing params ? if ( !count($args) > 1 ) { throw new Exception("You must provide a transformation to apply.\nsymfony transform-schema-sfguard\nsymfony transform-schema-sfguard xml"); } // -- schema exists ? if ($args[0] == 'xml') { $schema_filename = sprintf( '%s/schema.xml', sfConfig::get('sf_config_dir') ); if ( !file_exists($schema_filename) ) { throw new Exception( "Missing schema.xml" ); } } else { $schema_filename = sprintf( '%s/schema.yml', sfConfig::get('sf_config_dir') ); if ( !file_exists($schema_filename) ) { throw new Exception( "Missing schema.yml (not yet implemented)" ); } else { throw new Exception( "schema.yml not yet implemented" ); } } // Backup schema //pake_copy( $schema_filename, $schema_filename . '.previous', array('override' => true) ); if ($args[0] == 'xml') { $handle = fopen($schema_filename, "r"); // get the entire file in $contents $contents = ''; while (!feof($handle)) { $contents.= fread($handle, 8192); } fclose($handle); $num = preg_match_all('/<table(.*)>/i', $contents, $matches); // each table definition found foreach ($matches[0] as $val) { if (!preg_match('/package|phpName/i', $val) && preg_match('/name="(sf_guard_.+?)"/i', $val, $val_matches)) { $table_name = $val_matches[1]; //$php_name = sfInflector::camelize($val_matches[1]); $php_name = sfToolkit::pregtr($val_matches[1], array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(_)(.)/e' => "strtoupper('\\2')", '/(^)(.)/e' => "strtolower('\\2')")); $pattern = '/(<table.*)(name="'.$table_name.'")(.*>)/i'; $replace = '$1$2 package="plugins.sfGuardPlugin.lib.model" phpName="'.$php_name.'" $3'; $contents = preg_replace($pattern, $replace, $contents, 1, $count); pake_echo($table_name); } } // write the result $handle = fopen($schema_filename, "w+"); fwrite($handle, $contents); fclose($handle); } }
Put the myPakeTransformSchemaSfguard.php script into data/tasks directory
mv ./plugins/sfGuardPlugin/config/schema.yml ./plugins/sfGuardPlugin/config/schema.yml.off symfony propel-build-schema xml symfony transform-schema-sfguard xml symfony propel-build-model
The sfDimensionsPlugin ( http://trac.symfony-project.com/wiki/sfDimensionsPlugin )
Allows you to use different configurations in your application (for example, themes and culture).
However, it requires a few symfony core changes, which makes installation a little more difficult than traditional plugins - and upgrading the core can cause you to lose the changes, thus having to "reinstall".
The following pake tasks:
Note: remember to run uninstall before upgrading the symfony core file set.
Future development could include:
While the need for core changes to Symfony are rare, there are times when additional functionality (like this plugin provides) do require such changes (usually minimal).
Hopefully a more generic tool can be written at some point to manage generic patch sets.
In the meantime, this pake task can save some frustration.
<?php /*EVOLUTION*/ pake_desc('install dimensions plugin (modifies core)'); pake_task('dimensions-install', 'project_exists'); pake_desc('uninstall dimensions plugin (unmodifies core)'); pake_task('dimensions-uninstall', 'project_exists'); function run_dimensions_install($task, $args) { global $sf_symfony_lib_dir, $sf_symfony_data_dir; $here = dirname(__FILE__); $home = "$here/../../../.."; $backup_dir = $here . "/../dimension-backup"; $dim_dir = "$home/plugins/sfDimensionsPlugin"; if (file_exists($backup_dir)) { pake_echo_action('plugin', "Failure: backup exists: $backup_dir"); exit(1); } pake_echo_action('plugin', "Backing up files"); mkdir($backup_dir); copy($sf_symfony_lib_dir . "/config/sfLoader.class.php", "$backup_dir/sfLoader.class.php"); copy($sf_symfony_data_dir . "/config/constants.php", "$backup_dir/constants.php"); copy("$home/config/config.php", "$backup_dir/config.php"); pake_echo_action('plugin', "Modifying Core"); copy("$dim_dir/lib/config/sfLoader.class.php", $sf_symfony_lib_dir . "/config/sfLoader.class.php"); copy("$dim_dir/config/constants.php", $sf_symfony_data_dir . "/config/constants.php"); pake_echo_action('plugin', "Dimensions installed"); } function run_dimensions_uninstall($task, $args) { global $sf_symfony_lib_dir, $sf_symfony_data_dir; $here = dirname(__FILE__); $home = "$here/../../../.."; $backup_dir = $here . "/../dimension-backup"; $dim_dir = "$home/plugins/sfDimensionsPlugin"; pake_echo_action('plugin', "restoring files"); $time = time(); copy("$home/config/config.php", "$home/$time.config.php"); copy("$backup_dir/config.php", "$home/config/config.php"); copy("$backup_dir/sfLoader.class.php", $sf_symfony_lib_dir . "/config/sfLoader.class.php"); copy("$backup_dir/constants.php", $sf_symfony_data_dir . "/config/constants.php"); pake_echo_action('plugin', "removing backup directory and files"); _recursive_remove_directory($backup_dir); }
Sometimes we need more or different folders to be fix-permed. Mine is an easy hack, but having symfony freezed its not that ugly. The file is: /data/symfony/tasks/sfPakeMisc.php (line 41++)
function run_fix_perms($task, $args) { $sf_root_dir = sfConfig::get('sf_root_dir'); // just added this line for a folder pake_chmod("batch/any/folder", $sf_root_dir, 0777); pake_chmod(sfConfig::get('sf_cache_dir_name'), $sf_root_dir, 0777); pake_chmod(sfConfig::get('sf_log_dir_name'), $sf_root_dir, 0777); pake_chmod(sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir_name'), $sf_root_dir, 0777); pake_chmod('symfony', $sf_root_dir, 0777); $dirs = array( // and this for chmoding files inside: sfConfig::get('sf_root_dir') . "/batch/any/folder", sfConfig::get('sf_cache_dir_name'), sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir_name'), sfConfig::get('sf_log_dir_name')); $dir_finder = pakeFinder::type('dir')->ignore_version_control(); $file_finder = pakeFinder::type('file')->ignore_version_control(); foreach ($dirs as $dir) { pake_chmod($dir_finder, $dir, 0777); pake_chmod($file_finder, $dir, 0666); } }
Perhaps somebody uses a more elegant way ... ;)
Accessing just via:
> symfony fix-perms
Problem:
Mysql produce TINYINT fields because BOOLEAN is just a synonym for TINYINT. And if you have TINYINT fields with value 0 or 1 (like BOOLEAN fields) in your database and use command symfony propel-build-schema to generate schema, you will have one problem with admin generator, because it will produse TINYINT fields as text form fields with value - 0 or 1, not as checkboxes. Admin generator needs BOOLEAN fields in schema to produse checkboxes.
Solution:
Solution to automate transformation field type tinyint to boolean where field name prefix is "is_".
sfPakeTransformTinyint.php
<?php pake_desc( 'apply tinyint-boolean transformation to your data model' ); pake_task( 'transform-schema-tinyint', 'project_exists' ); function run_transform_schema_tinyint( $task, $args ) { // Check params // -- missing params ? if ( !count($args) ) { throw new Exception( 'You must provide a transformation to apply.' ); } // -- schema exists ? $schema_filename = sprintf( '%s/schema.xml', sfConfig::get('sf_config_dir') ); if ( !file_exists($schema_filename) ) { throw new Exception( "Missing schema.xml" ); } // Backup schema pake_copy( $schema_filename, $schema_filename . '.previous', array('override' => true) ); //do hard work - tinyint->boolean if ($args[0] == 'do') { $handle = fopen($schema_filename, "r"); $contents = ''; while (!feof($handle)) { $contents .= fread($handle, 8192); } fclose($handle); $contents = preg_replace('/(name="is_.*?type=")TINYINT"/i','$1BOOLEAN"',$contents); $handle = fopen($schema_filename, "w+"); fwrite($handle, $contents); fclose($handle); } //undo hard work - boolean->tinyint if ($args[0] == 'undo') { $handle = fopen($schema_filename, "r"); $contents = ''; while (!feof($handle)) { $contents .= fread($handle, 8192); } fclose($handle); $contents = preg_replace('/(name="is_.*?type=")BOOLEAN"/i','$1TINYINT"',$contents); $handle = fopen($schema_filename, "w+"); fwrite($handle, $contents); fclose($handle); } } ?>
copy this code and drop it as new file in SF_DATA_DIR/tasks/ use command: symfony transform-schema-tinyint do to change tinyint to boolean, where field name with "is_" prefix, than rebuild your model with propel-build-model, clear cache, and use admin generator with checkboxes.
If something going wrong, do this command to undo changes in your model:
symfony transform-schema-tinyint undo (to change boolean to tinyint, where field name with "is_" prefix)
or you may use schema.xml.previous <- this is your schema before transformation
We wanted to use a 'propel-insert-sql' in our acceptance tests suite to clear DB before every test reducing interferences. We all learned here http://www.symfony-project.com/snippets/snippet/16 how to call a Pake task from our PHP code. To get a quiet 'propel-insert-sql' task letting 'test' task be verbose and reporting test results we must add a method to the pakeTask class in pakeTask.class.php file:
public function setVerbose() { $this->verbose = false; }
and edit sfPakePropel.php file to make 'propel-insert-sql' task quiet:
function run_propel_insert_sql($task, $args) { $task->setVerbose(); _call_phing($task, 'insert-sql'); }
This way we have a lot quiter acceptance test suite and a clean DB whenever we want.
I find boring to wait to run all the tests while I'm focusing on a single one or few ones. Thus I decided to hack pake simpletest task to accept test group selection.
1st step:
In your Pake tasks folder (eg.: /usr/share/pear/pake/tasks) edit the pakeSimpletestTask.class.php file
public static function call_simpletest($task, $type = 'text', $dirs = array(), $test_file = null)
and add this few lines replacing the single line 48
if (!$test_file) { $files = pakeFinder::type('file')->name('*Test.php')->in($test_dirs); } else { $files = pakeFinder::type('file')->name($test_file)->in($test_dirs); }
This way you are making your pake test task able to accept "hints" about which file to load in the test folder.
2nd step:
Open the sfPakeTest.php file in your symfony/tasks folder and do the following: Add
$test_file = null; if (count($args) > 1) { $test_file = $args[1]; }
at line 14, then change last line into
pakeSimpletestTask::call_simpletest($task, 'text', $dirs_to_test, $test_file);
That's all.
Now you can launch symfony test <app_name> <test_filename> and have this only executed with no loss of time. You can even use wildcards!!! For example: symfont test myportal *ValidatorTest.php It will execute all the tests named with that pattern in your test/myportal folder.
Super confortable testing at last! Test driven programming requires very flexible test groups approach and this could be a small contribution. Hope it helps. Bye!
You can mimick the call of the symfony command line via a PHP script called from the browser. For instance, for the command
$ symfony clear-cache
...create a webclearcache.php file in your myproject/web/ directory (where the index.php is) with the following content:
<?php // as we are in the web/ dir, we need to go up one level to get to the project root chdir(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'); include_once('/lib/symfony/pake/bin/pake.php'); $pake = pakeApp::get_instance(); try { $ret = $pake->run('/data/symfony/bin/pakefile.php', 'clear-cache'); } catch (pakeException $e) { print "<strong>ERROR</strong>: ".$e->getMessage(); } ?>
You can now clear the cache by calling:
http://myapp.example.com/webclearcache.php
Note: Beware that by letting web access to administration tools, you can compromise the safety of your website.
If you have not a PEAR symfony installation, but rather a couple of symlinks in the lib/ and data/ directories of your project, and if you didn't define shortcuts for the symfony command, you'll have to call manually pake (the tool used for the command line interface) and pass it the right pakefile (the configuration file containing the symfony commands).
This can be done that way:
$ cd /home/production/myproject
$ php /path/to/pake.php -f data/symfony/bin/pakefile.php propel-build-model
In systems where both PHP4 and PHP5 are installed, you probably need to use a PHP5 specific command:
$ php5 /usr/local/php5.1.2/lib/php/pake.php -f data/symfony/bin/pakefile.php propel-build-model