Overview

Packages

  • Pear

Classes

  • Horde_Pear_Exception
  • Horde_Pear_Package_Contents_Ignore_Composite
  • Horde_Pear_Package_Contents_Ignore_Dot
  • Horde_Pear_Package_Contents_Ignore_Git
  • Horde_Pear_Package_Contents_Ignore_Hidden
  • Horde_Pear_Package_Contents_Ignore_Nothing
  • Horde_Pear_Package_Contents_Ignore_Patterns
  • Horde_Pear_Package_Contents_Include_All
  • Horde_Pear_Package_Contents_InstallAs_Horde
  • Horde_Pear_Package_Contents_InstallAs_HordeApplication
  • Horde_Pear_Package_Contents_InstallAs_HordeComponent
  • Horde_Pear_Package_Contents_InstallAs_HordeRole
  • Horde_Pear_Package_Contents_List
  • Horde_Pear_Package_Contents_Role_HordeApplication
  • Horde_Pear_Package_Contents_Role_HordeComponent
  • Horde_Pear_Package_Dependencies
  • Horde_Pear_Package_Task_UpdateContents
  • Horde_Pear_Package_Type_Horde
  • Horde_Pear_Package_Xml
  • Horde_Pear_Package_Xml_Contents
  • Horde_Pear_Package_Xml_Directory
  • Horde_Pear_Package_Xml_Element_Directory
  • Horde_Pear_Package_Xml_Element_File
  • Horde_Pear_Package_Xml_Factory
  • Horde_Pear_Registry
  • Horde_Pear_Remote
  • Horde_Pear_Rest
  • Horde_Pear_Rest_Dependencies
  • Horde_Pear_Rest_Package
  • Horde_Pear_Rest_PackageList
  • Horde_Pear_Rest_Release
  • Horde_Pear_Rest_Releases

