Subversion Repositories PHPX

Rev

Rev 57 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
27 PointedEar 1
<?php
2
 
51 PointedEar 3
namespace PointedEars\PHPX;
4
 
64 PointedEar 5
if (!defined('\\DIRECTORY_SEPARATOR'))
57 PointedEar 6
{
7
        define('DIRECTORY_SEPARATOR', '/');
8
}
9
 
52 PointedEar 10
function autoload ($class)
11
{
57 PointedEar 12
        if (\strpos($class, '..') !== false)
52 PointedEar 13
        {
14
                throw new \InvalidArgumentException(
57 PointedEar 15
                        "Refusing to load unsafe class '{$class}'");
52 PointedEar 16
        }
27 PointedEar 17
 
57 PointedEar 18
        require_once \str_replace('\\', DIRECTORY_SEPARATOR,
19
                \preg_replace(
20
                        '#^' . \preg_quote(__NAMESPACE__, '#') .'#',
21
                        __DIR__,
22
                        $class
23
                )
52 PointedEar 24
        ) . '.php';
25
}
26
 
27
\spl_autoload_register(__NAMESPACE__ . '\\autoload');
28
 
27 PointedEar 29
/**
30
 * Basic application class
31
 *
32
 * @author Thomas Lahn
33
 */
34
class Application
35
{
36
  /**
37
   * Relative path to the controllers directory
38
   * @var string
39
   */
40
  protected $_controllerPath = 'application/controllers';
45 PointedEar 41
 
27 PointedEar 42
  /**
43
   * Default controller of the application
44
   * @var string
45
   */
46
  protected $_defaultController = 'Index';
45 PointedEar 47
 
27 PointedEar 48
  /**
49
   * Registry key for the default database of the application
50
   * @var string
51
   */
52
  protected $_defaultDatabase;
45 PointedEar 53
 
27 PointedEar 54
  /**
55
   * Currently active controller of this application
56
   * @var Controller
57
   */
58
  protected $_currentController;
45 PointedEar 59
 
27 PointedEar 60
  /**
61
   * Singleton
62
   *
63
   * @var Application
64
   */
65
  private static $_instance;
45 PointedEar 66
 
52 PointedEar 67
  protected function __construct ()
27 PointedEar 68
  {
69
    /* Singleton pattern */
70
  }
45 PointedEar 71
 
27 PointedEar 72
  /**
73
   * Gets a reference to the <code>Application</code> instance
74
   *
75
   * @param Application $instance
76
   *   The instance to be used as application.  The default is a new
77
   *   application.  This parameter is ignored if the application was
78
   *   already initialized.
79
   * @return Application
80
   */
52 PointedEar 81
  public static function getInstance (Application $instance = null)
27 PointedEar 82
  {
31 PointedEar 83
    if (self::$_instance === null)
27 PointedEar 84
    {
85
      self::$_instance = ($instance === null) ? new self() : $instance;
86
    }
45 PointedEar 87
 
27 PointedEar 88
    return self::$_instance;
89
  }
45 PointedEar 90
 
31 PointedEar 91
  /**
92
   * Getter for properties
93
   *
94
   * @param string $name
95
   * @throws ModelPropertyException
96
   * @return mixed
97
   */
52 PointedEar 98
  public function __get ($name)
31 PointedEar 99
  {
100
    /* Support for Object-Relational Mappers */
52 PointedEar 101
    if (\strpos($name, 'persistent') === 0)
31 PointedEar 102
    {
52 PointedEar 103
      $class = \get_class($this);
34 PointedEar 104
      return $class::${$name};
31 PointedEar 105
    }
45 PointedEar 106
 
52 PointedEar 107
    $method = 'get' . \ucfirst($name);
45 PointedEar 108
 
52 PointedEar 109
    if (\method_exists($this, $method))
31 PointedEar 110
    {
111
      return $this->$method();
112
    }
45 PointedEar 113
 
52 PointedEar 114
    if (\property_exists($this, "_$name"))
31 PointedEar 115
    {
116
      return $this->{"_$name"};
117
    }
45 PointedEar 118
 
31 PointedEar 119
    return $this->$name;
120
  }
45 PointedEar 121
 
27 PointedEar 122
  /**
31 PointedEar 123
   * Setter for properties
124
   *
125
   * @param string $name
126
   * @param mixed $value  The new property value before assignment
127
   * @throws ModelPropertyException
128
   */
52 PointedEar 129
  public function __set ($name, $value)
31 PointedEar 130
  {
52 PointedEar 131
    $method = 'set' . \ucfirst($name);
45 PointedEar 132
 
52 PointedEar 133
    if (\method_exists($this, $method))
31 PointedEar 134
    {
135
      return $this->$method($value);
136
    }
45 PointedEar 137
 
52 PointedEar 138
    if (\property_exists($this, "_$name"))
31 PointedEar 139
    {
140
      $this->{"_$name"} = $value;
141
      return $this->{"_$name"};
142
    }
45 PointedEar 143
 
31 PointedEar 144
    /* NOTE: Attempts to set other properties are _silently_ _ignored_ */
145
  }
45 PointedEar 146
 
31 PointedEar 147
  /**
27 PointedEar 148
   * Runs the application, setting up session management and
149
   * constructing the controller indicated by the URI
150
   */
52 PointedEar 151
  public function run ()
27 PointedEar 152
  {
153
    $this->startSession();
45 PointedEar 154
 
27 PointedEar 155
    $controller = self::getParam('controller', $_REQUEST);
156
    if (!$controller)
157
    {
158
      $controller = $this->_defaultController;
159
    }
160
 
52 PointedEar 161
    $controller = \ucfirst($controller);
45 PointedEar 162
 
27 PointedEar 163
    $controller = $controller . 'Controller';
164
    require_once "{$this->_controllerPath}/{$controller}.php";
165
    $this->_currentController = new $controller();
45 PointedEar 166
 
27 PointedEar 167
    return $this;
168
  }
169
 
52 PointedEar 170
  protected function startSession ()
27 PointedEar 171
  {
52 PointedEar 172
    \session_start();
27 PointedEar 173
  }
45 PointedEar 174
 
27 PointedEar 175
  /**
176
   * Gets a request parameter
177
   *
178
   * @param string $key
179
   *   Key to look up in the array
180
   * @param array $array
181
   *   Array where to look up <var>$key</var>.
182
   *   The default is <code>$_GET</code>.
183
   * @return mixed
184
   *   <code>null</code> if there is no such <var>$key</var>
185
   *   in <var>$array</var>
186
   */
52 PointedEar 187
  public static function getParam ($key, array $array = null)
27 PointedEar 188
  {
31 PointedEar 189
    if ($array === null)
27 PointedEar 190
    {
191
      $array = $_GET;
192
    }
45 PointedEar 193
 
27 PointedEar 194
    return isset($array[$key]) ? $array[$key] : null;
195
  }
45 PointedEar 196
 
27 PointedEar 197
  /**
198
   * Registers a database
199
   *
200
   * @param string $key
201
   * @param Database $database
45 PointedEar 202
   * @return string Registry key
203
   * @see Application::setDefaultDatabase()
27 PointedEar 204
   */
51 PointedEar 205
  public function registerDatabase ($key, Db\Database $database)
27 PointedEar 206
  {
207
    Registry::set($key, $database);
45 PointedEar 208
    return $key;
27 PointedEar 209
  }
210
 
211
  /**
212
   * Sets the default database
45 PointedEar 213
   * @param string Registry key to refer to the {@link Database}
27 PointedEar 214
   */
45 PointedEar 215
  public function setDefaultDatabase ($key)
27 PointedEar 216
  {
217
    $this->_defaultDatabase = $key;
218
  }
219
 
220
  /**
221
  * Sets the current controller for this application
222
  *
223
  * @param Controller $controller
224
  * @return Application
225
  */
52 PointedEar 226
  public function setCurrentController (Controller $controller)
27 PointedEar 227
  {
228
    $this->_currentController = $controller;
229
    return $this;
230
  }
45 PointedEar 231
 
27 PointedEar 232
  /**
233
   * Returns the current controller for this application
234
   *
235
   * @return Controller
236
   */
52 PointedEar 237
  public function getCurrentController ()
27 PointedEar 238
  {
239
    return $this->_currentController;
240
  }
241
 
242
  /**
243
   * Returns the default database for this application
244
   *
245
   * @return Database
246
   */
52 PointedEar 247
  public function getDefaultDatabase ()
27 PointedEar 248
  {
249
    return Registry::get($this->_defaultDatabase);
250
  }
251
 
252
  /**
35 PointedEar 253
   * Returns a relative URI-reference for an action of the
27 PointedEar 254
   * application
255
   *
256
   * @param string[optional] $controller
257
   * @param string[optional] $action
258
   * @param int[optional] $id
259
   */
52 PointedEar 260
  public function getURL ($controller = null, $action = null, $id = null)
27 PointedEar 261
  {
262
    /* Apache module */
263
    $url = self::getParam('SCRIPT_URL', $_SERVER);
264
    if ($url === null)
265
    {
266
      /* FastCGI */
267
      $url = self::getParam('URL', $_SERVER);
268
      if ($url === null)
269
      {
31 PointedEar 270
        /* Server/PHP too old, compute URI */
271
        $url = self::getParam('REQUEST_URI', $_SERVER);
52 PointedEar 272
        if (\preg_match('/^[^?]+/', $url, $matches) > 0)
31 PointedEar 273
        {
274
          $url = $matches[0];
275
        }
276
        else
277
        {
278
          /* Has .php in it, but at least it works */
279
          $url = self::getParam('SCRIPT_NAME', $_SERVER);
280
          if ($url === null)
281
          {
52 PointedEar 282
            throw new \Exception(
31 PointedEar 283
              'None of $_SERVER["SCRIPT_URL"], $_SERVER["URL"],'
284
              . ' $_SERVER["REQUEST_URI"], or $_SERVER["SCRIPT_NAME"]'
285
              . ' is available, cannot continue.');
286
          }
287
        }
27 PointedEar 288
      }
289
    }
45 PointedEar 290
 
31 PointedEar 291
    $query = (($controller !== null) ? 'controller=' . $controller : '')
292
           . (($action !== null) ? '&action=' . $action : '')
293
           . (($id !== null) ? '&id=' . $id : '');
45 PointedEar 294
 
27 PointedEar 295
    return $url . ($query ? '?' . $query : '');
296
  }
45 PointedEar 297
 
27 PointedEar 298
  /**
299
   * Performs a server-side redirect within the application
300
   */
52 PointedEar 301
  public static function redirect ($query = '')
27 PointedEar 302
  {
303
    $script_uri = self::getParam('SCRIPT_URI', $_SERVER);
31 PointedEar 304
    if ($script_uri === null)
27 PointedEar 305
    {
306
      /* Server/PHP too old, compute URI */
52 PointedEar 307
      if (\preg_match('/^[^?]+/',
27 PointedEar 308
          self::getParam('REQUEST_URI', $_SERVER), $matches) > 0)
309
      {
310
        $query_prefix = $matches[0];
311
      }
312
      else
313
      {
314
        /* Has .php in it, but at least it works */
315
        $query_prefix = self::getParam('SCRIPT_NAME', $_SERVER);
316
      }
317
 
318
      /* TODO: Let user decide which ports map to which URI scheme */
319
      $script_uri = (self::getParam('SERVER_PORT', $_SERVER) == 443
320
                      ? 'https://'
321
                      : 'http://')
322
                  . self::getParam('HTTP_HOST', $_SERVER)
323
                  . $query_prefix;
324
    }
325
 
52 PointedEar 326
    \header('Location: ' . $script_uri
27 PointedEar 327
      . ($query ? (substr($query, 0, 1) === '?' ? '' : '?') . $query : ''));
328
  }
52 PointedEar 329
}