Development

Changeset 10132

You must first sign up to be able to contribute.

Changeset 10132

Show
Ignore:
Timestamp:
07/05/08 11:34:47 (5 years ago)
Author:
francois
Message:

sfPropelFinderPlugin Slight refactoring + fixing i18n relations when hydrating (closes #3911)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/sfPropelFinderPlugin/lib/sfPropelFinder.php

    r10123 r10132  
    258258      $this->criteria->setLimit($limit); 
    259259    } 
    260     $ret = $this->doFind($this->getCriteria(), $con); 
     260    $ret = $this->doFind($con); 
    261261    $this->updateLatestQuery($con); 
    262262    if($reinitCriteria) 
     
    271271  { 
    272272    $this->criteria->setLimit(1); 
    273     $ret = $this->doFind($this->getCriteria(), $con); 
     273    $ret = $this->doFind($con); 
    274274    $this->updateLatestQuery($con); 
    275275    if($reinitCriteria) 
     
    455455  } 
    456456   
    457   public function doFind($criteria, $con = null) 
    458   { 
     457  public function doFind($con = null) 
     458  { 
     459    $this->addMissingJoins(); 
    459460    if($this->getWithClasses() || $this->getWithColumns()) 
    460461    { 
    461       $c = $this->prepareCompositeCriteria($criteria); 
     462      $c = $this->prepareCompositeCriteria(); 
    462463      if(method_exists($this->getPeerClass(), 'doSelectRS')) 
    463464      { 
     
    527528            } 
    528529          } 
    529           sfPropelFinderUtils::relateObjects($withObj, $objectsInJoin, $isNewObject); 
     530          if(strpos(get_class($withObj), 'I18n') !== false) 
     531          { 
     532            sfPropelFinderUtils::relateI18nObjects($withObj, $objectsInJoin, $this->culture); 
     533          } 
     534          else 
     535          { 
     536            sfPropelFinderUtils::relateObjects($withObj, $objectsInJoin, $isNewObject); 
     537          } 
    530538          $objectsInJoin []= $withObj; 
    531539          if ($isNewObject) 
     
    566574    { 
    567575      // No 'with', so we use the native Propel doSelect() 
    568       return call_user_func(array($this->getPeerClass(), 'doSelect'), $criteria, $con); 
    569     } 
     576      return call_user_func(array($this->getPeerClass(), 'doSelect'), $this->buildCriteria(), $con); 
     577    } 
     578  } 
     579   
     580  /** 
     581   * Adds missing Joins from with() and withColumn() 
     582   */ 
     583  protected function addMissingJoins() 
     584  { 
     585    foreach ($this->getWithClasses() as $className) 
     586    { 
     587      if(!in_array(sfPropelFinderUtils::getPeerClassFromClass($className), $this->relations)) 
     588      { 
     589        $this->join($className); 
     590      } 
     591    } 
     592    foreach($this->getWithColumns() as $alias => $column) 
     593    { 
     594      $peerClass = $column['peerClass']; 
     595      if($peerClass && !in_array($peerClass, $this->relations)) 
     596      { 
     597        $this->join(sfPropelFinderUtils::getClassFromPeerClass($peerClass)); 
     598      } 
     599    } 
     600     
     601    return $this; 
    570602  } 
    571603   
     
    573605   * Prepare the select columns and add the missing joins 
    574606   */ 
    575   protected function prepareCompositeCriteria($criteria) 
    576   { 
     607  protected function prepareCompositeCriteria() 
     608  { 
     609    $criteria = $this->buildCriteria(); 
    577610    $c = clone $criteria; 
    578611    $c->clearSelectColumns(); 
     
    582615    foreach ($this->getWithClasses() as $className) 
    583616    { 
    584       $tempClass = new $className(); 
    585       call_user_func(array($tempClass->getPeer(), 'addSelectColumns'), $c); 
    586       // if join() wasn't called previously on this class, do a simple join 
    587       if(!in_array(sfPropelFinderUtils::getPeerClassFromClass($className), $this->relations)) 
    588       { 
    589         list($column1, $column2) = $this->getRelation($className); 
    590         $c->addJoin($column1, $column2); 
    591         $this->relations[]= sfPropelFinderUtils::getPeerClassFromClass($className); 
    592       } 
     617      call_user_func(array(sfPropelFinderUtils::getPeerClassFromClass($className), 'addSelectColumns'), $c); 
    593618    } 
    594619    // Then the columns added one by one by way of 'withColumn' 
    595620    foreach($this->getWithColumns() as $alias => $column) 
    596621    { 
    597       // if the column is on a related object property  
    598       // and if join() wasn't called previously on this object, do a simple join 
    599       $peerClass = $column['peerClass']; 
    600       if($peerClass && !in_array($peerClass, $this->relations)) 
    601       { 
    602         list($column1, $column2) = $this->getRelation(sfPropelFinderUtils::getClassFromPeerClass($peerClass)); 
    603         $c->addJoin($column1, $column2); 
    604         $this->relations[]= $peerClass; 
    605       } 
    606622      $c->addAsColumn('\''.$alias.'\'', $column['column']); 
    607623    } 
     
    636652  { 
    637653    $i18nClass = $this->class.'I18n'; 
    638     $tmp = new $i18nClass(); 
    639     $i18nPeerClass = get_class($tmp->getPeer()); 
    640     if(is_null($culture)) $culture = sfContext::getInstance()->getUser()->getCulture(); 
    641     $this->addWithClass($this->class.'I18n'); 
    642     $this->criteria->add(constant($i18nPeerClass.'::CULTURE'), $culture); 
    643     $this->culture = $culture; 
     654    $this->addWithClass($i18nClass); 
     655    $this->culture = is_null($culture) ? sfContext::getInstance()->getUser()->getCulture() : $culture; 
     656    $this->criteria->add(constant(sfPropelFinderUtils::getPeerClassFromClass($i18nClass).'::CULTURE'), $this->culture); 
    644657     
    645658    return $this; 
  • plugins/sfPropelFinderPlugin/lib/sfPropelFinderUtils.php

    r10118 r10132  
    2525        } 
    2626        call_user_func(array($new, $methodName), $existingObject); 
     27        break; 
     28      } 
     29    } 
     30  } 
     31   
     32  public static function relateI18nObjects($new, $existingObjects, $culture) 
     33  { 
     34    // brute force (to be optimized later) 
     35    foreach ($existingObjects as $existingObject) 
     36    { 
     37      $methodName = 'set'.get_class($new).'ForCulture'; 
     38      if(method_exists($existingObject, $methodName)) 
     39      { 
     40        call_user_func(array($existingObject, $methodName), $new, $culture); 
     41        call_user_func(array($new, 'set'.get_class($existingObject)), $existingObject); 
    2742        break; 
    2843      } 
  • plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderRelationsTest.php

    r10122 r10132  
    7979$con = Propel::getConnection(); 
    8080 
    81 $t = new lime_test(71, new lime_output_color()); 
     81$t = new lime_test(72, new lime_output_color()); 
    8282 
    8383$t->diag('findRelation()'); 
     
    274274$article1->setCategory($category1); 
    275275$article1->save(); 
     276$sql = 'SELECT article.ID, article.VERSION, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM article, category WHERE article.CATEGORY_ID=category.ID LIMIT 1'; 
    276277$finder = sfPropelFinder::from('Article')->join('Category')->with('Category'); 
    277278$article = $finder->findOne(); 
    278 $sql = 'SELECT article.ID, article.VERSION, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM article, category WHERE article.CATEGORY_ID=category.ID LIMIT 1'; 
    279279$t->is($finder->getLatestQuery(), $sql, 'with() gets the columns of the with class in addition to the columns of the current class'); 
     280$article->getCategory(); 
     281$t->is(Propel::getConnection()->getLastExecutedQuery(), $sql, 'with() hydrates the related classes and avoids subsequent queries'); 
     282 
    280283$finder = sfPropelFinder::from('Article')->with('Category'); 
    281284$article = $finder->findOne(); 
    282285$t->is($finder->getLatestQuery(), $sql, 'with() adds a join if not already added'); 
    283286$t->is($article->getTitle(), 'aaaaa', 'fetching objects with a with() returns the correct main object'); 
    284 $category = $article->getCategory(); 
    285 $t->is($category->getName(), 'cat1', 'fetching objects with a with() returns the correct related object'); 
    286 $con = Propel::getConnection(); 
    287 $latestQuery = $con->getLastExecutedQuery(); 
    288 $t->is($latestQuery, $sql, 'calling a FK getter on an object hydrated with with() does not issue a new query'); 
     287$t->is($article->getCategory()->getName(), 'cat1', 'fetching objects with a with() returns the correct related object'); 
     288$t->is(Propel::getConnection()->getLastExecutedQuery(), $sql, 'with() called without a join() hydrates the related classes and avoids subsequent queries'); 
    289289 
    290290ArticlePeer::doDeleteAll(); 
     
    305305$finder = sfPropelFinder::from('Comment')->with('Article')->with('Author'); 
    306306$comment = $finder->findOne(); 
     307$sql = 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article.VERSION, article.TITLE, article.CATEGORY_ID, author.ID, author.NAME FROM comment, article, author WHERE comment.ARTICLE_ID=article.ID AND comment.AUTHOR_ID=author.ID LIMIT 1'; 
     308$t->is($finder->getLatestQuery(), $sql, 'you can call with() several times to hydrate more than one related object'); 
    307309$t->is($comment->getContent(), 'foo', 'you can call with() several times to hydrate more than one related object'); 
    308310$t->is($comment->getArticle()->getTitle(), 'bbbbb', 'you can call with() several times to hydrate more than one related object'); 
    309311$t->is($comment->getAuthor()->getName(), 'John', 'you can call with() several times to hydrate more than one related object'); 
    310 $t->is($finder->getLatestQuery(), 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article.VERSION, article.TITLE, article.CATEGORY_ID, author.ID, author.NAME FROM comment, article, author WHERE comment.ARTICLE_ID=article.ID AND comment.AUTHOR_ID=author.ID LIMIT 1', 'you can call with() several times to hydrate more than one related object'); 
     312$t->is(Propel::getConnection()->getLastExecutedQuery(), $sql, 'with() called several tims hydrates the related classes and avoids subsequent queries'); 
    311313 
    312314$finder = sfPropelFinder::from('Comment')->with('Article')->with('Category'); 
     
    333335$finder = sfPropelFinder::from('Article')->withI18n(); 
    334336$article = $finder->findOne(); 
    335  
    336 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.VERSION, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'withI18n() hydrates the related I18n object with a culture taken from the user object'); 
     337$query = $finder->getLatestQuery(); 
     338$t->is($query, 'SELECT article.ID, article.VERSION, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'withI18n() hydrates the related I18n object with a culture taken from the user object'); 
    337339$t->is($article->getContent(), 'english content', 'withI18n() considers the current user culture for hydration'); 
     340$t->is(Propel::getConnection()->getLastExecutedQuery(), $query, 'withI18n() hydrates the i18n object so that no further query is necessary'); 
    338341 
    339342sfContext::getInstance()->getUser()->setCulture('fr');