<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Latest snippets</title>
  <link rel="alternate" href="http://snippets.strangebuzz.com/"></link>
  <id>http://snippets.strangebuzz.com/</id>
  <updated>2007-04-05T23:01:46Z</updated>
  <author>
    <name>Symfony</name>
    <author_email>noreply@symfony-project.com</author_email>
  </author>
<entry>
  <title>[Pear] Display source code of all php files of a package</title>
  <link href="http://snippets.strangebuzz.com/snippet/12"></link>
  <updated>2007-04-05T23:01:46Z</updated>
  <id>12</id>
  <summary type="html">You will need the original __package.xml__, it can be usefull for package maintainers to provide source of their package as i did [for my PHP_Debug pkg](http://phpdebug.coilblog.com/PHP_Debug_Sources.php)

[code php]
// file
function showSource($dir, $file)
{
    $path = $dir. $file;
    print('&lt;div&gt;');
    print('&lt;h1&gt;'. $path. '&lt;/h1&gt;');
    highlight_file($path);
    print('&lt;/div&gt;'. &quot;\n&quot;);
}

// Dir 
function parseDir($dir, $parent)
{
    $path = $parent. ($dir['name'] != '/' ? $dir['name']. '/' : '');
    foreach($dir-&gt;file as $file) {
        if (in_array($file['role'], array('test', 'php'))) {
            showSource($path, $file['name']);
        }
    }	
    foreach($dir-&gt;dir as $child) {
        parseDir($child, $path);
    }
    return;
}

$package = simplexml_load_file('package.xml');
$dir = '';
parseDir($package-&gt;contents-&gt;dir, $dir);
[/code]</summary>
</entry>
<entry>
  <title>[Symfony] Keep page number after update in an admin generator list</title>
  <link href="http://snippets.strangebuzz.com/snippet/11"></link>
  <updated>2007-03-13T17:22:31Z</updated>
  <id>11</id>
  <summary type="html">Here is a small patch for the __action.class__ of the admin generator theme :

in __executeList()__ function replace :

[code php]
$this-&gt;pager-&gt;setPage($this-&gt;getRequestParameter('page', 1));
[/code]

by :

[code]
$this-&gt;pager-&gt;setPage($this-&gt;getRequestParameter('page', $this-&gt;getUser()-&gt;getAttribute('page', 1, 'sf_admin/&lt;?php echo $this-&gt;getSingularName() ?&gt;')));
[/code]

in __executeList()__ function add at the end :

[code php]
    // Save page
    if ($this-&gt;getRequestParameter('page')) {
        $this-&gt;getUser()-&gt;setAttribute('page', $this-&gt;getRequestParameter('page'), 'sf_admin/&lt;?php echo $this-&gt;getSingularName() ?&gt;');
    }
[/code]

in the __process()__ function, before the 1st __removeNamespace__ statement add :

[code php]
$this-&gt;getUser()-&gt;getAttributeHolder()-&gt;removeNamespace('sf_admin/&lt;?php echo $this-&gt;getSingularName() ?&gt;');
[/code]

[Original forum post](http://www.symfony-project.com/forum/index.php/m/16113/#msg_%2016113)
</summary>
</entry>
<entry>
  <title>[Symfony] Fichier typique .htaccess pour OVH</title>
  <link href="http://snippets.strangebuzz.com/snippet/10"></link>
  <updated>2007-03-03T13:11:59Z</updated>
  <id>10</id>
  <summary type="html">**[EN]** This is a typical .htaccess file for the french hoster [OVH](http://www.ovh.com) **(1)**

**[FR]** Voici un fichier .htaccess typique pour faire fonctionner une application Symfony sur un hébergement mutualisé [OVH](http://www.ovh.com).

**(1)**
[code]
SetEnv PHP_VER 5
SetEnv REGISTER_GLOBALS 0
SetEnv MAGIC_QUOTES 0
mod_gzip_on Off

Options +FollowSymLinks +ExecCGI

&lt;IfModule mod_rewrite.c&gt;
  RewriteEngine On

  # we skip all files with .something
  RewriteCond %{REQUEST_URI} \..+$
  RewriteCond %{REQUEST_URI} !\.html$
  RewriteCond %{REQUEST_URI} !\.php
  #RewriteCond %{REQUEST_URI} !\.php
  RewriteRule .* - [L]

  # we check if the .html version is here (caching)
  RewriteRule ^$ /index.html [QSA]
  RewriteRule ^([^.]+)$ /$1.html [QSA]
  RewriteCond %{REQUEST_FILENAME} !-f

  # no, so we redirect to our front web controller
  RewriteRule ^(.*)$ /index.php [QSA,L]

  # hidden frontoffice controller
  RewriteRule ^index\.php/(.*)$ /index.php [QSA,L]

  # fo controllers
  RewriteRule ^frontend\.php/(.*)$ /frontend.php [QSA,L]
  RewriteRule ^frontend_dev\.php/(.*)$ /frontend_dev.php [QSA,L]

&lt;/IfModule&gt;

# big crash from our front web controller
ErrorDocument 500 &quot;&lt;h2&gt;Application error&lt;/h2&gt;symfony application failed to start properly&quot;
[/code]</summary>
</entry>
<entry>
  <title>[Symfony] Joomla to Symfony mini-bridge [EN]</title>
  <link href="http://snippets.strangebuzz.com/snippet/9"></link>
  <updated>2007-02-27T12:45:58Z</updated>
  <id>9</id>
  <summary type="html">[Fr] Traduction à venir.

# This tutorial is for the 0.7.0 version please check the [Symfony Wiki](http://www.symfony-project.com/trac/wiki/sfJoomlaBridgePlugin) for 0.8.0 doc until i can update this tutorial.

## Intro

Well, in fact i have taken the idea from what has already been done with cakePHP, you can find the original blog articles here **(1)** and thanks to the authors for the work. Now a full project for this purpose is available for cakePHP it is called [Jake](http://dev.sypad.com/projects/jake)

**(1)**

  * [http://www.gigapromoters.com/blog/2007/01/28/joining-powers-of-two-great-systems-joomla-and-cakephp](http://www.gigapromoters.com/blog/2007/01/28/joining-powers-of-two-great-systems-joomla-and-cakephp)
  * [http://www.gigapromoters.com/blog/2007/02/13/finally-a-practical-solution-joomla-with-cakephp-together-jake/](http://www.gigapromoters.com/blog/2007/02/13/finally-a-practical-solution-joomla-with-cakephp-together-jake/)

## 1 - Installation

Versions used :

  * **Symfony 1.0.0 stable**
  * **Joomla 1.0.12 stable**

  * Install the plugin (check [the plugin Wiki page in Symfony ](http://www.symfony-project.com/trac/wiki/sfJoomlaBridgePlugin))

  * or [Download here](http://snippets.coilblog.com/download/sfJoomlaBridgePlugin-0.7.0.tgz)
    * Copy it in the plugins folder (i'll make a full symfony package later)
    * Copy the plugin web directory in the /web directory of your project

Now you must have a **sfJoomlaBridge** dir in your plugins dir and a **com_symfony** dir in **/web/components**

The Symfony application is built as usual and the Joomla installation must be achieved in the **/web** of the Symfony project.

## 2 - Configuration

### Joomla component

Open **symfony.html.php**, line 8 modify the name of Symfony controller file (frontoffice.php by default). Take care to use a production controller, because we should't have any debug information

Un-comment line 34 with **file\_get\_contents** if you don't have curl installed on you web server, and comment the curl related line above.

In __index.php__ of Joomla 

before (near line 114)

[code php]
// mainframe is an API workhorse, lots of 'core' interaction routines
$mainframe = new mosMainFrame( $database, $option, '.' );
$mainframe-&gt;initSession();
[/code]

add

[code php]
//Before Joomla initialize its mainframe, lets play…
// check missing component — added before $mainframe is being initialized
//##########################
if (!file_exists($mosConfig_absolute_path . '/components/'. $option )) { 
    $option = 'com_symfony';  
    //set component to com_cake if a controller is not found.
}
[/code]

### Symfony

Clear the cache

[code bash]
&gt; symfony clear cc
[/code]

There is nothing really specific except the new link helper to use in the templates. To use the Joomla helpers :

[code php]
&lt;?php use_helper('Joomla'); ?&gt;
[/code]

You can also modify the index file of Joomla application in **plugins/sfJoomlaBridge/config/config.php**

## 3 - Use

### Creation of Symfony page

We are going to do a page (module/action) whitch will be called by Joomla with the help of its new component.

&lt;br/&gt;
#### sf actions creation

Nous are going to create 2 actions, 1 basic (static content) and one with the users list of Joomla administration

**index/actions/actions.class.php**
[code php]
    /**
     * Executes index action
     */
    public function executeIndex()
    {
    }

    /**
     * Test Joomla/Symfony integration
     * 
     * @author lvernet
     * @since  26 feb 2007
     */
    public function executeUsers()
    {
    	$this-&gt;users = JosUsersPeer::doSelect(new Criteria());
    }
[/code]
 
&lt;br/&gt;
#### sf view creation

The plugin introduce a new helper **link\_to\_joomla** that allows to do link to others symfony pages but with staying in the Joomla application.

**templates/usersSuccess.php**
[code php]

&lt;?php use_helper('Joomla'); ?&gt;

&lt;h1&gt;Joomla Users list&lt;/h1&gt;
&lt;p&gt;This list is retrieved with the help of the ORM of Symfony&lt;/p&gt;
&lt;br/&gt;

&lt;?php if ($users): ?&gt;

&lt;table class=&quot;contenttoc&quot;&gt;
    &lt;thead&gt;
        &lt;th&gt;Id&lt;/th&gt;
        &lt;th&gt;Name&lt;/th&gt;
        &lt;th&gt;User name&lt;/th&gt;
    &lt;/thead&gt;            
&lt;?php foreach($users as $user): ?&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;?php echo $user-&gt;getId(); ?&gt;&lt;/td&gt;
        &lt;td&gt;&lt;?php echo $user-&gt;getName(); ?&gt;&lt;/td&gt;
        &lt;td&gt;&lt;?php echo $user-&gt;getUsername(); ?&gt;&lt;/td&gt;
    &lt;/tr&gt;            
&lt;?php endforeach; ?&gt;
&lt;/table&gt;
&lt;?php endif; ?&gt;

&lt;br/&gt;
&lt;?php echo link_to_joomla('Back to index', 'index/index', array('query_string' =&gt; 'param1=chat&amp;param2=rat')); ?&gt;
[/code]


**templates/indexSuccess.php**
[code php]

&lt;?php use_helper('Joomla'); ?&gt;

&lt;h1&gt;This content is provided through Symfony framework.&lt;/h1&gt;

&lt;?php echo image_tag('powered_by.png') ?&gt; &amp;&amp;
&lt;?php echo image_tag('http://www.symfony-project.com/images/symfony_logo.gif') ?&gt;

&lt;br/&gt;
&lt;?php echo link_to_joomla('Users list', 'index/users'); ?&gt;
[/code]

This helper take standar **link_to()** arguments but you can't use routing system (indeed that has no interest here in this context) and the parameters of the link must be passed using the GET method (with the 'query_string' option) Here we are calling a sf page identified by the module **index** and action **index**, moreover 2 parameters are passed to the action.

Now we must desactivate the view's layout, because we don't want it as we will use the one of Joomla.

In **index/config/view.yml** :
[code]
indexSuccess:
  has_layout:    off

usersSuccess:
  has_layout:    off
[/code]

&lt;br/&gt;
#### Call and test it in Joomla

We can now call our sf pages in Joomla, link are formed as following : index.php?option=index&amp;task=users

  * **option** : identify the sf module name
  * **task** : identify the sf module action
  * After that you can add all the paremeters you want, they will be available to Symfony.

Go to the url: http://projectroot/index.php?option=index&amp;task=users, the users list is displayed and you have a link to go to the index page (link created with the joomla helper)

__/!\\ Be carefull, the option param should not match the name of a Joomla component /!\\__

## 4 - Demo

[See the plugin in action here](http://joomla.coilblog.com/index.php)

## 5 - Conclusion

I made this quiet quickly, of course there are lot of things to do to have a perfect integration as the Jake project does it for cakePHP. If someone is interested, feel free to take the code and contribute, it would be nice. **COil** :)

</summary>
</entry>
<entry>
  <title>[Symfony] sync exclude list</title>
  <link href="http://snippets.strangebuzz.com/snippet/8"></link>
  <updated>2007-02-10T16:54:58Z</updated>
  <id>8</id>
  <summary type="html">__[Fr]__ Dans la [doc](http://www.symfony-project.com/book/trunk/16-Application-Management-Tools#Deploying%20Applications) j'ai trouvé la liste de fichier à exclure assez peu fournie. Voici une liste plus complète à personnaliser : __(1)__

***

__[En]__ In the  [documentation](http://www.symfony-project.com/book/trunk/16-Application-Management-Tools#Deploying%20Applications) i found the exclude file list quiet small. Here is a more consistant one to customize : __(1)__

[code text]
.svn
.CVS
.project
.settings
.settings/*
symfony

/cache/*

/config/config.php
/config/propel.ini
/config/databases.yml
/config/properties.ini

/doc/*

/log/*

/lib/symfony
/lib/symfony/*

/data/symfony
/data/symfony/*

/plugins/.channels/
/plugins/.registry/
/plugins/.depdb
/plugins/.depdblock
/plugins/.filemap
/plugins/.lock
/plugins/.pearrc

/stats/*

/test/*

/web/.htaccess
/web/frontend_dev.php
/web/backend_dev.php
/web/phpinfo.php
/web/test.php
/web/uploads/*
/web/sf
/web/sf/*
[/code]</summary>
</entry>
<entry>
  <title>[Symfony] Fix perms of a project after a &gt; symfony sync</title>
  <link href="http://snippets.strangebuzz.com/snippet/7"></link>
  <updated>2007-02-10T16:21:25Z</updated>
  <id>7</id>
  <summary type="html">__[En]__ After having tested the sync command of Symfony i realised that all the permissions of my __/web__ directory were wrong. The symfony command : __(1)__

It supposed to correct this, unfortunately the command line php version is 4 on my shared hosting, so i had to to it by hand with a little unix script : __(2)__

There are lot and different problems on shared testing as can can see in this [forum thread](http://www.symfony-project.com/forum/index.php/m/17866/)

***

__[Fr]__ Apres avoir testé la commande de synchronisation de symfony, plus rien ne marchait... En fait c'est du au fait que tous mes fichiers de __/web__ n'avait plus les bonnes permission et il fallait les repasser en __755__. Une commande symfony permet de regler ce problème : __(1)__

[code bash]
&gt; symfony fix-perms 
[/code]

Néanmoins la version de PHP sur mon server mutualisé est la 4 ! le script symfony ne peut donc pas fonctionner... On peut néanmoins contourner en executant la commande suivante : __(2)__

[code bash]
&gt; symfony cc
&gt; find . -type f | xargs chmod 644
&gt; find . -type d | xargs chmod 755
[/code]

La joie des serveurs mutualisés avec Symfony, ce n'est pas toujours de tout repos comme le montre ce [post sur le forum](http://www.symfony-project.com/forum/index.php/m/17866/)</summary>
</entry>
<entry>
  <title>[Symfony] Delete Propel classes comments (0.6.3)</title>
  <link href="http://snippets.strangebuzz.com/snippet/6"></link>
  <updated>2007-02-02T21:26:00Z</updated>
  <id>6</id>
  <summary type="html">**[Fr]** Attention ce snippet n'est vraiment utile que pour la version **0.6.3** de Symfony, la version 1.0.0 intégrant déja une fonctionnalité de suppression des commentaires propel. Il suffit d'ajout dans votre **propel.ini** 

__(1)__ 
[code ini]
propel.builder.addIncludes = false
propel.builder.addComments = false
[/code]

Voici un batch pour supprimmer les commentaires des classes générées par Propel. On peut gagner entre 5% et 9% du fichier, ce qui n'est pas négligeable surtout sur les gros fichier. Créér simplement un fichier dans **'/batch/'**, par exemple **'strip_comments.php'** avec le code suivant __(2)__

***

**[En]** Take care, this snippet is only usefull for **0.6.3** version of Symfony, the 1.0.0 version already inlcudes this functionnality. Juste add in your **propel.ini** __(1)__

Here is a batch to delete the genrerated propel comments. On can optimize between 5% and 9% of file size, witch is not negligible. Just create a file in the directory **'/batch/'**, for example **'strip_comments.php'** with the following code :

***

## (2) /batch/strip_comments.php

[code php]
&lt;?php

// GEN =========================================================================

define('STR_N', &quot;&quot;);
define('CR', &quot;\r\n&quot;);
 
define('SF_ROOT_DIR',      realpath(dirname(__file__).'/..'));
define('SF_APP',           'backoffice');
define('SF_ENVIRONMENT',   'dev');
define('SF_DEBUG',          true);

// Tokenizer constants 
if (!defined('T_ML_COMMENT')) {
   define('T_ML_COMMENT', T_COMMENT);
} else {
   define('T_DOC_COMMENT', T_ML_COMMENT);
}
  
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR. 'apps'. DIRECTORY_SEPARATOR. SF_APP. DIRECTORY_SEPARATOR. 'config'. DIRECTORY_SEPARATOR. 'config.php');
 
// Logs
$logger = sfContext::getInstance()-&gt;getLogger();

// SPEC ========================================================================

$batchName = 'Strip Propel class comments ';


// PROCESS =====================================================================

// Titre
$info = '== BATCH : '.$batchName. CR;
print($info);
$logger-&gt;log($info);


// Start
$start = time();
$info = '== Start : '. CR; 
print($info);
$logger-&gt;log($info);


// Recuperation de la liste des fichiers
$modelPath = SF_ROOT_DIR. DIRECTORY_SEPARATOR. 'lib' . DIRECTORY_SEPARATOR. 'model'. DIRECTORY_SEPARATOR;
echo '$modelPath : '. $modelPath. CR;

$omPath  = $modelPath .'om'. DIRECTORY_SEPARATOR;
$mapPath = $modelPath. 'map'. DIRECTORY_SEPARATOR;

$omPropelFiles  = sfFinder::type('file')-&gt;name('Base*.php')-&gt;relative()-&gt;in($omPath);
$mapPropelFiles = sfFinder::type('file')-&gt;name('*MapBuilder.php')-&gt;relative()-&gt;in($mapPath);

// Om
if ($omPropelFiles) {
    foreach ($omPropelFiles as $file) {
    	strip_comments($omPath. $file);
    }

    $info = '== Om : '. count($omPropelFiles). ' fichiers epures.'. CR; 
    print($info);
    $logger-&gt;log($info);

}    

// Map
if ($mapPropelFiles) {
    foreach ($mapPropelFiles as $file) {
        strip_comments($mapPath. $file);
    }

    $info = '== Map : '. count($mapPropelFiles). ' fichiers epures.'. CR; 
    print($info);
    $logger-&gt;log($info);
}    

// End
$end = time();
$info = '== End'. CR; 
print($info);
$logger-&gt;log($info);


/**
 * Fonction de suppression des commentaires
 * 
 * @author Vernet Loïc
 * @since  2 févr. 2007
 */
function strip_comments($file)
{
    $source = file_get_contents($file);
    $tokens = token_get_all($source);
    
    $buffer = '';
    
    foreach ($tokens as $token) {
       if (is_string($token)) {
           // simple 1-character token
           $buffer.= $token;
       } else {
           // token array
           list($id, $text) = $token;
     
           switch ($id) {
               case T_COMMENT:
               case T_ML_COMMENT: // we've defined this
               case T_DOC_COMMENT: // and this
                   // no action on comments
                   break;
    
               default:
                   // anything else -&gt; output &quot;as is&quot;
                   $buffer.= $text;
                   break;
           }
       }
    }
    
    file_put_contents($file, $buffer);
}

?&gt;
[/code]
</summary>
</entry>
<entry>
  <title>[Symfony] Multi sort in admin generator</title>
  <link href="http://snippets.strangebuzz.com/snippet/5"></link>
  <updated>2007-01-15T14:09:22Z</updated>
  <id>5</id>
  <summary type="html">Here we go !

The sort in admin generator is for a single field only, but in some complex list, it can be usefull to sort by multiple criterias.
This is the main goal of this snippet. Those functions therefore override the ones of your auto-generated class. 
**(1)** And to display what are the ongoing sort criterias, you have to modify your **'\_list\_th\_tabular.php'** file.
  
## 1 - In your 'action.class.php'
  
[code php]
//
    /**
     * Add a sort criteria
     */
    protected function processSort ()
    {
        $sort = $this-&gt;getRequestParameter('sort');
        $type = $this-&gt;getRequestParameter('type');            

        // Register sort                 
        if ($sort) {
            $this-&gt;getUser()-&gt;setAttribute($sort, $type, 'sf_admin/produits/sort');
        }
    }    
    
    /**
     * Add the sort criterias to the query
     */
    protected function addSortCriteria(&amp;$c)
    {
        $multisort = $this-&gt;getUser()-&gt;getAttributeHolder()-&gt;getAll('sf_admin/produits/sort');

        if ($multisort) {
        	foreach($multisort as $sort_column =&gt; $sort_type) {
                $sort_column = Propel::getDB($c-&gt;getDbName())-&gt;quoteIdentifier($sort_column);
                if ($sort_type == 'asc') {
                    $c-&gt;addAscendingOrderByColumn($sort_column);
                }
                elseif ($sort_type == 'desc') {
                    $c-&gt;addDescendingOrderByColumn($sort_column);
                }
        	}
        } else {
            // Default sort 
            $sort_column = Propel::getDB($c-&gt;getDbName())-&gt;quoteIdentifier('libelle');
            $c-&gt;addAscendingOrderByColumn($sort_column);        	
        }
    }

    /**
     * Specific function for multi-sort
     */
    protected function processFilters ()
    {
        if ($this-&gt;getRequest()-&gt;hasParameter('filter'))
        {
            $filters = $this-&gt;getRequestParameter('filters');            

            // Multi-sort initialisation
            if (!is_array($filters)) {
                $this-&gt;getUser()-&gt;getAttributeHolder()-&gt;removeNamespace('sf_admin/produits/sort');
            }

            $this-&gt;getUser()-&gt;getAttributeHolder()-&gt;removeNamespace('sf_admin/produits/filters');
            $this-&gt;getUser()-&gt;getAttributeHolder()-&gt;add($filters, 'sf_admin/produits/filters');
        }
    }
[/code]
   
   
## 2 - In '\_list\_th\_tabular.php' 
  
(for each sortable field)
  
[code php]
&lt;?php 

$multisort = $sf_user-&gt;getAttributeHolder()-&gt;getAll('sf_admin/produits/sort');

?&gt;

    &lt;th id=&quot;sf_admin_list_th_libelle&quot;&gt;
        &lt;?php 
        if (isset($multisort['libelle'])) {
            echo link_to('Libellé', 'Produits/list?sort=libelle&amp;type='. ($multisort['libelle'] == 'asc' ? 'desc' : 'asc'));
            echo ' ('. $multisort['libelle'] . ')';
        } else {
            echo link_to('Libellé', 'Produits/list?sort=libelle&amp;type=asc'); 
        }
        ?&gt;
    &lt;/th&gt;
[/code]

**'Produits'** is the module name, **'libelle'** is the field to sort.
    
***
  
### Notes:
  
The 'reset button' of filters also initialize the multi-sort. The sort is made from the first field clicked to the last. That means, if you want a different primary sort you will have to use the reset filter button before.

**PS:** Obviously, this modification can be easly integrated in your backoffice theme, note that the default sort criteria set in the **'generator.yml'** is used in the addSortCriteria function (from line // default sort)

[Original Snippet](http://www.symfony-project.com/snippets/snippet/edit/id/103)

**COil  :)**</summary>
</entry>
</feed>