Zend Framework: Config Writer Yaml

AttachmentSize
ZExt_Config_Writer_Yaml.php4.22 KB

After writing the Zend Config Yml and Zend_Config_Any objects I realized that I wished to convert my existing ini files over to yml format, and so I banged out this code. I didn't really care for the format that the syck code generated, so have included a the option of passing in a boolean to format in my preferred style - see the inline documentation for an example of this.

Note that like Zend_Config_Yaml, this class also REQUIRES that the PHP syck modules be installed. On my Debian (Kubuntu, actually) this is accomplished easily via the repository (i.e. sudo apt-get install php5-syck) followed by a restart of apache (i.e. sudo /etc/init.d/apache2 restart). If the system you are using can not provide this extension (e.g. you're using rented system space with uncooperative sysadmins) then you may be able to modify this function using one of the PHP code based yml parsers, although I'm sure such an implementation would be considerably slower.

Edit 2009-04-10: I've changed the object name to "Yaml" upon realizing I wasn't following the established convention for doing so (even though it seems to ME that use of "Ini" and "Xml" might set a greater precedence for using a "Yml" extenesion).

An example call to this function might look something like this:

<?php
$inputfile = '../application/config.ini';
$outputfile = '../application/config.yml';

$config = new Zend_Config_Ini(
  $inputfile, 
  null, 
  array(
    'allowModifications' => false, 
    'skipExtends'=> true,
  )
);
$writer = new Zend_Config_Writer_Yaml();
$writer->write($outputfile, $config, true, true);

echo '<pre>'.file_get_contents($outputfile).'</pre>';

Aaaaaand the Config_Yaml class itself:

<?php
/**
 * @category   ZExt
 * @package    ZExt_Config
 * @subpackage ZExt_Writer_Config
 * @author     Sean P. O. MacCath-Moran
 * @email      zendcode@emanaton.com
 * @website    http://www.emanaton.com
 * @copyright  This work is licenced under a Attribution Non-commercial Share Alike Creative Commons licence
 * @license    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
*/

/**
 * @see Zend_Config
*/
require_once 'Zend/Config.php';

/**
 * @uses       ZExt_Config_Writer_Yaml
 * @package    ZExt_Config
 * @subpackage ZExt_Writer_Config
 * @author     Sean P. O. MacCath-Moran
 * @email      zendcode@emanaton.com
 * @website    http://www.emanaton.com
 * @copyright  This work is licenced under a Attribution Non-commercial Share Alike Creative Commons licence
 * @license    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
*/

/**
 * This class mirrors Zend_Config_Writer_Ini with a few exceptions.
 *
*/
class ZExt_Config_Writer_Yaml extends Zend_Config_Writer {
  /**
   * Filename to write to
   *
   * @var string
  */
  protected $_filename = null;

  /**
   * Wether to exclusively lock the file or not
   *
   * @var boolean
  */
  protected $_exclusiveLock = false;

  /**
   * Set the target filename
   *
   * @param  string $filename
   * @return Zend_Config_Writer_Xml
  */
  public function setFilename($filename)
  {
      $this->_filename = $filename;

      return $this;
  }

  /**
   * Set wether to exclusively lock the file or not
   *
   * @param  boolean     $exclusiveLock
   * @return Zend_Config_Writer_Array
  */
  public function setExclusiveLock($exclusiveLock)
  {
    $this->_exclusiveLock = $exclusiveLock;

    return $this;
  }

  /**
   * Defined by Zend_Config_Writer.
   *
   * The $reformat variable causes the output to be formatted using the convention of
   *       label: value
   * rather than
   *       $ label
   *       : value
   *
   * @param  string      $filename
   * @param  Zend_Config $config
   * @param  boolean     $exclusiveLock
   * @param  boolean     $reformat
   * @throws Zend_Config_Exception When filename was not set
   * @throws Zend_Config_Exception When filename is not writable
   * @return void
  */
  public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null, $reformat = false) {
    if ($filename !== null) {
      $this->setFilename($filename);
    }

    if ($config !== null) {
      $this->setConfig($config);
    }

    if ($exclusiveLock !== null) {
      $this->setExclusiveLock($exclusiveLock);
    }

    if ($this->_filename === null) {
      require_once 'Zend/Config/Exception.php';
      throw new Zend_Config_Exception('No filename was set');
    }

    if ($this->_config === null) {
      require_once 'Zend/Config/Exception.php';
      throw new Zend_Config_Exception('No config was set');
    }

    $data = ($this->_config instanceof Zend_Config) ? $this->_config->toArray() : $this->_config;
    $extends = $this->_config->getExtends();
    $sectionName = $this->_config->getSectionName();


    if (is_string($sectionName)) {
        $data = array($sectionName=>$data);
    } else {
      $data_work = $data;
      $data = array();
      foreach ($data_work as $sectionName => $sectionData) {
        if (isset($extends[$sectionName])) {
          $sectionName .= ' < ' . $extends[$sectionName];
        }

        $data = array_merge($data, array($sectionName=>$sectionData));
      }
    }

    $ymlString = syck_dump($data);
    if ($reformat) {
      // add an extra space before array key headers
      $ymlString = preg_replace('/(\n)(\s*[?][ ].*\n\s*[:][ ]\n)/', '$1$1$2', $ymlString);
      // remove the "? " that preceed new section keys
      $ymlString = preg_replace('/(\n\s*)[?][ ]/', '$1', $ymlString);
      // bring values up to the same line as the keys
      $ymlString = preg_replace('/\n\s*[:]/', ':', $ymlString);
      // remove double spacing
      $ymlString = preg_replace('/(\n)\n/', '$1', $ymlString);
    }

    $flags = 0;

    if ($this->_exclusiveLock) {
      $flags |= LOCK_EX;
    }

    $result = @file_put_contents($this->_filename, $ymlString, $flags);

    if ($result === false) {
      require_once 'Zend/Config/Exception.php';
      throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
    }
  }
}