2013-08-01 09:18:14 +02:00
|
|
|
<?php
|
|
|
|
// {{{ICINGA_LICENSE_HEADER}}}
|
|
|
|
/**
|
|
|
|
* This file is part of Icinga 2 Web.
|
|
|
|
*
|
|
|
|
* Icinga 2 Web - Head for multiple monitoring backends.
|
|
|
|
* Copyright (C) 2013 Icinga Development Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
|
|
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
|
|
|
* @author Icinga Development Team <info@icinga.org>
|
|
|
|
*/
|
|
|
|
// {{{ICINGA_LICENSE_HEADER}}}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
|
2013-08-01 09:18:14 +02:00
|
|
|
namespace Icinga\Config;
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
|
2013-08-01 09:18:14 +02:00
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* A ini file adapter that respects the file structure and the comments of already
|
|
|
|
* existing ini files
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
class PreservingIniWriter extends \Zend_Config_Writer_FileAbstract
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Create a new instance of PreservingIniWriter
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param array $options The options passed to the base class
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
function __construct(array $options)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
parent::__construct($options);
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Render the Zend_Config into a config file string
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function render()
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$oldconfig = new \Zend_Config_Ini($this->_filename);
|
|
|
|
$newconfig = $this->_config;
|
|
|
|
$editor = new IniEditor(file_get_contents($this->_filename));
|
|
|
|
$this->diffConfigs($oldconfig,$newconfig,$editor);
|
|
|
|
return $editor->getText();
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Create a property diff and apply the changes to the editor
|
|
|
|
*
|
|
|
|
* Compare two Zend_Config that represent the state change of an ini file and use the
|
|
|
|
* IniEditor to write the changes back to the config, while preserving the structure and
|
|
|
|
* the comments of the original file.
|
|
|
|
*
|
|
|
|
* @param Zend_Config $oldconfig The config representing the state before the change
|
|
|
|
* @param Zend_Config $newconfig The config representing the state after the change
|
|
|
|
* @param IniEditor $editor The editor that should be used to edit the old config file
|
|
|
|
* @param array $parents The parent keys that should be respected when editing the config
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function diffConfigs(
|
|
|
|
\Zend_Config $oldconfig,
|
|
|
|
\Zend_Config $newconfig,
|
|
|
|
IniEditor $editor,
|
|
|
|
array $parents = array())
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
foreach ($newconfig as $key => $value) {
|
|
|
|
$oldvalue = $oldconfig->get($key);
|
|
|
|
$fullKey = array_merge($parents,array($key));
|
|
|
|
if ($value instanceof \Zend_Config) {
|
|
|
|
if (empty($parents)) {
|
|
|
|
$extends = $newconfig->getExtends();
|
|
|
|
$extend = array_key_exists($key,$extends) ? $extends[$key] : null;
|
|
|
|
$editor->setSection($key,$extend);
|
|
|
|
}
|
|
|
|
if (!isset($oldvalue)) {
|
|
|
|
$this->diffConfigs(new \Zend_Config(array()),$value,$editor,$fullKey);
|
|
|
|
} else {
|
|
|
|
$this->diffConfigs($oldvalue,$value,$editor,$fullKey);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (is_numeric($key)){
|
|
|
|
$editor->setArrayEl($fullKey,$value);
|
|
|
|
} else {
|
|
|
|
$editor->set($fullKey,$value);
|
|
|
|
}
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
2013-08-06 16:28:26 +02:00
|
|
|
foreach ($oldconfig as $key => $value) {
|
|
|
|
$fullKey = array_merge($parents,array($key));
|
|
|
|
$o = $newconfig->get($key);
|
|
|
|
if (!isset($o)) {
|
|
|
|
if ($value instanceof \Zend_Config) {
|
|
|
|
$this->diffConfigs(
|
|
|
|
$value,new \Zend_Config(array()),$editor,$fullKey
|
|
|
|
);
|
|
|
|
$editor->removeSection($key);
|
|
|
|
} else {
|
|
|
|
if (is_numeric($key)) {
|
|
|
|
$editor->delArrayEl($fullKey);
|
|
|
|
} else {
|
|
|
|
$editor->reset($fullKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Edit the sections and keys of an ini in-place
|
|
|
|
*/
|
|
|
|
class IniEditor
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The text that is edited
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private $text;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The symbol that is used
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private $nestSeparator = '.';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the nest separator
|
|
|
|
*
|
|
|
|
* @return string The nest separator
|
|
|
|
*/
|
|
|
|
public function getNestSeparator()
|
|
|
|
{
|
|
|
|
return $this->nestSeparator;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Set the nest separator
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $separator The nest separator
|
|
|
|
* @return mixed The current instance of IniReader
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
public function setNestSeparator($separator)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$this->nestSeparator = $separator;
|
|
|
|
return $this;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Create a new IniEditor
|
|
|
|
*
|
|
|
|
* @param $content The content of the ini as string
|
|
|
|
*/
|
|
|
|
public function __construct($content)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$this->text = explode("\n",$content);
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Set the value of the given key.
|
|
|
|
*
|
|
|
|
* Update the key, if it already exists, otherwise create it.
|
|
|
|
*
|
|
|
|
* @param array $key
|
|
|
|
* @param $value
|
|
|
|
*/
|
|
|
|
public function set(array $key,$value)
|
|
|
|
{
|
|
|
|
$line = $this->getKeyLine($key);
|
|
|
|
if ($line === -1) {
|
|
|
|
$this->insert($key,$value);
|
|
|
|
return;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
2013-08-06 16:28:26 +02:00
|
|
|
$content = $this->formatKeyValuePair(
|
|
|
|
$this->truncateSection($key),$value);
|
|
|
|
$this->updateLine($line,$content);
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
public function delArrayEl(array $key)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$line = $this->getArrayEl($key);
|
|
|
|
if ($line !== -1) {
|
|
|
|
$this->deleteLine($line);
|
|
|
|
}
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
public function setArrayEl(array $key,$value)
|
|
|
|
{
|
|
|
|
$line = $this->getArrayEl($key);
|
|
|
|
if (count($key) > 1) {
|
|
|
|
$ident = $this->truncateSection($key);
|
|
|
|
$section = $key[0];
|
|
|
|
} else {
|
|
|
|
$ident = $key;
|
|
|
|
$section = null;
|
|
|
|
}
|
|
|
|
if ($line !== -1) {
|
|
|
|
if (count($ident) > 1){
|
|
|
|
$this->updateLine($line,$this->formatKeyValuePair($ident,$value));
|
|
|
|
} else {
|
|
|
|
// move into own section
|
|
|
|
$this->deleteLine($line);
|
|
|
|
$this->setSection($section);
|
|
|
|
$this->insert(array_merge(array($section),$ident),$value);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$e = $this->getSectionEnd($section);
|
|
|
|
$this->insertAtLine($e,$this->formatKeyValuePair($ident,$value));
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Get the line of an array element
|
|
|
|
*
|
|
|
|
* @param array $key The key of the property.
|
|
|
|
* @param $value The value
|
|
|
|
*/
|
|
|
|
private function getArrayEl(array $key)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$line = 0;
|
|
|
|
if (count($key) > 1) {
|
|
|
|
$line = $this->getSectionDeclLine($key[0]) + 1;
|
|
|
|
$validKey = array_slice($key,1,null,true);
|
|
|
|
}
|
|
|
|
$index = array_pop($validKey);
|
|
|
|
$formattedKey = explode('=',$this->formatKeyValuePair($validKey,''));
|
|
|
|
$formattedKey = $formattedKey[0];
|
|
|
|
|
|
|
|
for (;$line < count($this->text);$line++) {
|
|
|
|
$l = $this->text[$line];
|
|
|
|
if ($this->isSectionDecl($l)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (strlen($formattedKey) > 0) {
|
|
|
|
if (preg_match('/^'.$formattedKey.'\[\]/',$l) === 1 ||
|
|
|
|
preg_match('/^'.$formattedKey.'.'.$index.'/',$l) === 1 ) {
|
|
|
|
return $line;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (preg_match('/^'.$index.'/',$l) === 1 ) {
|
|
|
|
return $line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Reset the given key
|
|
|
|
*
|
|
|
|
* Set the key to null, if it already exists. Otherwise do nothing.
|
|
|
|
*
|
|
|
|
* @param array $key
|
|
|
|
*/
|
|
|
|
public function reset(array $key)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$line = $this->getKeyLine($key);
|
|
|
|
if ($line === -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$this->deleteLine($line);
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Change the extended section of $section
|
|
|
|
*/
|
|
|
|
public function setSection($section,$extend = null)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
if (isset($extend)) {
|
|
|
|
$decl = '['.$section.' : '.$extend.']';
|
|
|
|
} else {
|
|
|
|
$decl = '['.$section.']';
|
|
|
|
}
|
|
|
|
$line = $this->getSectionDeclLine($section);
|
|
|
|
if ($line !== -1) {
|
|
|
|
$this->deleteLine($line);
|
|
|
|
$this->insertAtLine($line,$decl);
|
|
|
|
} else {
|
|
|
|
$line = $this->getLastLine();
|
|
|
|
$this->insertAtLine($line,$decl);
|
|
|
|
$this->insertAtLine($line,"");
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Remove the section declarationa of $section
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
public function removeSection($section)
|
|
|
|
{
|
|
|
|
$line = $this->getSectionDeclLine($section);
|
|
|
|
if ($line !== -1) {
|
|
|
|
$this->deleteLine($line);
|
|
|
|
}
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Insert a key
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* Insert the key at the end of the corresponding section.
|
|
|
|
*
|
|
|
|
* @param array $key The key to insert
|
|
|
|
* @param $value The value to insert
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function insert(array $key,$value)
|
|
|
|
{
|
|
|
|
if (count($key) > 1) {
|
|
|
|
// insert into end of section
|
|
|
|
$line = $this->getSectionEnd($key[0]);
|
|
|
|
} else {
|
|
|
|
// insert into section-less space
|
|
|
|
$line = $this->getSectionEnd();
|
|
|
|
}
|
|
|
|
$content = $this->formatKeyValuePair($this->truncateSection($key),$value);
|
|
|
|
$this->insertAtLine($line,$content);
|
|
|
|
}
|
|
|
|
|
2013-08-01 09:18:14 +02:00
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Return the edited text
|
|
|
|
*
|
|
|
|
* @return string The edited text
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
public function getText()
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
// clean up whitespaces
|
|
|
|
$i = count($this->text) - 1;
|
|
|
|
for (;$i >= 0; $i--) {
|
|
|
|
$line = $this->text[$i];
|
|
|
|
if ($this->isSectionDecl($line)) {
|
|
|
|
$i--;
|
|
|
|
$line = $this->text[$i];
|
|
|
|
while ($i >= 0 && preg_match('/^[\s]*$/',$line) === 1) {
|
|
|
|
$this->deleteLine($i);
|
|
|
|
$i--;
|
|
|
|
$line = $this->text[$i];
|
|
|
|
}
|
|
|
|
if ($i !== 0) {
|
|
|
|
$this->insertAtLine($i + 1,'');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return implode("\n",$this->text);
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Insert the text at line $lineNr
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $lineNr The line nr the inserted line should have
|
|
|
|
* @param $toInsert The text that will be inserted
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function insertAtLine($lineNr,$toInsert)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$this->text = IniEditor::insertIntoArray($this->text,$lineNr,$toInsert);
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Update the line $lineNr
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $lineNr
|
|
|
|
* @param $toInsert The lineNr starting at 0
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function updateLine($lineNr,$toInsert)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$this->text[$lineNr] = $toInsert;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Delete the line $lineNr
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $lineNr The lineNr starting at 0
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function deleteLine($lineNr)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$this->text = $this->removeFromArray($this->text,$lineNr);
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Format a key-value pair to an INI file-entry
|
|
|
|
*
|
|
|
|
* @param array $key The key
|
|
|
|
* @param $value The value
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @return string The formatted key-value pair
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function formatKeyValuePair(array $key,$value)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
return implode($this->nestSeparator,$key).'='.$this->_prepareValue($value);
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
/**
|
|
|
|
* Strip the section off of a key, when necessary.
|
|
|
|
*
|
|
|
|
* @param array $key
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function truncateSection(array $key)
|
|
|
|
{
|
|
|
|
if (count($key) > 1) {
|
|
|
|
unset($key[0]);
|
|
|
|
}
|
|
|
|
return $key;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Get the first line after the given $section
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* If section is empty, return the end of section-less
|
|
|
|
* space at the file start.
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $section The name of the section
|
|
|
|
* @return int
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function getSectionEnd($section = null)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
$i = 0;
|
|
|
|
$started = false;
|
|
|
|
if (!isset($section)) {
|
|
|
|
$started = true;
|
|
|
|
}
|
|
|
|
foreach ($this->text as $line) {
|
|
|
|
if ($started) {
|
|
|
|
if (preg_match('/^\[/',$line) === 1) {
|
|
|
|
return $i;
|
|
|
|
}
|
|
|
|
} elseif (preg_match('/^\['.$section.'.*\]/',$line) === 1) {
|
|
|
|
$started = true;
|
|
|
|
}
|
|
|
|
$i++;
|
|
|
|
}
|
|
|
|
if (!$started) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return $i;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Check if the given line contains a section declaration
|
|
|
|
*
|
|
|
|
* @param $lineContent The content of the line
|
|
|
|
* @param string $section The optional section name that will be assumed
|
|
|
|
* @return bool
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function isSectionDecl($lineContent,$section = "")
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
return preg_match('/^\[/'.$section,$lineContent) === 1;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:28:26 +02:00
|
|
|
private function getSectionDeclLine($section)
|
|
|
|
{
|
|
|
|
$i = 0;
|
|
|
|
foreach ($this->text as $line) {
|
|
|
|
if (preg_match('/^\['.$section.'/',$line)) {
|
|
|
|
return $i;
|
|
|
|
}
|
|
|
|
$i++;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Return the line number of the given key
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* When sections are active, return the first matching key in the key's
|
|
|
|
* section, otherwise return the first matching key.
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param array $keys The key and its parents
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function getKeyLine(array $keys)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
// remove section
|
|
|
|
if (count($keys) > 1) {
|
|
|
|
// the key is in a section
|
|
|
|
$section = $keys[0];
|
|
|
|
$key = implode($this->nestSeparator,array_slice($keys,1,null,true));
|
|
|
|
$inSection = false;
|
|
|
|
} else {
|
|
|
|
// section-less key
|
|
|
|
$section = null;
|
|
|
|
$key = implode($this->nestSeparator,$keys);
|
|
|
|
$inSection = true;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
2013-08-06 16:28:26 +02:00
|
|
|
$i = 0;
|
|
|
|
foreach ($this->text as $line) {
|
|
|
|
if ($inSection && preg_match('/^\[/',$line) === 1) {
|
|
|
|
return -1;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
2013-08-06 16:28:26 +02:00
|
|
|
if ($inSection && preg_match('/^'.$key.'/',$line) === 1) {
|
|
|
|
return $i;
|
|
|
|
}
|
|
|
|
if (!$inSection && preg_match('/^\['.$section.'/',$line) === 1) {
|
|
|
|
$inSection = true;
|
|
|
|
}
|
|
|
|
$i++;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
2013-08-06 16:28:26 +02:00
|
|
|
return -1;
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Get the last line number
|
|
|
|
*
|
|
|
|
* @return int The line nr. of the last line
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function getLastLine()
|
|
|
|
{
|
|
|
|
return count($this->text);
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Insert a new element into a specific position of an array
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $array The array to use
|
|
|
|
* @param $pos The target position
|
|
|
|
* @param $element The element to insert
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private static function insertIntoArray($array,$pos,$element)
|
|
|
|
{
|
|
|
|
array_splice($array, $pos, 0, $element);
|
|
|
|
return $array;
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Remove an element from an array
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $array The array to use
|
|
|
|
* @param $pos The position to remove
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
private function removeFromArray($array,$pos)
|
|
|
|
{
|
|
|
|
unset($array[$pos]);
|
|
|
|
return array_values($array);
|
|
|
|
}
|
2013-08-01 09:18:14 +02:00
|
|
|
|
|
|
|
/**
|
2013-08-06 16:28:26 +02:00
|
|
|
* Prepare a value for INI
|
2013-08-01 09:18:14 +02:00
|
|
|
*
|
2013-08-06 16:28:26 +02:00
|
|
|
* @param $value
|
|
|
|
* @return string
|
|
|
|
* @throws Zend_Config_Exception
|
2013-08-01 09:18:14 +02:00
|
|
|
*/
|
2013-08-06 16:28:26 +02:00
|
|
|
protected function _prepareValue($value)
|
2013-08-01 09:18:14 +02:00
|
|
|
{
|
2013-08-06 16:28:26 +02:00
|
|
|
if (is_integer($value) || is_float($value)) {
|
|
|
|
return $value;
|
|
|
|
} elseif (is_bool($value)) {
|
|
|
|
return ($value ? 'true' : 'false');
|
|
|
|
} elseif (strpos($value, '"') === false) {
|
|
|
|
return '"' . $value . '"';
|
|
|
|
} else {
|
|
|
|
/** @see Zend_Config_Exception */
|
|
|
|
require_once 'Zend/Config/Exception.php';
|
|
|
|
throw new Zend_Config_Exception('Value can not contain double quotes "');
|
2013-08-01 09:18:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|