A typical Developer Blog
by Gordon Franke
Icon

How can i override user attribute in my functional test?

Some times your code depend on a user attribute, so you want set the user attribute in your functional test.

The Problem is that the doCall method in the sfBrowser class rebuild the context and in the end calls theshutdown method from user and storage object to write the session data.

So you must create your own Browser class and override the doCall function and simple move the shutdown calls to the beginning.

Browser Class:

class myBrowser extends sfBrowser
{
  /**
   * Calls a request to a uri.
   */
  protected function doCall()
  {
    // manually shutdown user to save current session data
    if (isset($this->context) AND $this->context->getUser())
    {
      $this->context->getUser()->shutdown();
      $this->context->getStorage()->shutdown();
    }
 
    // recycle our context object
    $this->context = $this->getContext(true);
 
    sfConfig::set('sf_test', true);
 
    // we register a fake rendering filter
    sfConfig::set('sf_rendering_filter', array('sfFakeRenderingFilter', null));
 
    $this->resetCurrentException();
 
    // dispatch our request
    ob_start();
    $this->context->getController()->dispatch();
    $retval = ob_get_clean();
 
    // append retval to the response content
    $this->context->getResponse()->setContent($retval);
  }
}

Test code:

include dirname(__FILE__).'/../../bootstrap/functional.php';
 
$browser = new sfTestFunctional(new myBrowser());
 
$browser->
  get('/site-one');
 
// override the session data
$browser->getUser()->setAttribute('key', $value);
 
$browser->
  get('/site-one');

Simple script to find missing translation strings

How can i use field credentials for symfony admin generator forms?

When you would restrict the display of a field or fieldset group on user credential. you must do the following

1. open the action class and add

public function preExecute()
{
  parent::preExecute();
 
  $this->configuration->setUser($this->getUser());
}

2. open the *GeneratorConfiguration class and add

protected $user;
 
public function setUser($user)
{
  $this->user = $user;
}
 
public function getUser()
{
  return $this->user;
}
 
public function getEditDisplay()
{
  $fieldsets = parent::getEditDisplay();
  if (!$this->getUser()->hasCredential('admin'))
  {
    unset(
      $fieldsets['Auth'][2], // field
      $fieldsets['Rights']   // field group
    );
  }
 
  return $fieldsets;
}
 
public function getNewDisplay()
{
  ... // see getEditDisplay
}
 
public function getFormOptions()
{
  return array('user' => $this->getUser());
}

3. last remove the fields from the form, open the *Form class and add

public function configure()
{
  ...
  if (!$this->getOption('user')->hasCredential('admin'))
  {
    unset($this['is_super_admin'], $this['groups_list'], $this['permissions_list']);
  }
  ...
}

How can i automatic add ids to my trans-unit nodes in my XML Xliff Tanslation files?

When you validate you XML Xliff file you have often the problem that a trans-unit node has no or a already existing id. So i have wrote a small script for that problem.

fix_id.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
 
$doc = new DOMDocument();
$doc->load($argv[1]);
 
$xpath = new DOMXPath($doc);
 
$query = '//trans-unit';
 
$entries = $xpath->query($query);
foreach ($entries as $i => $entry) {
    $entry->setAttribute('id', $i+1);
}
 
$doc->save($argv[1]);

Execute the following command in your symfony1 root directory ;)

for FILE in `find apps/*/i18n -name *\.xml`; do php fix_id.php $FILE; done;

How can i use embed forms or simgle form fields depend on a form field?

You have a register form with a field account_type and two embed forms Company and Address.

You want remove the embed Company form, when the field account_type is sfGuardUserProfile::TYPE_PRIVATE otherwise you want remove the embed Address form.

The solution is to override the bind method in your form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    // unset request param and validator
    if($taintedValues['account_type'] == sfGuardUserProfile::TYPE_PRIVATE)
    {
      unset(
        $taintedValues['Company'],
        $this->validatorSchema['Company']
      );
    }
    else
    {
      unset(
        $taintedValues['Address'],
        $this->validatorSchema['Address']
      );
    }
 
    parent::bind($taintedValues, $taintedFiles);
  }

