vendor/mondator/src/Mandango/Mondator/Mondator.php
changeset 18 c85b9d1ddf19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/mondator/src/Mandango/Mondator/Mondator.php	Thu Oct 27 05:47:14 2011 +0200
@@ -0,0 +1,311 @@
+<?php
+
+/*
+ * This file is part of Mandango.
+ *
+ * (c) Pablo Díez <pablodip@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Mandango\Mondator;
+
+/**
+ * Mondator.
+ *
+ * @author Pablo Díez <pablodip@gmail.com>
+ *
+ * @api
+ */
+class Mondator
+{
+    private $configClasses;
+    private $extensions;
+    private $outputs;
+
+    /**
+     * Constructor.
+     *
+     * @api
+     */
+    public function __construct()
+    {
+        $this->configClasses = array();
+        $this->extensions = array();
+        $this->options = array();
+    }
+
+    /**
+     * Set a config class.
+     *
+     * @param string $class       The class.
+     * @param array  $configClass The config class.
+     *
+     * @api
+     */
+    public function setConfigClass($class, array $configClass)
+    {
+        $this->configClasses[$class] = $configClass;
+    }
+
+    /**
+     * Set the config classes.
+     *
+     * @param array $configClasses An array of config classes (class as key and config class as value).
+     *
+     * @api
+     */
+    public function setConfigClasses(array $configClasses)
+    {
+        $this->configClasses = array();
+        foreach ($configClasses as $class => $configClass) {
+            $this->setConfigClass($class, $configClass);
+        }
+    }
+
+    /**
+     * Returns if a config class exists.
+     *
+     * @param string $class The class.
+     *
+     * @return bool Returns if the config class exists.
+     *
+     * @api
+     */
+    public function hasConfigClass($class)
+    {
+        return array_key_exists($class, $this->configClasses);
+    }
+
+    /**
+     * Returns the config classes.
+     *
+     * @return array The config classes.
+     *
+     * @api
+     */
+    public function getConfigClasses()
+    {
+        return $this->configClasses;
+    }
+
+    /**
+     * Returns a config class.
+     *
+     * @param string $class The class.
+     *
+     * @return array The config class.
+     *
+     * @throws \InvalidArgumentException If the config class does not exists.
+     *
+     * @api
+     */
+    public function getConfigClass($class)
+    {
+        if (!$this->hasConfigClass($class)) {
+            throw new \InvalidArgumentException(sprintf('The config class "%s" does not exists.', $class));
+        }
+
+        return $this->configClasses[$class];
+    }
+
+    /**
+     * Add a extension.
+     *
+     * @param Mandango\Mondator\Extension $extension The extension.
+     *
+     * @api
+     */
+    public function addExtension(Extension $extension)
+    {
+        $this->extensions[] = $extension;
+    }
+
+    /**
+     * Set the extensions.
+     *
+     * @param array $extensions An array of extensions.
+     *
+     * @api
+     */
+    public function setExtensions(array $extensions)
+    {
+        $this->extensions = array();
+        foreach ($extensions as $extension) {
+            $this->addExtension($extension);
+        }
+    }
+
+    /**
+     * Returns the extensions.
+     *
+     * @return array The extensions.
+     *
+     * @api
+     */
+    public function getExtensions()
+    {
+        return $this->extensions;
+    }
+
+    /**
+     * Generate the containers.
+     *
+     * @return array The containers.
+     *
+     * @api
+     */
+    public function generateContainers()
+    {
+        $containers = array();
+        $containers['_global'] = new Container();
+
+        // global extensions
+        $globalExtensions = $this->getExtensions();
+
+        // configClasses
+        $configClasses = new \ArrayObject();
+        foreach ($this->getConfigClasses() as $class => $configClass) {
+            $configClasses[$class] = new \ArrayObject($configClass);
+        }
+
+        // classes extensions
+        $classesExtensions = new \ArrayObject();
+        $this->generateContainersClassesExtensions($globalExtensions, $classesExtensions, $configClasses);
+
+        // config class process
+        foreach ($classesExtensions as $class => $classExtensions) {
+            foreach ($classExtensions as $classExtension) {
+                $classExtension->configClassProcess($class, $configClasses);
+            }
+        }
+
+        // pre global process
+        foreach ($globalExtensions as $globalExtension) {
+            $globalExtension->preGlobalProcess($configClasses, $containers['_global']);
+        }
+
+        // class process
+        foreach ($classesExtensions as $class => $classExtensions) {
+            $containers[$class] = $container = new Container();
+            foreach ($classExtensions as $classExtension) {
+                $classExtension->classProcess($class, $configClasses, $container);
+            }
+        }
+
+        // post global process
+        foreach ($globalExtensions as $globalExtension) {
+            $globalExtension->postGlobalProcess($configClasses, $containers['_global']);
+        }
+
+        return $containers;
+    }
+
+    private function generateContainersClassesExtensions($globalExtensions, $classesExtensions, $configClasses)
+    {
+        foreach ($configClasses as $class => $configClass) {
+            if (isset($classesExtensions[$class])) {
+                continue;
+            }
+
+            $classesExtensions[$class] = $classExtensions = new \ArrayObject($globalExtensions);
+            $this->generateContainersNewClassExtensions($class, $classExtensions, $configClasses);
+
+            foreach ($classExtensions as $classExtension) {
+                $newConfigClasses = new \ArrayObject();
+                $classExtension->newConfigClassesProcess($class, $configClasses, $newConfigClasses);
+
+                foreach ($newConfigClasses as $newClass => $newConfigClass) {
+                    if (isset($classesExtensions[$newClass])) {
+                        throw new \RuntimeException(sprintf('The class "%s" has several config classes.', $class));
+                    }
+                    $configClasses[$newClass] = new \ArrayObject($newConfigClass);
+                }
+
+                $this->generateContainersClassesExtensions($globalExtensions, $classesExtensions, $configClasses);
+            }
+        }
+    }
+
+    private function generateContainersNewClassExtensions($class, $classExtensions, $configClasses, $extensions = null)
+    {
+        if (null === $extensions) {
+            $extensions = $classExtensions;
+        }
+
+        foreach ($extensions as $extension) {
+            $newClassExtensions = new \ArrayObject();
+            $extension->newClassExtensionsProcess($class, $configClasses, $newClassExtensions);
+
+            foreach ($newClassExtensions as $newClassExtension) {
+                if (!$newClassExtension instanceof ClassExtension) {
+                    throw new \RuntimeException(sprintf('Some class extension of the class "%s" in the extension "%s" is not an instance of ClassExtension.', $class, get_class($extension)));
+                }
+                if ($newClassExtension instanceof Extension) {
+                    throw new \RuntimeException(sprintf('Some class extension of the class "%s" in the extension "%s" is a instance of Extension, and it can be only a instance of ClassExtension.', $class, get_class($extension)));
+                }
+
+                $classExtensions[] = $newClassExtension;
+                $this->generateContainersNewClassExtensions($class, $classExtensions, $configClasses, $newClassExtension);
+            }
+        }
+    }
+
+    /**
+     * Dump containers.
+     *
+     * @param array $containers An array of containers.
+     *
+     * @api
+     */
+    public function dumpContainers(array $containers)
+    {
+        // directories
+        foreach ($containers as $container) {
+            foreach ($container->getDefinitions() as $name => $definition) {
+                $output = $definition->getOutput();
+                $dir    = $output->getDir();
+
+                if (!file_exists($dir) && false === @mkdir($dir, 0777, true)) {
+                    throw new \RuntimeException(sprintf('Unable to create the %s directory (%s).', $name, $dir));
+                }
+
+                if (!is_writable($dir)) {
+                    throw new \RuntimeException(sprintf('Unable to write in the %s directory (%s).', $name, $dir));
+                }
+            }
+        }
+
+        // output
+        foreach ($containers as $container) {
+            foreach ($container->getDefinitions() as $name => $definition) {
+                $output = $definition->getOutput($name);
+                $dir    = $output->getDir();
+
+                $file = $dir.DIRECTORY_SEPARATOR.$definition->getClassName().'.php';
+
+                if (!file_exists($file) || $output->getOverride()) {
+                    $dumper  = new Dumper($definition);
+                    $content = $dumper->dump();
+
+                    $tmpFile = tempnam(dirname($file), basename($file));
+                    if (false === @file_put_contents($tmpFile, $content) || !@rename($tmpFile, $file)) {
+                        throw new \RuntimeException(sprintf('Failed to write the file "%s".', $file));
+                    }
+                    chmod($file, 0644);
+                }
+            }
+        }
+    }
+
+    /**
+     * Generate and dump the containers.
+     *
+     * @api
+     */
+    public function process()
+    {
+        $this->dumpContainers($this->generateContainers());
+    }
+}