1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23: namespace picon;
24:
25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
42: class PageMap
43: {
44: const PAGE_MAP_RESOURCE_NAME = 'pagemap';
45: const PAGE_MAP_MOUNTED_RESOURCE_NAME ='map_mounted';
46: private $pages;
47: private $pageId = 1;
48: private $pageInstances = array();
49: private static $self;
50: private $mountedPages;
51:
52: 53: 54: 55: 56:
57: private function __construct()
58: {
59:
60: }
61:
62: public function initialise()
63: {
64: if(isset($this->pages) && $this->pages!=null)
65: {
66: return;
67: }
68: $this->mountedPages = array();
69: $this->scanPages();
70: }
71:
72: private function scanPages()
73: {
74: ApplicationInitializer::loadAssets(ASSETS_DIRECTORY);
75: $this->pages = array();
76: $scanner = new ClassScanner(array(new SubClassRule('\picon\WebPage')));
77:
78: $pages = $scanner->scanForName();
79: foreach($pages as $pageName)
80: {
81: $this->addToPath($pageName, $pageName);
82: }
83:
84: $pathScanner = new ClassScanner(array(new AnnotationRule('Path')));
85:
86: foreach($pathScanner->scanForReflection($pages) as $reflection)
87: {
88: $pathAnnoation = $reflection->getAnnotation('Path');
89: $path = $pathAnnoation->path;
90:
91: if(empty($path))
92: {
93: throw new \UnexpectedValueException(sprintf("Expecting path annoation to have a path value for class %s", $reflection->getName()));
94: }
95:
96: $this->addToPath($path, $reflection->getNamespaceName().'\\'.$reflection->getName());
97: }
98: PiconApplication::get()->getPageMapInitializationListener()->onInitialize($this);
99: }
100:
101: private function addToPath($path, $pageName)
102: {
103: if(array_key_exists($path, $this->pages))
104: {
105: throw new \DuplicatePageDefinitionException(sprintf("A page with path %s already exists and cannot be used again.", $path));
106: }
107: $this->pages[$path] = $pageName;
108: }
109:
110: 111: 112: 113: 114: 115:
116: public static function getPageMap()
117: {
118: return self::get()->pages;
119: }
120:
121: public static function getNextPageId()
122: {
123: $self = self::get();
124: $self->pageId++;
125: return 'page'.$self->pageId;
126: }
127:
128: public function getPageById($id)
129: {
130: if(array_key_exists($id, $this->pageInstances))
131: {
132: return $this->pageInstances[$id];
133: }
134:
135: $page = CacheManager::loadResource($id, CacheManager::SESSION_SCOPE);
136:
137: if($page!=null)
138: {
139: $this->addOrUpdate($page);
140: return $page;
141: }
142: else
143: {
144: return null;
145: }
146: }
147:
148: public static function get()
149: {
150: if (!isset(self::$self))
151: {
152: if (isset($_SESSION['page_map']))
153: {
154: self::$self = unserialize($_SESSION['page_map']);
155: }
156: else
157: {
158: self::$self = new self();
159: }
160: }
161: return self::$self;
162: }
163:
164: public function addOrUpdate(WebPage &$page)
165: {
166: $instances = &$this->pageInstances;
167: $instances[$page->getId()] = $page;
168: }
169:
170: public function __sleep()
171: {
172: CacheManager::saveResource(self::PAGE_MAP_RESOURCE_NAME, $this->pages, CacheManager::APPLICATION_SCOPE);
173: CacheManager::saveResource(self::PAGE_MAP_MOUNTED_RESOURCE_NAME, $this->mountedPages, CacheManager::APPLICATION_SCOPE);
174: return array('pageId');
175: }
176:
177: public function __wakeup()
178: {
179: $this->pages = CacheManager::loadResource(self::PAGE_MAP_RESOURCE_NAME, CacheManager::APPLICATION_SCOPE);
180: $this->mountedPages = CacheManager::loadResource(self::PAGE_MAP_MOUNTED_RESOURCE_NAME, CacheManager::APPLICATION_SCOPE);
181: }
182:
183: public function __destruct()
184: {
185: foreach($this->pageInstances as $pageid => $page)
186: {
187: CacheManager::saveResource($pageid, $page, CacheManager::SESSION_SCOPE);
188: }
189: $_SESSION['page_map'] = serialize($this);
190: }
191:
192: public function mount($path, Identifier $page)
193: {
194: if(!$page->of(WebPage::getIdentifier()))
195: {
196: throw new \InvalidArgumentException('Expected an identifier of a web page');
197: }
198: if($this->isMounted($path))
199: {
200: throw new \InvalidArgumentException(sprintf('The path %s is already mounted', $path));
201: }
202: $this->addToPath($path, $page->getFullyQualifiedName());
203: $this->mountedPages[] = $path;
204: }
205:
206: public function isMounted($path)
207: {
208: return in_array($path, $this->mountedPages);
209: }
210:
211: public function unMount($path)
212: {
213: if($this->isMounted($path))
214: {
215: unset($this->pages[$path]);
216: $key = array_search($path, $this->mountedPages);
217: unset($this->mountedPages[$key]);
218: }
219: }
220:
221: public function getMounted()
222: {
223: return $this->mountedPages;
224: }
225: }
226:
227: ?>
228: