Development

moreI18n

You must first sign up to be able to contribute.

Version 2 (modified by rubenrua, 10 years ago)
--

If you use Propel 1.2 with i18n, I think this patch can be util to improbe your performace:

In PEER:

  • public static function retrieveByPKWithI18n($pk, $culture = null, $con = null)
  • public static function retrieveByPKsWithI18n($pks, $culture = null, $con = null)

In OBJECT:

  • public function getSerialWithI18n($con = null)
  • public function getFilesWithI18n($criteria = null, $con = null)
  • hydate initialice culture by default

In file 'SfPeerBuilder?.php' add:

  protected function addRetrieveByPKMethods(&$script)
  {
    parent::addRetrieveByPKMethods($script);

    if ($this->getTable()->getAttribute('isI18N'))
    {
      if (count($this->getTable()->getPrimaryKey()) === 1) {
	$this->addRetrieveByPKWithI18n_SinglePK($script);
	$this->addRetrieveByPKsWithI18n_SinglePK($script);
      } else {
	$this->addRetrieveByPKWithI18n_MultiPK($script);
      }
    }
  }




  /**
   * Adds the retrieveByPKWithI18n method for tables with single-column primary key.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addRetrieveByPKWithI18n_SinglePK(&$script)
  {
    $table = $this->getTable();
    $script .= "
	/**
	 * Retrieve a single object by pkey with their i18n objects.
	 *
	 * @param      mixed \$pk the primary key.
	 * @param      Connection \$con the connection to use
	 * @return     " . $table->getPhpName() . "
	 */
	public static function ".$this->getRetrieveMethodName()."WithI18n(\$pk, \$culture = null, \$con = null)
	{
		if (\$con === null) {
			\$con = Propel::getConnection(self::DATABASE_NAME);
		}

		\$criteria = new Criteria(".$this->getPeerClassname()."::DATABASE_NAME);
";
    if (count($table->getPrimaryKey()) === 1) {
      $pkey = $table->getPrimaryKey();
      $col = array_shift($pkey);
      $script .= "
		\$criteria->add(".$this->getColumnConstant($col).", \$pk);
";
    } else {
      // primary key is composite; we therefore, expect
      // the primary key passed to be an array of pkey
      // values
      $i=0;
      foreach($table->getPrimaryKey() as $col) {
	$script .= "
		\$criteria->add(".$this->getColumnConstant($col).", \$pk[$i]);";
	$i++;
      }
    } /* if count(table.PrimaryKeys) */
    $script .= "

		\$v = ".$this->getPeerClassname()."::doSelectWithI18n(\$criteria, \$culture, \$con);

		return !empty(\$v) > 0 ? \$v[0] : null;
	}
";
  }



  /**
   * Adds the retrieveByPKs method for tables with single-column primary key.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addRetrieveByPKsWithI18n_SinglePK(&$script)
  {
    $table = $this->getTable();
    $script .= "
	/**
	 * Retrieve multiple objects by pkey.
	 *
	 * @param      array \$pks List of primary keys with their i18n objects.
	 * @param      Connection \$con the connection to use
	 * @throws     PropelException Any exceptions caught during processing will be
	 *		 rethrown wrapped into a PropelException.
	 */
	public static function ".$this->getRetrieveMethodName()."sWithI18n(\$pks, \$culture = null, \$con = null)
	{
		if (\$con === null) {
			\$con = Propel::getConnection(self::DATABASE_NAME);
		}

		\$objs = null;
		if (empty(\$pks)) {
			\$objs = array();
		} else {
			\$criteria = new Criteria();";
    if (count($table->getPrimaryKey()) == 1) {
      $k1 = $table->getPrimaryKey();
      $script .= "
			\$criteria->add(".$this->getColumnConstant($k1[0]).", \$pks, Criteria::IN);";
    } else {
      $script .= "
			foreach(\$pks as \$pk) {";
      $i = 0;
      foreach($table->getPrimaryKey() as $col) {
	$script .= "
				\$c{$i} = \$criteria->getNewCriterion(".$this->getPeerClassname($col).", \$pk[$i], Criteria::EQUAL);";
	$j = $i - 1;
	if ($i > 0) {
	  $script .= "
				\$c{$j}->addAnd(\$c{$i});";
	} /* if $i > 0 */
	$i++;
      } /* foreach */
      
      $script .= "

				\$criteria->addOr(\$c0);
			}";
    } /* if count prim keys == 1 */
    $script .= "
			\$objs = ".$this->getPeerClassname()."::doSelectWithI18n(\$criteria, \$culture, \$con);
		}
		return \$objs;
	}
";
  }



  /**
   * Adds the retrieveByPK method for tables with multi-column primary key.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addRetrieveByPKWithI18n_MultiPK(&$script)
  {
    $table = $this->getTable();
    $script .= "
	/**
	 * Retrieve object using using composite pkey values.
	 * ";
    foreach ($table->getPrimaryKey() as $col) {
      $clo = strtolower($col->getName());
      $cptype = $col->getPhpNative();
      $script .= "@param $cptype $".$clo."
	   ";
    }
    $script .= "
	 * @param      Connection \$con
	 * @return     ".$table->getPhpName()."
	 */
	public static function ".$this->getRetrieveMethodName()."WithI18n(";
    $co = 0;
    foreach ($table->getPrimaryKey() as $col) {
      $clo = strtolower($col->getName());
      $script .= ($co++ ? "," : "") . " $".$clo;
    } /* foreach */
    $script .= ", \$culture = null, \$con = null) {
		if (\$con === null) {
			\$con = Propel::getConnection(self::DATABASE_NAME);
		}
		\$criteria = new Criteria();";
    foreach ($table->getPrimaryKey() as $col) {
      $clo = strtolower($col->getName());
      $script .= "
		\$criteria->add(".$this->getColumnConstant($col).", $".$clo.");";
    }
    $script .= "
		\$v = ".$this->getPeerClassname()."::doSelectWithI18n(\$criteria, \$culture, \$con);

		return !empty(\$v) ? \$v[0] : null;
	}";
  }
  


And in file 'SfObjectBuilder?.php' add:

  /**
   * Adds the hydrate() method, which sets attributes of the object based on a ResultSet.
   */
  protected function addHydrate(&$script)
  {
    $tmp = '';
    $new = (!$this->getTable()->getAttribute('isI18N'))?"\$this->setNew(false);":"\$this->setNew(false);
			\$this->setCulture(sfContext::getInstance()->getUser()->getCulture());";
    parent::addHydrate($tmp);
    // add autosave to i18n object even if the base object is not changed
    $tmp = str_replace('$this->setNew(false);', $new, $tmp);
    
    $script .= $tmp;
  }


  /**
   * Adds the methods that get & set objects related by foreign key to the current object.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addFKMethods(&$script)
  {
    foreach ($this->getTable()->getForeignKeys() as $fk) {
      $this->addFKMutator($script, $fk);
      $this->addFKAccessor($script, $fk);
      
      if($this->getForeignTable($fk)->getAttribute('isI18N'))
      {
      	$this->addFKAccessorWithI18n($script, $fk);
      }
      
    } // foreach fk
  }


  /**
   * Adds the accessor (getter) method for getting an fkey related object.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addFKAccessorWithI18n(&$script, ForeignKey $fk)
  {
    $table = $this->getTable();
    
    $className = $this->getForeignTable($fk)->getPhpName();
    $varName = $this->getFKVarName($fk);

    $and = "";
    $comma = "";
    $conditional = "";
    $arglist = "";
    $argsize = 0;
    foreach ($fk->getLocalColumns() as $columnName) {
      $column = $table->getColumn($columnName);
      $cptype = $column->getPhpNative();
      $clo = strtolower($column->getName());
      
      // FIXME: is this correct? what about negative numbers?
      if ($cptype == "integer" || $cptype == "float" || $cptype == "double") {
	$conditional .= $and . "\$this->". $clo ." > 0";
      } elseif($cptype == "string") {
	$conditional .= $and . "(\$this->" . $clo ." !== \"\" && \$this->".$clo." !== null)";
      } else {
	$conditional .= $and . "\$this->" . $clo ." !== null";
      }
      $arglist .= $comma . "\$this->" . $clo;
      $and = " && ";
      $comma = ", ";
      $argsize = $argsize + 1;
    }
    
    $pCollName = $this->getFKPhpNameAffix($fk, $plural = true);
    
    $fkPeerBuilder = OMBuilder::getNewPeerBuilder($this->getForeignTable($fk));
    
    $script .= "

	/**
	 * Get the associated $className object
	 *
	 * @param      Connection Optional Connection object.
	 * @return     $className The associated $className object.
	 * @throws     PropelException
	 */
	public function get".$this->getFKPhpNameAffix($fk, $plural = false)."WithI18n(\$con = null)
	{
		if (\$this->$varName === null && ($conditional)) {
			// include the related Peer class
			include_once '".$fkPeerBuilder->getClassFilePath()."';
";
    $script .= "
			\$this->$varName = ".$fkPeerBuilder->getPeerClassname()."::".$fkPeerBuilder->getRetrieveMethodName()."WithI18n($arglist, \$this->getCulture(), \$con);

			/* The following can be used instead of the line above to
			   guarantee the related object contains a reference
			   to this object, but this level of coupling
			   may be undesirable in many circumstances.
			   As it can lead to a db query with many results that may
			   never be used.
			   \$obj = ".$fkPeerBuilder->getPeerClassname()."::retrieveByPKWithI18n($arglist, \$this->getCulture(), \$con);
			   \$obj->add$pCollName(\$this);
			 */
		}
		return \$this->$varName;
	}
";
    
  } // addFKAccessor  



  /**
   * Adds the methods for retrieving, initializing, adding objects that are related to this one by foreign keys.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addRefFKMethods(&$script)
  {
    foreach($this->getTable()->getReferrers() as $refFK) {
      // if ( $refFK->getTable()->getName() != $this->getTable()->getName() ) {
      $this->addRefFKInit($script, $refFK);
      $this->addRefFKGet($script, $refFK);
      $this->addRefFKCount($script, $refFK);
      $this->addRefFKAdd($script, $refFK);
      $this->addRefFKGetJoinMethods($script, $refFK);

      if($this->getTable()->getDatabase()->getTable($refFK->getTableName())->getAttribute('isI18N'))
      {
	$this->addRefFKGetWithI18n($script, $refFK);
      }
      // }
    }
  }


  /**
   * Adds the method that returns the referrer fkey collection.
   * @param      string &$script The script will be modified in this method.
   */
  protected function addRefFKGetWithI18n(&$script, ForeignKey $refFK)
  {
    $table = $this->getTable();
    $tblFK = $refFK->getTable();
    
    $fkPeerBuilder = OMBuilder::getNewPeerBuilder($refFK->getTable());
    $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
    
    $collName = $this->getRefFKCollVarName($refFK);
    $lastCriteriaName = $this->getRefFKLastCriteriaVarName($refFK);
    
    $script .= "
	/**
	 * If this collection has already been initialized with
	 * an identical criteria, it returns the collection.
	 * Otherwise if this ".$table->getPhpName()." has previously
	 * been saved, it will retrieve related $relCol from storage.
	 * If this ".$table->getPhpName()." is new, it will return
	 * an empty collection or the current collection, the criteria
	 * is ignored on a new object.
	 *
	 * @param      Connection \$con
	 * @param      Criteria \$criteria
	 * @throws     PropelException
	 */
	public function get${relCol}WithI18n(\$criteria = null, \$con = null)
	{
		// include the Peer class
		include_once '".$fkPeerBuilder->getClassFilePath()."';
		if (\$criteria === null) {
			\$criteria = new Criteria();
		}
		elseif (\$criteria instanceof Criteria)
		{
			\$criteria = clone \$criteria;
		}

		if (\$this->$collName === null) {
			if (\$this->isNew()) {
			   \$this->$collName = array();
			} else {
";
    foreach ($refFK->getLocalColumns() as $colFKName) {
      // $colFKName is local to the referring table (i.e. foreign to this table)
      $lfmap = $refFK->getLocalForeignMapping();
      $localColumn = $this->getTable()->getColumn($lfmap[$colFKName]);
      $colFK = $refFK->getTable()->getColumn($colFKName);
      
      $script .= "
				\$criteria->add(".$fkPeerBuilder->getColumnConstant($colFK).", \$this->get".$localColumn->getPhpName()."());
";
    } // end foreach ($fk->getForeignColumns()
    
    $script .= "
				\$this->$collName = ".$fkPeerBuilder->getPeerClassname()."::doSelectWithI18n(\$criteria, \$this->getCulture(), \$con);
			}
		} else {
			// criteria has no effect for a new object
			if (!\$this->isNew()) {
				// the following code is to determine if a new query is
				// called for.  If the criteria is the same as the last
				// one, just return the collection.
";
    foreach ($refFK->getLocalColumns() as $colFKName) {
      // $colFKName is local to the referring table (i.e. foreign to this table)
      $lfmap = $refFK->getLocalForeignMapping();
      $localColumn = $this->getTable()->getColumn($lfmap[$colFKName]);
      $colFK = $refFK->getTable()->getColumn($colFKName);
      $script .= "

				\$criteria->add(".$fkPeerBuilder->getColumnConstant($colFK).", \$this->get".$localColumn->getPhpName()."());
";
    } // foreach ($fk->getForeignColumns()
    $script .= "
				if (!isset(\$this->$lastCriteriaName) || !\$this->".$lastCriteriaName."->equals(\$criteria)) {
					\$this->$collName = ".$fkPeerBuilder->getPeerClassname()."::doSelectWithI18n(\$criteria, \$this->getCulture(), \$con);
				}
			}
		}
		\$this->$lastCriteriaName = \$criteria;
		return \$this->$collName;
	}
";
  } // addRefererGet()
  

Sorry for my English