How can i check the count of database queries in my unit test?

1
2
3
$manager    = new sfDatabaseManager($configuration);
$connection = $manager->getDatabase('doctrine')->getDoctrineConnection();
$connection->count();

How can i call a symfony event from doctrine model?

1
2
$dispatcher = sfProjectConfiguration::getActive()->getEventDispatcher();
$dispatcher->notify($event);

Bash script to build symfony project with sfDoctrinePlugin, sfDoctrineGuardPlugin and sfDoctrineGuardExtraPlugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/bash
 
# config
PROJECTNAME=TEST;
APPNAME=frontend;
AUTHORNAME=gfranke;
CSRFSECRET=UniqueSecret;
 
#DBDSN="sqlite:%SF_DATA_DIR%/sandbox.db";
DBDSN="mysql:host=localhost;dbname=symfony_build_with_guard";
DBUSER=root;
DBPASS="";
 
SYMFONYTAG=RELEASE_1_2_4;
 
# sfGaurdExtraPlugin don't work with propel
ORM=doctrine;
 
 
# remove existing files
rm apps/ web/ plugins/ lib/ log/ config/ cache/ data/ doc/ symfony test/ vendor/symfony_plugins/ -Rf;
 
# make vendor dir
if ! [ -d vendor ]; then
  mkdir vendor;
fi
 
# make symfony vendor dir
if ! [ -d vendor/symfony ]; then
  mkdir vendor/symfony;
fi
 
# get symfony
if ! [ -d vendor/symfony/${SYMFONYTAG}_lib ]; then
  svn export http://svn.symfony-project.com/tags/${SYMFONYTAG}/lib vendor/symfony/${SYMFONYTAG}_lib;
fi
if ! [ -d vendor/symfony/${SYMFONYTAG}_data ]; then
  svn export http://svn.symfony-project.com/tags/${SYMFONYTAG}/data vendor/symfony/${SYMFONYTAG}_data;
fi
 
# make current links for fast switch
if ! [ -L vendor/symfony/current_lib ]; then
  ln -s RELEASE_1_2_4_lib vendor/symfony/current_lib;
fi
if ! [ -L vendor/symfony/current_data ]; then
  ln -s RELEASE_1_2_4_data vendor/symfony/current_data;
fi
 
# only for build
if ! [ -L vendor/symfony/lib ]; then
  ln -s current_lib vendor/symfony/lib;
fi
if ! [ -L vendor/symfony/data ]; then
  ln -s current_data vendor/symfony/data;
fi
 
# init symfony
php vendor/symfony/data/bin/symfony generate:project $PROJECTNAME;
 
# correct symfony lib
sed "3d"  config/ProjectConfiguration.class.php2;
sed "3irequire_once dirname(__FILE__).'/../vendor/symfony/current_lib/autoload/sfCoreAutoload.class.php';"  config/ProjectConfiguration.class.php;
 
# remove build temp dirs
rm vendor/symfony/lib vendor/symfony/data;
 
# set author name
./symfony configure:author $AUTHORNAME;
 
# generate app
./symfony generate:app --escaping-strategy=on --csrf-secret=$CSRFSECRET $APPNAME;
 
