Overview

Namespaces

  • None
  • PHP
  • Wei
    • Validator

Classes

  • Apc
  • App
  • ArrayCache
  • Asset
  • Base
  • BaseCache
  • Bicache
  • Cache
  • Config
  • Cookie
  • Couchbase
  • Counter
  • Db
  • DbCache
  • E
  • Env
  • Error
  • FileCache
  • Gravatar
  • Http
  • Lock
  • Logger
  • Memcache
  • Memcached
  • MongoCache
  • Password
  • PhpError
  • Pinyin
  • Record
  • Redis
  • Request
  • Response
  • Router
  • SafeUrl
  • Session
  • Soap
  • T
  • Ua
  • Upload
  • Url
  • Uuid
  • Validate
  • View
  • WeChatApp
  • Wei
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Wei Framework
  4:  *
  5:  * @copyright   Copyright (c) 2008-2013 Twin Huang
  6:  * @license     http://opensource.org/licenses/mit-license.php MIT License
  7:  */
  8: 
  9: namespace Wei
 10: {
 11:     /**
 12:      * @see Wei\Base
 13:      */
 14:     require_once 'Base.php';
 15: 
 16:     /**
 17:      * The service container
 18:      *
 19:      * @author      Twin Huang <twinhuang@qq.com>
 20:      *
 21:      * Cache
 22:      * @property Cache      $cache A cache service proxy
 23:      * @method   mixed      cache($key, $value = null, $expire = 0) Retrieve or store an item by cache
 24:      * @property ArrayCache $arrayCache  A cache service that stored data in PHP array
 25:      * @method   mixed      arrayCache($key, $value = null, $expire = 0) Retrieve or store an item by array cache
 26:      * @property Apc        $apc A cache service that stored data in PHP APC
 27:      * @method   mixed      apc($key, $value = null, $expire = 0) Retrieve or store an item
 28:      * @property DbCache    $dbCache A cache service that stored data in databases
 29:      * @method   mixed      dbCache($key, $value = null, $expire = 0) Retrieve or store an item by database cache
 30:      * @property FileCache  $fileCache A cache service that stored data in files
 31:      * @method   mixed      fileCache($key, $value = null, $expire = 0) Retrieve or store an item by file
 32:      * @property Memcache   $memcache A cache service that stored data in Memcache
 33:      * @method   mixed      memcache($key, $value = null, $expire = 0) Retrieve or store an item by Memcache
 34:      * @property Memcached  $memcached A cache service that stored data in Memcached
 35:      * @method   mixed      memcached($key, $value = null, $expire = 0) Retrieve or store an item by Memcached
 36:      * @property MongoCache $mongoCache A cache service that stores data in MongoDB
 37:      * @method   mixed      mongoCache($key, $value = null, $expire = 0) Retrieve or store an item by MongoDB
 38:      * @property Couchbase  $couchbase A cache service base on Couchbase
 39:      * @method   mixed      couchbase($key, $value = null, $expire = 0) Retrieve or store an item by Couchbase
 40:      * @property Redis      $redis A cache service that stores data in Redis
 41:      * @method   mixed      redis($key = null, $value = null, $expire = 0) Retrieve or store an item by Redis
 42:      * @property Bicache    $bicache A two-level cache service
 43:      * @method   mixed      bicache($key, $value = null, $expire = 0) Retrieve or store an item by two-level cache
 44:      *
 45:      * Database
 46:      * @property Db             $db A database service inspired by Doctrine DBAL
 47:      * @method   \Wei\Record    db($table = null) Create a new record object
 48:      *
 49:      * HTTP Client
 50:      * @property Http       $http An alias of call service
 51:      * @method   \Wei\Http  http(array $options) Create a new HTTP service and execute
 52:      *
 53:      * HTTP Request
 54:      * @property Request    $request A service that handles the HTTP request data
 55:      * @method   mixed      request($name, $default = null) Returns a stringify request parameter value
 56:      * @property Cookie     $cookie A object that handles the HTTP request and response cookies
 57:      * @method   mixed      cookie($key, $value = null, $options = array()) Get or set cookie
 58:      * @property Session    $session A object that session parameters ($_SESSION)
 59:      * @method   mixed      session($name, $default = null) Returns a stringify session parameter value
 60:      * @property Ua         $ua A object to detect user OS, device and browser name and version
 61:      * @method   bool       ua() Check if in the specified browser, OS or device
 62:      * @property Upload     $upload A object that handles the uploaded files
 63:      * @method   bool       upload(array $options = array()) Upload a file
 64:      *
 65:      * HTTP Response
 66:      * @property Response       $response A object that handles the HTTP response data
 67:      * @method   \Wei\Response  response($content = null, $status = null) Send response header and content
 68:      *
 69:      * View
 70:      * @property View       $view A object that use to render PHP template
 71:      * @method   string     view($name = null, $vars = array()) Returns view object or render a PHP template
 72:      * @property Asset      $asset A service to generate assets' URL
 73:      * @method   string     asset($file) Returns the asset URL by specified file
 74:      * @property E          $e A object to escape HTML, javascript, CSS, HTML Attribute and URL for secure output
 75:      * @method   string     e($string, $type = 'html') Escapes a string by specified type for secure output
 76:      *
 77:      * Application
 78:      * @property App            $app An MVC application service
 79:      * @method   \Wei\App       app(array $options = array()) Startup an MVC application
 80:      * @property WeChatApp      $weChatApp A object handles WeChat(WeiXin) callback message
 81:      * @method   \Wei\WeChatApp weChatApp() Start up WeChat application and output the matched rule message
 82:      * @property Router         $router A object that build a simple REST application
 83:      * @method   \Wei\Router    router($pathInfo = null, $method = null) Run the application
 84:      * @property Url            $url A util object to build URL
 85:      * @method   string         url($uri) Build URL by specified uri and parameters
 86:      *
 87:      * Other
 88:      * @property Config     $config A object to manage object configurations
 89:      * @property Counter    $counter A counter service
 90:      * @property Env        $env A object to detect the environment name and load configuration by environment name
 91:      * @method   string     env() Returns the environment name
 92:      * @property Error      $error A object that handles exception and display pretty exception message
 93:      * @method   \Wei\Error error($fn) Attach a handler to exception error
 94:      * @property Gravatar   $gravatar A object that generates a Gravatar URL for a specified email address
 95:      * @method   string     gravatar($email, $size = null, $default = null, $rating = null) Generates a Gravatar URL for a specified email address
 96:      * @property Lock       $lock A service that provide the functionality of exclusive Lock
 97:      * @method   bool       lock($key) Acquire a lock key
 98:      * @property Logger     $logger A logger service, which is inspired by Monolog
 99:      * @method   bool       logger($level, $message) Logs with an arbitrary level
100:      * @property Password   $password A wrapper class for password hashing functions
101:      * @property Pinyin     $pinyin An util object that converts Chinese words to phonetic alphabets
102:      * @method   string     pinyin($word) Converts Chinese words to phonetic alphabets
103:      * @property SafeUrl    $safeUrl Generate a URL with signature
104:      * @property Uuid       $uuid A util object that generates a RANDOM UUID(universally unique identifier)
105:      * @method   string     uuid() generates a RANDOM UUID(universally unique identifier)
106:      * @property T          $t A translator object
107:      * @method   string     t($message, array $parameters = array()) Translate the message
108:      *
109:      * Validation
110:      * @method   \Wei\Validate   validate(array $option) Create a new validator and validate by specified options
111:      *
112:      * Data type and composition
113:      * @property Validator\Alnum            $isAlnum
114:      * @method   bool                       isAlnum($input) Check if the input contains letters (a-z) and digits (0-9)
115:      * @property Validator\Alpha            $isAlpha
116:      * @method   bool                       isAlpha($input) Check if the input contains only letters (a-z)
117:      * @property Validator\Blank            $isBlank
118:      * @method   bool                       isBlank($input) Check if the input is blank
119:      * @property Validator\Contains         $isContains
120:      * @method   bool                       isContains($input, $search, $regex = false) Check if the input is contains the specified string or pattern
121:      * @property Validator\Decimal          $isDecimal
122:      * @method   bool                       isDecimal($input) Check if the input is decimal
123:      * @property Validator\Digit            $isDigit
124:      * @method   bool                       isDigit($input) Check if the input contains only digits (0-9)
125:      * @property Validator\DivisibleBy      $isDivisibleBy
126:      * @method   bool                       isDivisibleBy($input, $divisor) Check if the input could be divisible by specified divisor
127:      * @property Validator\DoubleByte       $isDoubleByte
128:      * @method   bool                       isDoubleByte($input) Check if the input contains only double characters
129:      * @property Validator\Present          $isPresent
130:      * @method   bool                       isPresent($input) Check if the input is empty
131:      * @property Validator\EndsWith         $isEndsWith
132:      * @method   bool                       isEndsWith($input, $findMe, $case = false) Check if the input is ends with specified string
133:      * @property Validator\In               $isIn
134:      * @method   bool                       isIn($input, array $array, $strict = false) Check if the input is in specified array
135:      * @property Validator\Lowercase        $isLowercase
136:      * @method   bool                       isLowercase($input) Check if the input is lowercase
137:      * @property Validator\Luhn             $isLuhn
138:      * @method   bool                       isLuhn($input) Check if the input is valid by the Luhn algorithm
139:      * @property Validator\NaturalNumber    $isNaturalNumber
140:      * @method   bool                       isNaturalNumber($input) Check if the input is a natural number (integer that greater than or equals 0)
141:      * @property Validator\Null             $isNull
142:      * @method   bool                       isNull($input) Check if the input is null
143:      * @property Validator\Number           $isNumber
144:      * @method   bool                       isNumber($input) Check if the input is number
145:      * @property Validator\PositiveInteger  $isPositiveInteger
146:      * @method   bool                       isPositiveInteger($input) Check if the input is a positive integer (integer that greater than 0)
147:      * @property Validator\Regex            $isRegex
148:      * @method   bool                       isRegex($input, $pattern) Check if the input is valid by specified regular expression
149:      * @property Validator\StartsWith       $isStartsWith
150:      * @method   bool                       isStartsWith($input, $findMe, $case = false) Check if the input is starts with specified string
151:      * @property Validator\Type             $isType
152:      * @method   bool                       isType($input, $type) Check if the type of input is equals specified type name
153:      * @property Validator\Uppercase        $isUppercase
154:      * @method   bool                       isUppercase($input) Check if the input is uppercase
155:      *
156:      * Length
157:      * @property Validator\Length       $isLength
158:      * @method   bool                   isLength($input, $length, $max = null) Check if the length (or size) of input is equals specified length or in specified length range
159:      * @property Validator\CharLength   $isCharLength
160:      * @method   bool                   isCharLength($input, $length) Check if the characters length of input is equals specified length
161:      * @property Validator\MinLength    $isMinLength
162:      * @method   bool                   isMinLength($input, $min) Check if the length (or size) of input is greater than specified length
163:      * @property Validator\MaxLength    $isMaxLength
164:      * @method   bool                   isMaxLength($input, $max) Check if the length (or size) of input is lower than specified length
165:      *
166:      * Comparison
167:      * @property Validator\EqualTo              $isEqualTo
168:      * @method   bool                           isEqualTo($input, $value) Check if the input is equals to (==) the specified value
169:      * @property Validator\IdenticalTo          $identicalTo
170:      * @method   bool                           isIdenticalTo($input, $value) Check if the input is equals to (==) the specified value
171:      * @property Validator\GreaterThan          $isGreaterThan
172:      * @method   bool                           isGreaterThan($input, $value) Check if the input is greater than (>=) the specified value
173:      * @property Validator\GreaterThanOrEqual   $isGreaterThanOrEqual
174:      * @method   bool                           isGreaterThanOrEqual($input, $value) Check if the input is greater than or equal to (>=) the specified value
175:      * @property Validator\LessThan             $isLessThan
176:      * @method   bool                           isLessThan($input, $value) Check if the input is less than (<) the specified value
177:      * @property Validator\LessThanOrEqual      $isLessThanOrEqual
178:      * @method   bool                           isLessThanOrEqual($input, $value) Check if the input is less than or equal to (<=) the specified value
179:      * @property Validator\Between              $isBetween
180:      * @method   bool                           isBetween($input, $min, $max) Check if the input is between the specified minimum and maximum value
181:      *
182:      * Date and time
183:      * @property Validator\Date         $isDate
184:      * @method   bool                   isDate($input, $format = 'Y-m-d') Check if the input is a valid date
185:      * @property Validator\DateTime     $isDateTime
186:      * @method   bool                   isDateTime($input, $format = null) Check if the input is a valid datetime
187:      * @property Validator\Time         $isTime
188:      * @method   bool                   isTime($input, $format = 'H:i:s') Check if the input is a valid time
189:      *
190:      * File and directory
191:      * @property Validator\Dir          $isDir
192:      * @method   bool                   isDir($input) Check if the input is existing directory
193:      * @property Validator\Exists       $isExists
194:      * @method   bool                   isExists($input) Check if the input is existing file or directory
195:      * @property Validator\File         $isFile
196:      * @method   bool                   isFile($input, array $options) Check if the input is valid file
197:      * @property Validator\Image        $isImage
198:      * @method   bool                   isImage($input, array $options) Check if the input is valid image
199:      *
200:      * Network
201:      * @property Validator\Email        $isEmail
202:      * @method   bool                   isEmail($input) Check if the input is valid email address
203:      * @property Validator\Ip           $isIp
204:      * @method   bool                   isIp($input, array $options = array()) Check if the input is valid IP address
205:      * @property Validator\Tld          $isTld
206:      * @method   bool                   isTld($input) Check if the input is a valid top-level domain
207:      * @property Validator\Url          $isUrl
208:      * @method   bool                   isUrl($input, array $options = array()) Check if the input is valid URL address
209:      * @property Validator\Uuid         $isUuid
210:      * @method   bool                   isUuid($input) Check if the input is valid UUID(v4)
211:      *
212:      * Region
213:      * @property Validator\CreditCard   $isCreditCard
214:      * @method   bool                   isCreditCard($input, $type = null) Check if the input is valid credit card number
215:      * @property Validator\Phone        $isPhone
216:      * @method   bool                   isPhone($input) Check if the input is valid phone number, contains only digit, +, - and spaces
217:      * @property Validator\Chinese      $isChinese
218:      * @method   bool                   isChinese($input) Check if the input contains only Chinese characters
219:      * @property Validator\IdCardCn     $isIdCardCn
220:      * @method   bool                   isIdCardCn($input) Check if the input is valid Chinese identity card
221:      * @property Validator\IdCardHk     $isIdCardHk
222:      * @method   bool                   isIdCardHk($input) Check if the input is valid Hong Kong identity card
223:      * @property Validator\IdCardMo     $isIdCardMo
224:      * @method   bool                   isIdCardMo($input) Check if the input is valid Macau identity card
225:      * @property Validator\IdCardTw     $isIdCardTw
226:      * @method   bool                   isIdCardTw($input) Check if the input is valid Taiwan identity card
227:      * @property Validator\PhoneCn      $isPhoneCn
228:      * @method   bool                   isPhoneCn($input) Check if the input is valid Chinese phone number
229:      * @property Validator\PlateNumberCn $isPlateNumberCn
230:      * @method   bool                   isPlateNumberCn($input) Check if the input is valid Chinese plate number
231:      * @property Validator\PostcodeCn   $isPostcodeCn
232:      * @method   bool                   isPostcodeCn($input) Check if the input is valid Chinese postcode
233:      * @property Validator\QQ           $isQQ
234:      * @method   bool                   isQQ($input) Check if the input is valid QQ number
235:      * @property Validator\MobileCn     $isMobileCn
236:      * @method   bool                   isMobileCn($input) Check if the input is valid Chinese mobile number
237:      *
238:      * Group
239:      * @property Validator\AllOf        $isAllOf
240:      * @method   bool                   isAllOf($input, array $rules) Check if the input is valid by all of the rules
241:      * @property Validator\NoneOf       $isNoneOf
242:      * @method   bool                   isNoneOf($input, array $rules) Check if the input is NOT valid by all of specified rules
243:      * @property Validator\OneOf        $isOneOf
244:      * @method   bool                   isOneOf($input, array $rules) Check if the input is valid by any of the rules
245:      * @property Validator\SomeOf       $isSomeOf
246:      * @method   bool                   isSomeOf($input, array $rules, $atLeast) Check if the input is valid by specified number of the rules
247:      *
248:      * Others
249:      * @property Validator\RecordExists $isRecordExists
250:      * @method   bool                   isRecordExists($input, $table, $field = 'id') Check if the input is existing table record
251:      * @property Validator\All          $isAll
252:      * @method   bool                   isAll($input, array $rules) Check if all of the element in the input is valid by all specified rules
253:      * @property Validator\Callback     $isCallback
254:      * @method   bool                   isCallback($input, \Closure $fn, $message = null) Check if the input is valid by specified callback
255:      * @property Validator\Color        $isColor
256:      * @method   bool                   isColor($input) Check if the input is valid Hex color
257:      * @property Validator\Password     $isPassword
258:      * @method   bool                   isPassword($input, array $options = array()) Check if the input password is secure enough
259:      */
260:     class Wei extends Base
261:     {
262:         /**
263:          * Version
264:          */
265:         const VERSION = '0.9.14';
266: 
267:         /**
268:          * The configurations for all objects
269:          *
270:          * @var array
271:          */
272:         protected $configs = array();
273: 
274:         /**
275:          * The name of current application
276:          *
277:          * @var string
278:          */
279:         protected $name;
280: 
281:         /**
282:          * Whether in debug mode or not
283:          *
284:          * @var bool
285:          */
286:         protected $debug = true;
287: 
288:         /**
289:          * The PHP configuration options that will be set when the service container constructing
290:          *
291:          * @var array
292:          * @see http://www.php.net/manual/en/ini.php
293:          * @see http://www.php.net/manual/en/function.ini-set.php
294:          */
295:         protected $inis = array();
296: 
297:         /**
298:          * Whether enable class autoload or not
299:          *
300:          * @var bool
301:          */
302:         protected $autoload = true;
303: 
304:         /**
305:          * The directories for autoload
306:          *
307:          * @var array
308:          */
309:         protected $autoloadMap = array();
310: 
311:         /**
312:          * The service name to class name map
313:          *
314:          * @var array
315:          */
316:         protected $aliases = array();
317: 
318:         /**
319:          * The service provider map
320:          *
321:          * @var array
322:          */
323:         protected $providers = array();
324: 
325:         /**
326:          * The import configuration
327:          *
328:          * Format:
329:          * array(
330:          *     array(
331:          *         'dir' => 'lib/Wei/Validator',
332:          *         'namespace' => 'Wei\Validator',
333:          *         'format' => 'is%s',
334:          *         'autoload' => false
335:          *     ),
336:          *     array(
337:          *         'dir' => 'src/MyProject/Wei',
338:          *         'namespace' => 'MyProject\Wei',
339:          *         'format' => '%s',
340:          *         'autoload' => true
341:          *     )
342:          * );
343:          * @var array
344:          */
345:         protected $import = array();
346: 
347:         /**
348:          * The callback executes *before* service constructed
349:          *
350:          * @var callable
351:          */
352:         protected $beforeConstruct;
353: 
354:         /**
355:          * The callback executes *after* service constructed
356:          *
357:          * @var callable
358:          */
359:         protected $afterConstruct;
360: 
361:         /**
362:          * The services that will be instanced after service container constructed
363:          *
364:          * @var array
365:          */
366:         protected $preload = array();
367: 
368:         /**
369:          * An array contains the instanced services
370:          *
371:          * @var Base[]
372:          */
373:         protected $services = array();
374: 
375:         /**
376:          * The current service container
377:          *
378:          * @var Wei
379:          */
380:         protected static $container;
381: 
382:         /**
383:          * Instance service container
384:          *
385:          * @param array $config
386:          */
387:         public function __construct(array $config = array())
388:         {
389:             // Set configurations for all services
390:             $this->setConfig($config);
391: 
392:             $this->set('wei', $this);
393:             $this->wei = $this;
394: 
395:             // Set all options
396:             $options = get_object_vars($this);
397:             if (isset($this->configs['wei'])) {
398:                 $options = array_merge($options, $this->configs['wei']);
399:             }
400:             $this->setOption($options);
401:         }
402: 
403:         /**
404:          * Get the service container instance
405:          *
406:          * @param array $config                 The array or file configuration
407:          * @return $this
408:          * @throws \InvalidArgumentException    When the configuration parameter is not array or file
409:          */
410:         public static function getContainer($config = array())
411:         {
412:             // Most of time, it's called after instanced and without any arguments
413:             if (!$config && static::$container) {
414:                 return static::$container;
415:             }
416: 
417:             switch (true) {
418:                 case is_array($config):
419:                     break;
420: 
421:                 case is_string($config) && file_exists($config):
422:                     $config = (array) require $config;
423:                     break;
424: 
425:                 default:
426:                     throw new \InvalidArgumentException('Configuration should be array or file', 1010);
427:             }
428: 
429:             if (!isset(static::$container)) {
430:                 static::$container = new static($config);
431:             } else {
432:                 static::$container->setConfig($config);
433:             }
434:             return static::$container;
435:         }
436: 
437:         /**
438:          * Set the service container
439:          *
440:          * @param Wei $container
441:          */
442:         public static function setContainer(Wei $container = null)
443:         {
444:             static::$container = $container;
445:         }
446: 
447:         /**
448:          * Autoload the PSR-0 class
449:          *
450:          * @param  string $class the name of the class
451:          * @return bool
452:          */
453:         public function autoload($class)
454:         {
455:             $class = strtr($class, array('_' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR)) . '.php';
456: 
457:             foreach ($this->autoloadMap as $prefix => $dir) {
458:                 // Autoload class from relative path like PSR-4 when prefix starts with "\"
459:                 if (isset($prefix[0]) && $prefix[0] == '\\' && 0 === strpos($class, ltrim($prefix, '\\'))) {
460:                     $file = $dir . DIRECTORY_SEPARATOR . substr($class, strlen($prefix));
461:                     if (file_exists($file)) {
462:                         require_once $file;
463:                         return true;
464:                     }
465:                 }
466: 
467:                 // Allow empty class prefix
468:                 if (!$prefix || 0 === strpos($class, $prefix)) {
469:                     if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $class)) {
470:                         require_once $file;
471:                         return true;
472:                     }
473:                 }
474:             }
475: 
476:             return false;
477:         }
478: 
479:         /**
480:          * Set service's configuration
481:          *
482:          * @param string|array $name
483:          * @param mixed $value
484:          * @return $this
485:          */
486:         public function setConfig($name, $value = null)
487:         {
488:             // Set array configurations
489:             if (is_array($name)) {
490:                 foreach ($name as $key => $value) {
491:                     $this->setConfig($key, $value);
492:                 }
493:                 return $this;
494:             }
495: 
496:             // Set one configuration
497:             $names = explode(':', $name);
498:             $first = $names[0];
499:             $configs = &$this->configs;
500: 
501:             foreach ($names as $name) {
502:                 if (!is_array($configs)) {
503:                     $configs = array();
504:                 }
505:                 if (!isset($configs[$name])) {
506:                     $configs[$name] = array();
507:                 }
508:                 $configs = &$configs[$name];
509:             }
510: 
511:             // Merge only first child node
512:             if (is_array($configs) && is_array($value)) {
513:                 $configs = $value + $configs;
514:             } else {
515:                 $configs = $value;
516:             }
517: 
518:             /**
519:              * Automatically create dependence map when configuration key contains "."
520:              *
521:              * $this->configs = array(
522:              *    'mysql.db' => array(),
523:              * );
524:              * =>
525:              * $this->providers['mysqlDb'] = 'mysql.db';
526:              */
527:             if (false !== strpos($first, '.')) {
528:                 $parts = explode('.', $first, 2);
529:                 $serviceName = $parts[0] . ucfirst($parts[1]);
530:                 if (!isset($this->providers[$serviceName])) {
531:                     $this->providers[$serviceName] = $first;
532:                 }
533:             }
534: 
535:             // Set options for existing service
536:             if (isset($this->services[$first])) {
537:                 $this->services[$first]->setOption($value);
538:             }
539: 
540:             return $this;
541:         }
542: 
543:         /**
544:          * Get services' configuration
545:          *
546:          * @param string $name The name of configuration
547:          * @param mixed $default The default value if configuration not found
548:          * @return mixed
549:          */
550:         public function getConfig($name = null, $default = null)
551:         {
552:             if (is_null($name)) {
553:                 return $this->configs;
554:             }
555: 
556:             if (false === strpos($name, ':')) {
557:                 return isset($this->configs[$name]) ? $this->configs[$name] : $default;
558:             }
559: 
560:             $configs = &$this->configs;
561:             foreach (explode(':', $name) as $key) {
562:                 if (is_array($configs) && isset($configs[$key])) {
563:                     $configs = &$configs[$key];
564:                 } else {
565:                     return $default;
566:                 }
567:             }
568:             return $configs;
569:         }
570: 
571:         /**
572:          * Get a service and call its "__invoke" method
573:          *
574:          * @param string $name The name of the service
575:          * @param array $args The arguments for "__invoke" method
576:          * @param array $providers The service providers map
577:          * @return mixed
578:          */
579:         public function invoke($name, array $args = array(), $providers = array())
580:         {
581:             $service = $this->get($name, $providers);
582:             return call_user_func_array(array($service, '__invoke'), $args);
583:         }
584: 
585:         /**
586:          * Get a service
587:          *
588:          * @param string $name The name of the service, without class prefix "Wei\"
589:          * @param array $options The option properties for service
590:          * @param array $providers The dependent configuration
591:          * @throws \BadMethodCallException
592:          * @return Base
593:          */
594:         public function get($name, array $options = array(), array $providers = array())
595:         {
596:             // Resolve the service name in dependent configuration
597:             if (isset($providers[$name])) {
598:                 $name = $providers[$name];
599:             }
600: 
601:             if (isset($this->providers[$name])) {
602:                 $name = $this->providers[$name];
603:             }
604: 
605:             if (isset($this->services[$name])) {
606:                 return $this->services[$name];
607:             }
608: 
609:             // Resolve the real service name and the config name($full)
610:             $full = $name;
611:             if (false !== ($pos = strpos($name, '.'))) {
612:                 $name = substr($name, $pos + 1);
613:             }
614: 
615:             // Get the service class and instance
616:             $class = $this->getClass($name);
617:             if (class_exists($class)) {
618:                 // Trigger the before construct callback
619:                 $this->beforeConstruct && call_user_func($this->beforeConstruct, $this, $full, $name);
620: 
621:                 // Load the service configuration and make sure "wei" option at first
622:                 $options = array('wei' => $this) + $options + (array)$this->getConfig($full);
623: 
624:                 $this->services[$full] = new $class($options);
625: 
626:                 // Trigger the after construct callback
627:                 $this->afterConstruct && call_user_func($this->afterConstruct, $this, $full, $name, $this->services[$full]);
628: 
629:                 return $this->services[$full];
630:             }
631: 
632:             // Build the error message
633:             $traces = debug_backtrace();
634: 
635:             // $wei->notFound()
636:             if (isset($traces[3]) && $name == $traces[3]['function']) {
637:                 // For call_user_func/call_user_func_array
638:                 $file = isset($traces[3]['file']) ? $traces[3]['file'] : $traces[4]['file'];
639:                 $line = isset($traces[3]['line']) ? $traces[3]['line'] : $traces[4]['line'];
640:                 throw new \BadMethodCallException(sprintf('Method "%s->%2$s" or object "%s" (class "%s") not found, called in file "%s" at line %s', $traces[3]['class'], $traces[3]['function'], $class, $file, $line), 1011);
641:             // $wei->notFound
642:             } elseif (isset($traces[1]) && '__get' == $traces[1]['function'] && $name == $traces[1]['args'][0]) {
643:                 throw new \BadMethodCallException(sprintf('Property or object "%s" (class "%s") not found, called in file "%s" at line %s', $traces[1]['args'][0], $class, $traces[1]['file'], $traces[1]['line']), 1012);
644:             // $wei->get('notFound');
645:             } else {
646:                 throw new \BadMethodCallException(sprintf('Property or method "%s" not found', $name), 1013);
647:             }
648:         }
649: 
650:         /**
651:          * Returns all instanced services
652:          *
653:          * @return Base[]
654:          */
655:         public function getServices()
656:         {
657:             return $this->services;
658:         }
659: 
660:         /**
661:          * Check if the service is instanced
662:          *
663:          * @param string $name The name of service
664:          * @return bool
665:          */
666:         public function isInstanced($name)
667:         {
668:             return isset($this->services[$name]);
669:         }
670: 
671:         /**
672:          * Initialize a new instance of service, with the specified name
673:          *
674:          * @param string $name The name of the service
675:          * @param array $options The option properties for service
676:          * @param array $providers The dependent configuration
677:          * @return Base The instanced service
678:          */
679:         public function newInstance($name, array $options = array(), array $providers = array())
680:         {
681:             $name .= uniqid() . '.' . $name;
682:             return $this->wei->get($name, $options, $providers);
683:         }
684: 
685:         /**
686:          * Add a service to the service container
687:          *
688:          * @param string $name The name of service
689:          * @param Base $service The object of service
690:          * @return $this
691:          */
692:         public function set($name, Base $service)
693:         {
694:             $this->services[$name] = $service;
695:             return $this;
696:         }
697: 
698:         /**
699:          * Remove the service by the specified name
700:          *
701:          * @param  string  $name The name of service
702:          * @return bool
703:          */
704:         public function remove($name)
705:         {
706:             if (isset($this->services[$name])) {
707:                 unset($this->services[$name]);
708:                 return true;
709:             }
710:             return false;
711:         }
712: 
713:         /**
714:          * Get the service class by the given name
715:          *
716:          * @param string $name The name of service
717:          * @return string
718:          */
719:         public function getClass($name)
720:         {
721:             if (isset($this->aliases[$name])) {
722:                 $class = $this->aliases[$name];
723:             } elseif ('is' == substr($name, 0, 2) && strlen($name) > 2) {
724:                 $class = 'Wei\Validator\\' . ucfirst(substr($name, 2));
725:             } else {
726:                 $class = 'Wei\\' . ucfirst($name);
727:             }
728:             return $class;
729:         }
730: 
731:         /**
732:          * Check if the service exists by the specified name, if the service exists,
733:          * returns the full class name, else return false
734:          *
735:          * @param string $name The name of service
736:          * @return string|false
737:          */
738:         public function has($name)
739:         {
740:             $class = $this->getClass($name);
741:             return class_exists($class) ? $class : false;
742:         }
743: 
744:         /**
745:          * Set debug flag
746:          *
747:          * @param $bool
748:          * @return $this
749:          */
750:         public function setDebug($bool)
751:         {
752:             $this->debug = (bool) $bool;
753:             return $this;
754:         }
755: 
756:         /**
757:          * Whether in debug mode or not
758:          *
759:          * @return bool
760:          */
761:         public function isDebug()
762:         {
763:             return $this->debug;
764:         }
765: 
766:         /**
767:          * Whether enable autoload or not
768:          *
769:          * @param bool $enable
770:          * @return $this
771:          */
772:         public function setAutoload($enable)
773:         {
774:             $this->autoload = (bool) $enable;
775:             call_user_func(
776:                 $enable ? 'spl_autoload_register' : 'spl_autoload_unregister',
777:                 array($this, 'autoload')
778:             );
779:             return $this;
780:         }
781: 
782:         /**
783:          * Set autoload directories for autoload method
784:          *
785:          * @param array $map
786:          * @throws \InvalidArgumentException
787:          * @return $this
788:          */
789:         public function setAutoloadMap(array $map)
790:         {
791:             foreach ($map as &$dir) {
792:                 if (!is_dir($dir)) {
793:                     throw new \InvalidArgumentException(sprintf('Directory "%s" for autoloading is not found', $dir));
794:                 }
795:                 $dir = realpath($dir);
796:             }
797: 
798:             // Automatic add PSR-4 autoloading for "\Wei" namespace
799:             $map['\Wei'] = __DIR__;
800: 
801:             $this->autoloadMap = $map;
802:             return $this;
803:         }
804: 
805:         /**
806:          * Sets the value of PHP configuration options
807:          *
808:          * @param array $inis
809:          * @return $this
810:          */
811:         public function setInis(array $inis)
812:         {
813:             $this->inis = $inis + $this->inis;
814:             foreach ($inis as $key => $value) {
815:                 ini_set($key, $value);
816:             }
817:             return $this;
818:         }
819: 
820:         /**
821:          * Merge service aliases
822:          *
823:          * @param array $aliases
824:          * @return $this
825:          */
826:         public function setAliases(array $aliases)
827:         {
828:             $this->aliases = $aliases + $this->aliases;
829:             return $this;
830:         }
831: 
832:         /**
833:          * Set service alias
834:          *
835:          * @param string $name The name of service
836:          * @param string $class The class that the service reference to
837:          * @return $this
838:          */
839:         public function setAlias($name, $class)
840:         {
841:             $this->aliases[$name] = $class;
842:             return $this;
843:         }
844: 
845:         /**
846:          * Add a service to the service container
847:          *
848:          * @param string $name The name of service
849:          * @param Base $service The service service
850:          * @return $this
851:          */
852:         public function __set($name, Base $service)
853:         {
854:             return $this->set($name, $service);
855:         }
856: 
857:         /**
858:          * Import classes in the specified directory as services
859:          *
860:          * @param string $dir The directory to search class
861:          * @param string $namespace The prefix namespace of the class
862:          * @param null $format The service name format, eg 'is%s'
863:          * @param bool $autoload Whether add namespace and directory to `autoloadMap` or nor
864:          * @throws \InvalidArgumentException When the first parameter is not a directory
865:          * @return $this
866:          */
867:         public function import($dir, $namespace, $format = null, $autoload = false)
868:         {
869:             if (!is_dir($dir)) {
870:                 throw new \InvalidArgumentException(sprintf('Fail to import classes from non-exists directory "%s"', $dir), 1014);
871:             }
872: 
873:             if ($autoload) {
874:                 $this->autoloadMap[$namespace] = dirname($dir);
875:             }
876: 
877:             $files = glob($dir . '/*.php') ?: array();
878:             foreach ($files as $file) {
879:                 $class = substr(basename($file), 0, -4);
880:                 $name = $format ? sprintf($format, $class) : $class;
881:                 $this->aliases[lcfirst($name)] = $namespace . '\\' . $class;
882:             }
883: 
884:             return $this;
885:         }
886: 
887:         /**
888:          * Set the name of current application
889:          *
890:          * @param string $name
891:          * @return $this
892:          */
893:         public function setName($name)
894:         {
895:             $this->name = $name;
896:             return $this;
897:         }
898: 
899:         /**
900:          * Returns the name of current application
901:          *
902:          * @return string
903:          */
904:         public function getName()
905:         {
906:             return $this->name;
907:         }
908: 
909:         /**
910:          * Set import services
911:          *
912:          * @param array $import
913:          * @return $this
914:          */
915:         protected function setImport(array $import = array())
916:         {
917:             $this->import = $import + $this->import;
918:             foreach ($import as $option) {
919:                 $option += array(
920:                     'dir' => null,
921:                     'namespace' => null,
922:                     'format' => null,
923:                     'autoload' => false,
924:                 );
925:                 $this->import($option['dir'], $option['namespace'], $option['format'], $option['autoload']);
926:             }
927:         }
928: 
929:         /**
930:          * Merge the dependence map
931:          *
932:          * @param array $providers
933:          */
934:         protected function setProviders(array $providers)
935:         {
936:             $this->providers = $providers + $this->providers;
937:         }
938: 
939:         /**
940:          * Instance preload services
941:          *
942:          * @param array $preload
943:          */
944:         protected function setPreload(array $preload)
945:         {
946:             $this->preload = array_merge($this->preload, $preload);
947:             foreach ($preload as $service) {
948:                 $this->set($service, $this->get($service));
949:             }
950:         }
951: 
952:         /**
953:          * Merge service objects
954:          *
955:          * @param array $services
956:          */
957:         protected function setServices(array $services)
958:         {
959:             $this->services = $services + $this->services;
960:         }
961:     }
962: }
963: 
964: /**
965:  * Define function in global namespace
966:  */
967: namespace
968: {
969:     /**
970:      * Get the service container instance
971:      *
972:      * @return Wei\Wei
973:      */
974:     function wei()
975:     {
976:         return call_user_func_array(array('Wei\Wei', 'getContainer'), func_get_args());
977:     }
978: 
979:     /**
980:      * Get the service container instance
981:      *
982:      * @return Wei\Wei
983:      * @deprecated Remove in 0.9.9
984:      */
985:     function widget()
986:     {
987:         return call_user_func_array(array('Wei\Wei', 'getContainer'), func_get_args());
988:     }
989: }
990: 
Wei Framework API documentation generated by ApiGen