1<?php
2
3/**
4 * Responsible for creating definition caches.
5 */
6class HTMLPurifier_DefinitionCacheFactory
7{
8    /**
9     * @type array
10     */
11    protected $caches = array('Serializer' => array());
12
13    /**
14     * @type array
15     */
16    protected $implementations = array();
17
18    /**
19     * @type HTMLPurifier_DefinitionCache_Decorator[]
20     */
21    protected $decorators = array();
22
23    /**
24     * Initialize default decorators
25     */
26    public function setup()
27    {
28        $this->addDecorator('Cleanup');
29    }
30
31    /**
32     * Retrieves an instance of global definition cache factory.
33     * @param HTMLPurifier_DefinitionCacheFactory $prototype
34     * @return HTMLPurifier_DefinitionCacheFactory
35     */
36    public static function instance($prototype = null)
37    {
38        static $instance;
39        if ($prototype !== null) {
40            $instance = $prototype;
41        } elseif ($instance === null || $prototype === true) {
42            $instance = new HTMLPurifier_DefinitionCacheFactory();
43            $instance->setup();
44        }
45        return $instance;
46    }
47
48    /**
49     * Registers a new definition cache object
50     * @param string $short Short name of cache object, for reference
51     * @param string $long Full class name of cache object, for construction
52     */
53    public function register($short, $long)
54    {
55        $this->implementations[$short] = $long;
56    }
57
58    /**
59     * Factory method that creates a cache object based on configuration
60     * @param string $type Name of definitions handled by cache
61     * @param HTMLPurifier_Config $config Config instance
62     * @return mixed
63     */
64    public function create($type, $config)
65    {
66        $method = $config->get('Cache.DefinitionImpl');
67        if ($method === null) {
68            return new HTMLPurifier_DefinitionCache_Null($type);
69        }
70        if (!empty($this->caches[$method][$type])) {
71            return $this->caches[$method][$type];
72        }
73        if (isset($this->implementations[$method]) &&
74            class_exists($class = $this->implementations[$method], false)) {
75            $cache = new $class($type);
76        } else {
77            if ($method != 'Serializer') {
78                trigger_error("Unrecognized DefinitionCache $method, using Serializer instead", E_USER_WARNING);
79            }
80            $cache = new HTMLPurifier_DefinitionCache_Serializer($type);
81        }
82        foreach ($this->decorators as $decorator) {
83            $new_cache = $decorator->decorate($cache);
84            // prevent infinite recursion in PHP 4
85            unset($cache);
86            $cache = $new_cache;
87        }
88        $this->caches[$method][$type] = $cache;
89        return $this->caches[$method][$type];
90    }
91
92    /**
93     * Registers a decorator to add to all new cache objects
94     * @param HTMLPurifier_DefinitionCache_Decorator|string $decorator An instance or the name of a decorator
95     */
96    public function addDecorator($decorator)
97    {
98        if (is_string($decorator)) {
99            $class = "HTMLPurifier_DefinitionCache_Decorator_$decorator";
100            $decorator = new $class;
101        }
102        $this->decorators[$decorator->name] = $decorator;
103    }
104}
105
106// vim: et sw=4 sts=4
107