Subversion Repositories PHPX

Rev

Rev 52 | Rev 64 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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