</th>
            <th><?php 
echo __('Author');
?>
</th>
        </tr>
    </thead>
    <tbody>
    <?php 
$table_list_even_odd = 0;
foreach ($items as $item) {
    $table_class = $table_list_even_odd++ % 2 == 0 ? 'table_list_even' : 'table_list_odd';
    $user_link = '@document_by_id?module=users&id=' . $item['user_private_data']['id'];
    $models = c2cTools::Type2Models($item['type']);
    $main_module = c2cTools::model2module($models['main']);
    $linked_module = c2cTools::model2module($models['linked']);
    $main_item = count($item['mainI18n']) ? $item['mainI18n'][0] : null;
    $linked_item = count($item['linkedI18n']) ? $item['linkedI18n'][0] : null;
    // FIXME: routes slugs
    $main_link = '@document_by_id_lang_slug?module=' . $main_module . '&id=' . $item['main_id'] . '&lang=' . $main_item['culture'] . '&slug=' . make_slug($main_item['name']);
    $linked_link = '@document_by_id_lang_slug?module=' . $linked_module . '&id=' . $item['linked_id'] . '&lang=' . $linked_item['culture'] . '&slug=' . make_slug($linked_item['name']);
    ?>
        <tr class="<?php 
    echo $table_class;
    if ($item['is_creation']) {
        echo ' creation';
    } else {
        echo ' deletion';
    }
    ?>
">
 /**
  * Changes the association order for associations of same type (eg summit-summit)
  * It should only be used for ss, pp and tt associations, but there is probably
  * no real problem if other associations are inverted
  */
 public function executeInvertAssociation()
 {
     $user = $this->getUser();
     $user_id = $user->getId();
     $is_moderator = $user->hasCredential('moderator');
     $type = $this->getRequestParameter('type');
     $main_id = $this->getRequestParameter('main_id');
     $linked_id = $this->getRequestParameter('linked_id');
     // check if session timed out
     if (!$user_id) {
         return $this->setErrorAndRedirect('Session is over. Please login again.', $this->getRequest()->getReferer());
     }
     // only moderators can perform such actions
     if (!$is_moderator) {
         return $this->setErrorAndRedirect('You do not have enough credentials to perform this operation', $this->getRequest()->getReferer());
     }
     // we check that the association type really exists and that the two
     // documents are from the same model
     if (substr($type, 0, 1) != substr($type, -1) || !in_array($type, sfConfig::get('app_associations_types'))) {
         return $this->ajax_feedback('Wrong association type');
     }
     // check that association exists in database
     $models = c2cTools::Type2Models($type);
     $model = $models['main'];
     $module = c2cTools::model2module($model);
     $a = Association::find($main_id, $linked_id, $type);
     // strict search
     if (!$a) {
         return $this->setErrorAndRedirect('Operation not allowed', $this->getRequest()->getReferer());
     }
     // invert association
     $conn = sfDoctrine::Connection();
     try {
         $conn->beginTransaction();
         $a->main_id = $linked_id;
         $a->linked_id = $main_id;
         $a->save();
         $al1 = new AssociationLog();
         $al1->main_id = $main_id;
         $al1->linked_id = $linked_id;
         $al1->type = $type;
         $al1->user_id = $user_id;
         $al1->is_creation = 'false';
         $al1->save();
         $al1 = new AssociationLog();
         $al1->main_id = $linked_id;
         $al1->linked_id = $main_id;
         $al1->type = $type;
         $al1->user_id = $user_id;
         $al1->is_creation = 'true';
         $al1->save();
         $conn->commit();
     } catch (exception $e) {
         $conn->rollback();
         c2cTools::log("executeInvertAssociation() : invertion failed ({$main_id}, {$linked_id}, {$type}, {$user_id}) - rollback");
         return $this->ajax_feedback('Association invertion failed');
     }
     // remove cache and force page reload
     $this->clearCache($module, $main_id, false, 'view');
     $this->clearCache($module, $linked_id, false, 'view');
     return $this->setNoticeAndRedirect('Association inverted', $this->getRequest()->getReferer());
 }
 /**
  * Get nearest docs to a point
  */
 public static function getNearest($lon, $lat, $model = 'Document', $exclude = null)
 {
     $module = c2cTools::model2module($model);
     $distance = sfConfig::get('app_autocomplete_near_max_distance');
     $limit = sfConfig::get('app_autocomplete_suggest_max_results');
     // We have to use raw SQL because of postgis functions
     // Not that we first filter width ST_DWithin and only after that compute the dstance,
     // which is more effective
     $q = new Doctrine_RawSql();
     $q->select('{d.id}, {m.culture}, {m.name}')->from('(SELECT id FROM ' . $module . ' ' . 'WHERE ST_DWithin(geom, ST_Transform(ST_SetSRID(ST_MakePoint(?, ?), 4326), 900913), ?) ' . 'AND redirects_to IS NULL ' . (empty($exclude) ? '' : ' AND id NOT IN (' . implode(',', array_fill(0, sizeof($exclude), '?')) . ') ') . 'ORDER BY ST_Distance(geom, ST_Transform(ST_SetSRID(ST_MakePoint(?, ?), 4326), 900913)) ' . 'LIMIT ?) AS d ' . 'LEFT JOIN ' . $module . '_i18n m ON d.id = m.id')->addComponent('d', $model . ' d')->addComponent('m', 'd.' . $model . 'I18n m');
     return $q->execute(array_merge(array($lon, $lat, $distance), (array) $exclude, array($lon, $lat, $limit)), Doctrine::FETCH_ARRAY);
 }