memcache_ui.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <?php
  2. class GraphicsContext {
  3. protected $palette = array();
  4. }
  5. /**
  6. * A wrapper for XML elements.
  7. */
  8. class Element {
  9. public $name = NULL;
  10. public $attributes = array();
  11. public $value = NULL;
  12. public $new_line; // Add a new line after element
  13. public function __construct($name, $attr = NULL, $value = NULL) {
  14. $this->name = $name;
  15. $this->attributes = $attr;
  16. $this->value = $value;
  17. }
  18. public function __toString() {
  19. $ret = '<'. $this->name;
  20. if (!empty($this->attributes)) {
  21. $ret .= ' ' . implode(' ', $this->attributes);
  22. }
  23. if (empty($this->value)) {
  24. $ret .= ' />';
  25. }
  26. else {
  27. $ret .= '>';
  28. if ($this->value instanceof Element) {
  29. $ret .= (string) $this->value; // force __toString()
  30. }
  31. elseif (is_array($this->value)) {
  32. $ret .= implode('', $this->value);
  33. }
  34. else {
  35. $ret .= $this->value;
  36. }
  37. $ret .= "</$this->name>";
  38. }
  39. return $ret;
  40. }
  41. }
  42. class Context {
  43. /**
  44. * Directory in which the current script is located.
  45. *
  46. * Follow symlinks if applicable, to obtain the actual implementation
  47. * directory, instead of just the main file symlink, in order to find the
  48. * other files.
  49. *
  50. * @var string
  51. */
  52. protected $dirname;
  53. /**
  54. * Requested path: <$PHP_SELF>?q=a/b/c
  55. *
  56. * @var string
  57. */
  58. protected $path = NULL;
  59. /**
  60. * Graphics context
  61. *
  62. * @var GraphicsContext
  63. */
  64. protected $gc = NULL;
  65. public function getDirname() {
  66. if (!isset($this->dirname)) {
  67. $this->dirname = dirname(__FILE__);
  68. }
  69. return $this->dirname;
  70. }
  71. /**
  72. * Return the requested path.
  73. *
  74. * @param string $path
  75. */
  76. public function getPath() {
  77. if (!isset($this->path)) {
  78. $this->path = empty($_GET['q']) ? '' : $_GET['q'];
  79. }
  80. return $this->path;
  81. }
  82. /**
  83. * User information: logged or not ?
  84. *
  85. * @var boolean
  86. */
  87. protected $user = FALSE;
  88. function __construct() {
  89. $this->getPath();
  90. }
  91. function __toString() {
  92. $ret = '<pre>' . print_r($this, TRUE) . '</pre>';
  93. return $ret;
  94. }
  95. }
  96. class Page extends Element {
  97. /**
  98. * @var Context
  99. */
  100. protected $context;
  101. /**
  102. * @var array
  103. */
  104. protected $styles;
  105. /**
  106. * @var array
  107. */
  108. protected $finalized = array();
  109. public function getHeader($name) {
  110. }
  111. public function setHeader($name, $value) {
  112. }
  113. public function getHead() {
  114. $this->finalizeHead();
  115. $head = new Element('head', NULL, $this->head);
  116. $ret = (string) $head;
  117. return $ret;
  118. }
  119. public function setHead($item) {
  120. }
  121. public function getBody() {
  122. $this->finalizeBody();
  123. $body = new Element('body', NULL, $this->body);
  124. $ret = (string) $body;
  125. return $ret;
  126. }
  127. public function setBody($fragment) {
  128. $this->body[] = $fragment;
  129. }
  130. public function finalizeHead() {
  131. if (isset($this->finalized['head'])) {
  132. throw new Exception('Attempt to finalize already finalized head');
  133. }
  134. $cssLink = new Element('link', array(
  135. 'rel' => 'stylesheet',
  136. 'type' => 'text/css',
  137. 'href' => $this->context->getPath() .'/memcache_ui.css',
  138. ));
  139. $this->setHead($cssLink);
  140. $this->finalized['head'] = TRUE;
  141. }
  142. public function finalizeBody() {
  143. if (isset($this->finalized['body'])) {
  144. throw new Exception('Attempt to finalize already finalized body');
  145. }
  146. $this->finalized['body'] = TRUE;
  147. }
  148. public function render() {
  149. $html = new Element('html', NULL, $this->getHead() . $this->getBody());
  150. return (string) $html;
  151. }
  152. /**
  153. * Page constructor.
  154. *
  155. * @param Context $context
  156. * @param array $item
  157. * A router info array.
  158. *
  159. * @see Router::getInfo()
  160. */
  161. public function __construct(Context $context, array $item) {
  162. parent::__construct('html');
  163. $this->context = $context;
  164. }
  165. }
  166. class Router {
  167. function getInfo() {
  168. $ret = array(
  169. '^server/(\w+)/flush/(\w+)$' => array(
  170. 'page class' => 'page_server_flush',
  171. 'page arguments' => array('$1', '$2'),
  172. 'title callback' => 'title_server',
  173. 'title arguments' => 'page arguments',
  174. ),
  175. '^server/(\w+)/flush$' => array(
  176. 'page class' => 'page_server_flush',
  177. 'page arguments' => array('$1'),
  178. 'title callback' => 'title_server',
  179. 'title arguments' => 'page arguments',
  180. ),
  181. '^server/(\w+)/slab/(\d+)$' => array(
  182. 'page class' => 'page_slab_view',
  183. 'page arguments' => array('$1', '$2'),
  184. 'title callback' => 'title_slab',
  185. 'title arguments' => 'page arguments',
  186. ),
  187. '^server/(\w+)/key/(.+)/delete/(\w+)$' => array(
  188. 'page class' => 'page_variable_delete_confirm',
  189. 'page arguments' => array('$1', '$2', '$3'),
  190. 'title callback' => 'title_variable',
  191. 'title arguments' => 'page arguments',
  192. ),
  193. '^server/(\w+)/key/(.+)/delete$' => array(
  194. 'page class' => 'page_variable_delete_form',
  195. 'page arguments' => array('$1', '$2'),
  196. 'title callback' => 'title_variable',
  197. 'title arguments' => 'page arguments',
  198. ),
  199. '^server/(\w+)/key/(.+)/dump$' => array(
  200. 'page class' => 'page_variable_view_php',
  201. 'page arguments' => array('$1', '$2'),
  202. 'title callback' => 'title_variable',
  203. 'title arguments' => 'page arguments',
  204. ),
  205. '^server/(\w+)/key/(.+)/php$' => array(
  206. 'page class' => 'page_variable_view_php',
  207. 'page arguments' => array('$1', '$2'),
  208. 'title callback' => 'title_variable',
  209. 'title arguments' => 'page arguments',
  210. ),
  211. '^server/(\w+)/key/(.+)$' => array(
  212. 'page class' => 'page_variable_view_text',
  213. 'page arguments' => array('$1', '$2'),
  214. 'title callback' => 'title_variable',
  215. 'title arguments' => 'page arguments',
  216. ),
  217. '^slabs$' => array(
  218. 'page class' => 'page_slab_overview',
  219. 'title' => 'Slabs per server',
  220. ),
  221. '^$' => array(
  222. 'page class' => 'Page_Main',
  223. 'title' => 'Overview',
  224. ),
  225. );
  226. return $ret;
  227. }
  228. function getRoute() {
  229. $found = FALSE;
  230. $path = $this->context->getPath();
  231. // echo "<pre>Path: [". $path . "]</p>";
  232. $matches = array();
  233. foreach ($this->getInfo() as $regex => $info) {
  234. $regex = "@$regex@";
  235. $count = preg_match($regex, $path, $matches);
  236. // echo "<pre>$regex: $count";
  237. // if ($count) print_r($matches);
  238. // echo "</pre>";
  239. if ($count) {
  240. $found = TRUE;
  241. break;
  242. }
  243. }
  244. if ($found) {
  245. // echo "Found at $regex<pre>";
  246. // print_r($info);
  247. $regexes = array_fill(0, count($info['page arguments']), $regex);
  248. $paths = array_fill(0, count($info['page arguments']), $path);
  249. $info['page arguments'] = preg_replace($regexes, $info['page arguments'], $paths);
  250. }
  251. else {
  252. $info = NULL;
  253. }
  254. return $info;
  255. }
  256. function __construct(Context $context) {
  257. $this->context = $context;
  258. }
  259. }
  260. class Page_Main extends Page {
  261. function finalizeBody() {
  262. $hello = new Element('p', NULL, 'Hello world');
  263. $this->setBody($hello);
  264. parent::finalizeBody();
  265. }
  266. }
  267. function main() {
  268. $context = new Context();
  269. // echo "<p>Dirname: [". $context->getDirname() . "]</p>";
  270. // echo "<p>Path: [". $context->getPath() . "]</p><pre>";
  271. $router = new Router($context);
  272. $item = $router->getRoute();
  273. $page = new $item['page class']($context, $item);
  274. // echo '<pre>'; var_dump($page);
  275. echo $page->render();
  276. }
  277. try {
  278. main();
  279. }
  280. catch (Exception $e) {
  281. echo '<pre>';
  282. echo $e->getMessage() . PHP_EOL;
  283. echo $e->getTraceAsString();
  284. echo "</pre>";
  285. }