# get plugins
mkdir vendor/symfony_plugins;
if [ "$ORM" = "propel" ]; then
  SVNVERSION=`svn info http://svn.symfony-project.com/plugins/sfGuardPlugin/branches/1.2/ | sed '8s/[^0-9]*//' | sed '1,7d' | sed '2,4d'`;
  svn export http://svn.symfony-project.com/plugins/sfGuardPlugin/branches/1.2/ vendor/symfony_plugins/sfGuardPlugin;
 
  ln -s sfGuardPlugin_$SVNVERSION vendor/symfony_plugins/sfGuardPlugin_current;
  ln -s ../vendor/symfony_plugins/sfGuardPlugin_current plugins/sfGuardPlugin;
 
  SVNVERSION=`svn info http://svn.symfony-project.com/plugins/sfGuardExtraPlugin/branches/1.2/ | sed '8s/[^0-9]*//' | sed '1,7d' | sed '2,4d'`;
  svn export http://svn.symfony-project.com/plugins/sfGuardExtraPlugin/branches/1.2/ vendor/symfony_plugins/sfGuardExtraPlugin;
 
  ln -s sfGuardExtraPlugin_$SVNVERSION vendor/symfony_plugins/sfGuardExtraPlugin_current;
  ln -s ../vendor/symfony_plugins/sfGuardExtraPlugin_current plugins/sfGuardExtraPlugin;
 
  # database config
  ./symfony configure:database "sqlite:%SF_DATA_DIR%/sandbox.db"
else
  sed '11s/sfDoctrinePlugin/sfPropelPlugin/'  config/ProjectConfiguration.class.php2;
  mv config/ProjectConfiguration.class.php2 config/ProjectConfiguration.class.php;
 
  SVNVERSION=`svn info http://svn.symfony-project.com/plugins/sfDoctrineGuardPlugin/branches/1.2/ | sed '8s/[^0-9]*//' | sed '1,7d' | sed '2,4d'`;
  svn export http://svn.symfony-project.com/plugins/sfDoctrineGuardPlugin/branches/1.2/ vendor/symfony_plugins/sfDoctrineGuardPlugin_$SVNVERSION;
 
  ln -s sfDoctrineGuardPlugin_$SVNVERSION vendor/symfony_plugins/sfDoctrineGuardPlugin_current;
  ln -s ../vendor/symfony_plugins/sfDoctrineGuardPlugin_current plugins/sfDoctrineGuardPlugin;
 
  SVNVERSION=`svn info http://svn.symfony-project.com/plugins/sfDoctrineGuardExtraPlugin/branches/1.2/ | sed '8s/[^0-9]*//' | sed '1,7d' | sed '2,4d'`;
  svn export http://svn.symfony-project.com/plugins/sfDoctrineGuardExtraPlugin/branches/1.2/ vendor/symfony_plugins/sfDoctrineGuardExtraPlugin_$SVNVERSION;
 
  ln -s sfDoctrineGuardExtraPlugin_$SVNVERSION vendor/symfony_plugins/sfDoctrineGuardExtraPlugin_current;
  ln -s ../vendor/symfony_plugins/sfDoctrineGuardExtraPlugin_current plugins/sfDoctrineGuardExtraPlugin;
 
  # database config
  ./symfony configure:database --name=doctrine --class=sfDoctrineDatabase $DBDSN $DBUSER $DBPASS
 
  # remove propel connection
  sed '2,6s/propel/doctrine/'  config/databases.yml2;
  mv config/databases.yml2 config/databases.yml;
fi
 
# enabled modules and change login module and action
sed "31i    # Activated modules from plugins or from the symfony coren    enabled_modules: [default, sfGuardAuth, sfGuardRegister, sfGuardForgotPassword]n"  apps/frontend/config/settings.yml2;
mv apps/frontend/config/settings.yml2 apps/frontend/config/settings.yml;
 
# deactivate guard routes
sed "2d"  apps/frontend/config/app.yml2;
echo "all:n  sf_guard_plugin:n    routes_register: falsen" >> apps/frontend/config/app.yml2;
mv apps/frontend/config/app.yml2 apps/frontend/config/app.yml;
 
# insert guard routes
sed "6isf_guard_signin:n  url:   /loginn  param: { module: sfGuardAuth, action: signin }nnsf_guard_signout:n  url:   /logoutn  param: { module: sfGuardAuth, action: signout }n"  apps/frontend/config/routing.yml2;
mv apps/frontend/config/routing.yml2 apps/frontend/config/routing.yml;
 
# create db file
touch data/sandbox.db
chmod 777 data
chmod 777 data/sandbox.db
 
