A typical Developer Blog
by Gordon Franke
Icon

Wie kann ich user attribute in meinem Functional test überschreiben?

Manch mal hängt der code von einem user attribute ab, also will man das user attribute in seinem functional test überschreiben.

Das Problem ist das die doCall Methode in der sfBrowser Klasse den context neuerstellt und am ende die shutdown Methode für den user und die storage Objekte , zum schreiben der Session daten, aufruft.

Also muss man seine eigene Browser Klasse erstellen und die doCall Methode überschreiben und den code an den Anfang verschieben.

Browser Klasse:

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');

Simples skript zum finden fehlender Übersetzungen

Wie nutze ich die Rechteverwaltung in symfony admin generator formularen?

Wenn du bestimmt Felder oder Feldgruppen entfernen möchtest, wenn ein Benutzer nicht die dafür erforderlichen Rechte besitzt, musst du folgendes tun:

1. öffne deine action Klasse und füge folgendes ein:

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

2. öffne die *GeneratorConfiguration Klasse und füge folgendes ein:

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. zuletzt öffne die *Form Klasse und füge folgendes ein:

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

Wie kann ich automatisch ids, für meine trans-units, in meinen XML Xliff Übersetzungs Dateien vergeben?

Wer seine XML Xliff Dateien gegen die dtd validiert hat oft das Problem, dass die einzelnen trans-unit Nodes keine oder eine bereits existierende id aufweisen. Um dieses Problem zu lösen hab ich mir ein kleines Skript gebaut.

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]);

Im symfony1 Hauptverzeichnis nun folgenden Befehl absetzen ;)

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

Wie kann ich eingebettete Formulare oder einzelne Felder abhängig von einem Formularfeld verwenden?

Du hast ein Registrierungsformular mit einem Feld account_type und zwei eingebetteten Formularen Company und Address.

Du willst das eingebettete Company Formular entfernen, wenn das Feld account_type sfGuardUserProfile::TYPE_PRIVATE entspricht, andernfalls willst du das eingebettete Address Formular entfernen.

Die Lösung ist die bind Methode in deinem Formular zu überschreiben.

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);
  }

Wie kann ich die Anzahl der Datenbank Queries in meinem Unit Test überprüfen?

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

Wie kann ich ein symfony event aus dem doctrine model herraus aufrufen?

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

Bash Skript zum Erstellen eines Symfony Projekts mit sfDoctrinePlugin, sfDoctrineGuardPlugin und 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

Wie kann ich alle Formular Pflichtfelder mit einem * kennzeichnen?

Erstelle die Datei 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);
    }
  }
}

Füge folgendes am ende deiner Formular in der setup oder besser wenn du Unterformulare hast in der configure Methode ein

1
gfFormHelper::addRequiredToLabel($this);

Wie kann ich meine eigenen User Funktionen Unit testen?

Benutze dies in deinem Testcode um das User Objekt zu erstellen

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');