Interfaces

  • Horde_Pear_Package_Contents
  • Horde_Pear_Package_Contents_Ignore
  • Horde_Pear_Package_Contents_Include
  • Horde_Pear_Package_Contents_InstallAs
  • Horde_Pear_Package_Contents_Role
  • Horde_Pear_Package_Task
  • Horde_Pear_Package_Type
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Handles a directory in the contents list.
  4:  *
  5:  * PHP version 5
  6:  *
  7:  * @category Horde
  8:  * @package  Pear
  9:  * @author   Gunnar Wrobel <wrobel@pardus.de>
 10:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 11:  * @link     http://pear.horde.org/index.php?package=Pear
 12:  */
 13: 
 14: /**
 15:  * Handles a directory in the contents list.
 16:  *
 17:  * Copyright 2011-2012 Horde LLC (http://www.horde.org/)
 18:  *
 19:  * See the enclosed file COPYING for license information (LGPL). If you
 20:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 21:  *
 22:  * @category Horde
 23:  * @package  Pear
 24:  * @author   Gunnar Wrobel <wrobel@pardus.de>
 25:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 26:  * @link     http://pear.horde.org/index.php?package=Pear
 27:  */
 28: class Horde_Pear_Package_Xml_Directory
 29: {
 30:     /**
 31:      * The directory node.
 32:      *
 33:      * @var Horde_Pear_Package_Xml_Element_Directory
 34:      */
 35:     private $_element;
 36: 
 37:     /**
 38:      * The parent directory.
 39:      *
 40:      * @var Horde_Pear_Package_Xml_Directory
 41:      */
 42:     private $_parent;
 43: 
 44:     /**
 45:      * The list of subdirectories.
 46:      *
 47:      * @var array
 48:      */
 49:     private $_subdirectories = array();
 50: 
 51:     /**
 52:      * The list of files in this directory.
 53:      *
 54:      * @var array
 55:      */
 56:     private $_files;
 57: 
 58:     /**
 59:      * Constructor.
 60:      *
 61:      * @param Horde_Pear_Package_Xml_Element_Directory $dir    The directory element.
 62:      * @param mixed                                    $parent The parent directory
 63:      *                                                         or the XML document.
 64:      */
 65:     public function __construct(Horde_Pear_Package_Xml_Element_Directory $dir,
 66:                                 $parent)
 67:     {
 68:         $this->_element = $dir;
 69:         $this->_parent = $parent;
 70:         $subdirectories = $this->_element->getSubdirectories();
 71:         foreach ($subdirectories as $name => $element) {
 72:             $this->_subdirectories[$name] = $this->_create($element, $this);
 73:         }
 74:         $this->_files = $this->_element->getFiles();
 75:     }
 76: 
 77:     /**
 78:      * Return the directory node.
 79:      *
 80:      * @return DOMNode The directory node.
 81:      */
 82:     public function getDirectory()
 83:     {
 84:         return $this->_element;
 85:     }
 86: 
 87:     /**
 88:      * Return the list of files in this hierarchy.
 89:      *
 90:      * @return array The file list.
 91:      */
 92:     public function getFiles()
 93:     {
 94:         $result = array();
 95:         foreach ($this->_subdirectories as $directory) {
 96:             $result = array_merge(
 97:                 $result,
 98:                 array_map(
 99:                     array($this, '_prependDirectory'),
100:                     $directory->getFiles()
101:                 )
102:             );
103:         }
104:         $result = array_merge(
105:             $result,
106:             array_map(
107:                 array($this, '_prependDirectory'),
108:                 array_keys($this->_files)
109:             )
110:         );
111:         return $result;
112:     }
113: 
114:     /**
115:      * Create a new directory handler.
116:      *
117:      * @param Horde_Pear_Package_Xml_Element_Directory $element The represented element.
118:      * @param Horde_Pear_Package_Xml_Directory         $parent  The parent directory.
119:      *
120:      * @return Horde_Pear_Package_Xml_Directory
121:      */
122:     private function _getRoot()
123:     {
124:         if ($this->_parent instanceOf Horde_Pear_Package_Xml_Directory) {
125:             return $this->_parent->_getRoot();
126:         } else {
127:             return $this->_parent;
128:         }
129:     }
130: 
131:     /**
132:      * Create a new directory handler.
133:      *
134:      * @param Horde_Pear_Package_Xml_Element_Directory $element The represented element.
135:      * @param Horde_Pear_Package_Xml_Directory         $parent  The parent directory.
136:      *
137:      * @return Horde_Pear_Package_Xml_Directory
138:      */
139:     private function _create(Horde_Pear_Package_Xml_Element_Directory $element,
140:                              Horde_Pear_Package_Xml_Directory $parent)
141:     {
142:         return $this->_getRoot()->createDirectory($element, $parent);
143:     }
144: 
145:     /**
146:      * Prepend the directory name of this directory to the path name.
147:      *
148:      * @param string $path The input path name.
149:      *
150:      * @return The completed path.
151:      */
152:     private function _prependDirectory($path)
153:     {
154:         return strtr(
155:             $this->_element->getName() . '/' . $path, array('//' => '/')
156:         );
157:     }
158: 
159:     /**
160:      * Add a file to the list.
161:      *
162:      * @param string $file   The file name.
163:      * @param array  $params Additional file parameters.
164:      *
165:      * @return NULL
166:      */
167:     public function addFile($file, $params)
168:     {
169:         $this->getParent(explode('/', dirname($file)))
170:             ->_addFile($file, $params);
171:     }
172: 
173:     /**
174:      * Add a file to the list.
175:      *
176:      * @param string $file   The file name.
177:      * @param array  $params Additional file parameters.
178:      *
179:      * @return NULL
180:      */
181:     private function _addFile($file, $params)
182:     {
183:         $this->_files[basename($file)] = $this->_element->insertFile(
184:             basename($file),
185:             $params['role'],
186:             $this->_getFileInsertionPoint(basename($file))
187:         );
188:     }
189: 
190:     /**
191:      * Delete a file from the list.
192:      *
193:      * @param string $file The file name.
194:      *
195:      * @return NULL
196:      */
197:     public function deleteFile($file)
198:     {
199:         $this->getParent(explode('/', dirname($file)))->_deleteFile($file);
200:     }
201: 
202:     /**
203:      * Delete a file from the list.
204:      *
205:      * @param string $file The file name.
206:      *
207:      * @return NULL
208:      */
209:     private function _deleteFile($file)
210:     {
211:         $this->_files[basename($file)]->delete();
212:         unset($this->_files[basename($file)]);
213:         $this->_prune();
214:     }
215: 
216:     /**
217:      * Delete a subdirectory from the list.
218:      *
219:      * @param string $dir The directory name.
220:      *
221:      * @return NULL
222:      */
223:     private function _deleteSubdirectory($dir)
224:     {
225:         unset($this->_subdirectories[$dir]);
226:         $this->_prune();
227:     }
228: 
229:     /**
230:      * Prune this directory if it is empty.
231:      *
232:      * @return NULL
233:      */
234:     private function _prune()
235:     {
236:         if (empty($this->_files) && empty($this->_subdirectories)) {
237:             $this->_element->delete();
238:             if ($this->_parent instanceOf Horde_Pear_Package_Xml_Directory) {
239:                 $this->_parent->_deleteSubdirectory($this->_element->getName());
240:             }
241:         }
242:     }
243: 
244:     /**
245:      * Ensure the provided path hierarchy.
246:      *
247:      * @param array $tree The path elements that are required.
248:      *
249:      * @return DOMNode The parent directory for the file.
250:      */
251:     public function getParent($tree)
252:     {
253:         $next = array_shift($tree);
254:         while ($next === '') {
255:             $next = array_shift($tree);
256:         }
257:         if (empty($tree) && !strlen($next)) {
258:             return $this;
259:         }
260:         if (!isset($this->_subdirectories[$next])) {
261:             $this->_subdirectories[$next] = $this->_create(
262:                 $this->_element->insertSubDirectory(
263:                     $next,
264:                     $this->_getDirectoryInsertionPoint($next)
265:                 ),
266:                 $this
267:             );
268:         }
269:         return $this->_subdirectories[$next]->getParent($tree);
270:     }
271: 
272:     /**
273:      * Identify the insertion point for a new directory.
274:      *
275:      * @param string $new The key for the new element.
276:      *
277:      * @return mixed The insertion point.
278:      */
279:     private function _getDirectoryInsertionPoint($new)
280:     {
281:         $keys = array_keys($this->_subdirectories);
282:         array_push($keys, $new);
283:         usort($keys, array($this, '_fileOrder'));
284:         $pos = array_search($new, $keys);
285:         if ($pos < count($this->_subdirectories)) {
286:             return $this->_subdirectories[$keys[$pos + 1]]->getDirectory()->getDirectoryNode();
287:         } else {
288:             if (empty($this->_files)) {
289:                 return null;
290:             } else {
291:                 $keys = array_keys($this->_files);
292:                 usort($keys, array($this, '_fileOrder'));
293:                 return $this->_files[$keys[0]]->getFileNode();
294:             }
295:         }
296:     }
297: 
298:     /**
299:      * Sort order for files in the content list.
300:      *
301:      * @param string $a First path.
302:      * @param string $b Second path.
303:      *
304:      * @return int Sort comparison result.
305:      */
306:     private function _fileOrder($a, $b)
307:     {
308:         return strnatcasecmp($a, $b);
309:     }
310: 
311:     /**
312:      * Identify the insertion point for a new file.
313:      *
314:      * @param string $new The key for the new element.
315:      *
316:      * @return mixed The insertion point.
317:      */
318:     private function _getFileInsertionPoint($new)
319:     {
320:         $keys = array_keys($this->_files);
321:         array_push($keys, $new);
322:         usort($keys, array($this, '_fileOrder'));
323:         $pos = array_search($new, $keys);
324:         if ($pos < count($this->_files)) {
325:             return $this->_files[$keys[$pos + 1]]->getFileNode();
326:         } else {
327:             return null;
328:         }
329:     }
330: }
API documentation generated by ApiGen