# extends sfGuardSecurityUser
sed '3s/sfBasicSecurityUser/sfGuardSecurityUser/'  apps/frontend/lib/myUser.class.php2;
mv apps/frontend/lib/myUser.class.php2 apps/frontend/lib/myUser.class.php;
 
# clear cache
./symfony cc
 
# fix permissions
./symfony fix-perms
 
# build db model filter and forms
if [ "$ORM" = "propel" ]; then
  ./symfony propel:build-all --no-confirmation
else
  ./symfony doctrine:build-model
 
  echo "hasColumn('email', 'string', 80, array('notnull' => true, 'unique' => true));
  }
 
  public function getEmailAddress()
  {
    return $this->email;
  }
 
  public function setEmailAddress($email)
  {
    $this->email = $email;
  }
}" > lib/model/doctrine/sfDoctrineGuardPlugin/sfGuardUser.class.php;
 
  echo "from('sfGuardUser u')->where( '(u.username = ? OR u.email = ?) AND u.is_active = ?', array( $usernameOrEmail, $usernameOrEmail, $isActive ) )->execute()->getFirst();
  }
}
" > lib/model/doctrine/sfDoctrineGuardPlugin/sfGuardUserTable.class.php;
 
  # schema to inndb
  echo "---
options:
  type: INNODB
"  > config/doctrine/schema.yml
 
  # cleanup
  rm config/schema.yml config/propel.ini
 
  ./symfony doctrine:build-all-reload --no-confirmation
fi
 
# publish assets don't use publish-assets symlink must go to current link
rm web/sfPropelPlugin web/sfProtoculousPlugin;
ln -s ../vendor/symfony/current_data/web/sf/ web/sf;
ln -s ../vendor/symfony/current_lib/plugins/sfProtoculousPlugin/web web/sfProtoculousPlugin;
if [ "$ORM" = "propel" ]; then
  ln -s ../vendor/symfony/current_lib/plugins/sfPropelPlugin/web web/sfPropelPlugin;
else
  ln -s ../vendor/symfony/current_lib/plugins/sfDoctrinePlugin/web web/sfDoctrinePlugin;
fi
 
# clear cache
./symfony cc

How can i mark all required form fields with a *?

create file lib/gfFormHerlp.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
 
/**
 * Some usefull form helper
 *
 * @package    symfony
 * @subpackage helper
 * @author     Gordon Franke <gfranke@nevalon.de>
 * @link       http://www.nevalon.de
 */
class gfFormHelper
{
  /**
   * Add * to required field labels
   *
   * @param sfForm $form
   * @param string $symbol
   * @param string $title
   *
   * @return void
   */
  public static function addRequiredToLabel(sfForm $form, $symbol = '*', $title = 'This field is mandatory.')
  {
    $widgetSchema = $form->getWidgetSchema();
    $validatorSchema = $form->getValidatorSchema();
 
    foreach($form->getFormFieldSchema()->getWidget()->getFields() as $key => $object)
    {
      $label = $form->getFormFieldSchema()->offsetGet($key)->renderLabelName();
      if(isset($validatorSchema[$key]) and $validatorSchema[$key]->getOption('required') == true) {
        $label .= '<sup title="' . $widgetSchema->getFormFormatter()->translate($title) . '">' . $symbol . '</sup>';
      }
      $widgetSchema->setLabel($key, $label);
    }
  }
}

add at the end of your form setup or better when you have subforms into the configure method this line

1
gfFormHelper::addRequiredToLabel($this);

How can i unit test my own User class functions?

Use this in your testcode to create the user object

1
2
3
4
5
6
7
8
$_SERVER['session_id'] = 'test';
 
$dispatcher = new sfEventDispatcher();
$sessionPath = sfToolkit::getTmpDir().'/sessions_'.rand(11111, 99999);
$storage = new sfSessionTestStorage(array('session_path' => $sessionPath));
 
$myUser = new myUser($dispatcher, $storage);
$myUser->setAttribute('user_id', 1, 'sfGuardSecurityUser');