Browse Source

Initial commit for Laravel

Skamander 12 years ago
parent
commit
cf3b60333d
100 changed files with 11135 additions and 0 deletions
  1. 1 0
      php-laravel/.gitattributes
  2. 9 0
      php-laravel/.gitignore
  3. 6 0
      php-laravel/.travis.yml
  4. 9 0
      php-laravel/CONTRIBUTING.md
  5. 0 0
      php-laravel/__init__.py
  6. 40 0
      php-laravel/application/bundles.php
  7. 1 0
      php-laravel/application/config/.gitignore
  8. 199 0
      php-laravel/application/config/application.php
  9. 73 0
      php-laravel/application/config/auth.php
  10. 71 0
      php-laravel/application/config/cache.php
  11. 125 0
      php-laravel/application/config/database.php
  12. 69 0
      php-laravel/application/config/error.php
  13. 97 0
      php-laravel/application/config/mimes.php
  14. 117 0
      php-laravel/application/config/session.php
  15. 190 0
      php-laravel/application/config/strings.php
  16. 17 0
      php-laravel/application/controllers/base.php
  17. 38 0
      php-laravel/application/controllers/home.php
  18. 19 0
      php-laravel/application/language/ar/pagination.php
  19. 104 0
      php-laravel/application/language/ar/validation.php
  20. 19 0
      php-laravel/application/language/bg/pagination.php
  21. 104 0
      php-laravel/application/language/bg/validation.php
  22. 19 0
      php-laravel/application/language/da/pagination.php
  23. 104 0
      php-laravel/application/language/da/validation.php
  24. 19 0
      php-laravel/application/language/de/pagination.php
  25. 104 0
      php-laravel/application/language/de/validation.php
  26. 19 0
      php-laravel/application/language/el/pagination.php
  27. 104 0
      php-laravel/application/language/el/validation.php
  28. 19 0
      php-laravel/application/language/en/pagination.php
  29. 106 0
      php-laravel/application/language/en/validation.php
  30. 19 0
      php-laravel/application/language/fi/pagination.php
  31. 104 0
      php-laravel/application/language/fi/validation.php
  32. 19 0
      php-laravel/application/language/fr/pagination.php
  33. 104 0
      php-laravel/application/language/fr/validation.php
  34. 19 0
      php-laravel/application/language/he/pagination.php
  35. 107 0
      php-laravel/application/language/he/validation.php
  36. 19 0
      php-laravel/application/language/hu/pagination.php
  37. 104 0
      php-laravel/application/language/hu/validation.php
  38. 19 0
      php-laravel/application/language/id/pagination.php
  39. 104 0
      php-laravel/application/language/id/validation.php
  40. 19 0
      php-laravel/application/language/it/pagination.php
  41. 104 0
      php-laravel/application/language/it/validation.php
  42. 31 0
      php-laravel/application/language/ja/pagination.php
  43. 147 0
      php-laravel/application/language/ja/validation.php
  44. 19 0
      php-laravel/application/language/nl/pagination.php
  45. 95 0
      php-laravel/application/language/nl/validation.php
  46. 19 0
      php-laravel/application/language/pl/pagination.php
  47. 104 0
      php-laravel/application/language/pl/validation.php
  48. 19 0
      php-laravel/application/language/pt/pagination.php
  49. 99 0
      php-laravel/application/language/pt/validation.php
  50. 19 0
      php-laravel/application/language/ro/pagination.php
  51. 106 0
      php-laravel/application/language/ro/validation.php
  52. 19 0
      php-laravel/application/language/ru/pagination.php
  53. 104 0
      php-laravel/application/language/ru/validation.php
  54. 19 0
      php-laravel/application/language/sq/pagination.php
  55. 104 0
      php-laravel/application/language/sq/validation.php
  56. 19 0
      php-laravel/application/language/sr/pagination.php
  57. 104 0
      php-laravel/application/language/sr/validation.php
  58. 19 0
      php-laravel/application/language/sv/pagination.php
  59. 104 0
      php-laravel/application/language/sv/validation.php
  60. 28 0
      php-laravel/application/language/tr/pagination.php
  61. 108 0
      php-laravel/application/language/tr/validation.php
  62. 0 0
      php-laravel/application/libraries/.gitignore
  63. 0 0
      php-laravel/application/migrations/.gitignore
  64. 0 0
      php-laravel/application/models/.gitignore
  65. 126 0
      php-laravel/application/routes.php
  66. 173 0
      php-laravel/application/start.php
  67. 0 0
      php-laravel/application/tasks/.gitignore
  68. 15 0
      php-laravel/application/tests/example.test.php
  69. 125 0
      php-laravel/application/views/error/404.php
  70. 125 0
      php-laravel/application/views/error/500.php
  71. 57 0
      php-laravel/application/views/home/index.blade.php
  72. 24 0
      php-laravel/artisan
  73. 13 0
      php-laravel/benchmark_config
  74. 0 0
      php-laravel/bundles/.gitignore
  75. 2934 0
      php-laravel/bundles/docs/libraries/markdown.php
  76. 85 0
      php-laravel/bundles/docs/routes.php
  77. 5 0
      php-laravel/bundles/docs/views/page.blade.php
  78. 34 0
      php-laravel/bundles/docs/views/template.blade.php
  79. 125 0
      php-laravel/deploy/nginx.conf
  80. 9 0
      php-laravel/deploy/php-laravel
  81. 356 0
      php-laravel/laravel/asset.php
  82. 93 0
      php-laravel/laravel/auth.php
  83. 231 0
      php-laravel/laravel/auth/drivers/driver.php
  84. 73 0
      php-laravel/laravel/auth/drivers/eloquent.php
  85. 72 0
      php-laravel/laravel/auth/drivers/fluent.php
  86. 229 0
      php-laravel/laravel/autoloader.php
  87. 454 0
      php-laravel/laravel/blade.php
  88. 476 0
      php-laravel/laravel/bundle.php
  89. 118 0
      php-laravel/laravel/cache.php
  90. 89 0
      php-laravel/laravel/cache/drivers/apc.php
  91. 125 0
      php-laravel/laravel/cache/drivers/database.php
  92. 113 0
      php-laravel/laravel/cache/drivers/driver.php
  93. 110 0
      php-laravel/laravel/cache/drivers/file.php
  94. 186 0
      php-laravel/laravel/cache/drivers/memcached.php
  95. 151 0
      php-laravel/laravel/cache/drivers/memory.php
  96. 101 0
      php-laravel/laravel/cache/drivers/redis.php
  97. 142 0
      php-laravel/laravel/cache/drivers/sectionable.php
  98. 89 0
      php-laravel/laravel/cache/drivers/wincache.php
  99. 50 0
      php-laravel/laravel/cli/artisan.php
  100. 198 0
      php-laravel/laravel/cli/command.php

+ 1 - 0
php-laravel/.gitattributes

@@ -0,0 +1 @@
+* text=auto

+ 9 - 0
php-laravel/.gitignore

@@ -0,0 +1,9 @@
+/app/cache
+/app/logs
+/bin
+/vendors
+/build
+/dist
+.DS_Store
+/tags
+.idea

+ 6 - 0
php-laravel/.travis.yml

@@ -0,0 +1,6 @@
+language: php
+
+php:
+  - 5.3
+
+script: "php artisan test:core"

+ 9 - 0
php-laravel/CONTRIBUTING.md

@@ -0,0 +1,9 @@
+# Pull request guidelines
+
+[GitHub pull requests](https://help.github.com/articles/using-pull-requests) are a great way for everyone in the community to contribute to the Laravel codebase. Found a bug? Just fix it in your fork and submit a pull request. This will then be reviewed, and, if found as good, merged into the main repository.
+
+In order to keep the codebase clean, stable and at high quality, even with so many people contributing, some guidelines are necessary for high-quality pull requests:
+
+- **Branch:** Unless they are immediate documentation fixes relevant for old versions, pull requests should be sent to the `develop` branch only. Make sure to select that branch as target when creating the pull request (GitHub will not automatically select it.)
+- **Documentation:** If you are adding a new feature or changing the API in any relevant way, this should be documented. The documentation files can be found directly in the core repository.
+- **Unit tests:** To keep old bugs from re-appearing and generally hold quality at a high level, the Laravel core is thoroughly unit-tested. Thus, when you create a pull request, it is expected that you unit test any new code you add. For any bug you fix, you should also add regression tests to make sure the bug will never appear again. If you are unsure about how to write tests, the core team or other contributors will gladly help.

+ 0 - 0
php-laravel/__init__.py


+ 40 - 0
php-laravel/application/bundles.php

@@ -0,0 +1,40 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Bundle Configuration
+|--------------------------------------------------------------------------
+|
+| Bundles allow you to conveniently extend and organize your application.
+| Think of bundles as self-contained applications. They can have routes,
+| controllers, models, views, configuration, etc. You can even create
+| your own bundles to share with the Laravel community.
+|
+| This is a list of the bundles installed for your application and tells
+| Laravel the location of the bundle's root directory, as well as the
+| root URI the bundle responds to.
+|
+| For example, if you have an "admin" bundle located in "bundles/admin" 
+| that you want to handle requests with URIs that begin with "admin",
+| simply add it to the array like this:
+|
+|		'admin' => array(
+|			'location' => 'admin',
+|			'handles'  => 'admin',
+|		),
+|
+| Note that the "location" is relative to the "bundles" directory.
+| Now the bundle will be recognized by Laravel and will be able
+| to respond to requests beginning with "admin"!
+|
+| Have a bundle that lives in the root of the bundle directory
+| and doesn't respond to any requests? Just add the bundle
+| name to the array and we'll take care of the rest.
+|
+*/
+
+return array(
+
+	'docs' => array('handles' => 'docs'),
+
+);

+ 1 - 0
php-laravel/application/config/.gitignore

@@ -0,0 +1 @@
+local/*

+ 199 - 0
php-laravel/application/config/application.php

@@ -0,0 +1,199 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Application URL
+	|--------------------------------------------------------------------------
+	|
+	| The URL used to access your application without a trailing slash. The URL
+	| does not have to be set. If it isn't, we'll try our best to guess the URL
+	| of your application.
+	|
+	*/
+
+	'url' => '',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Asset URL
+	|--------------------------------------------------------------------------
+	|
+	| The base URL used for your application's asset files. This is useful if
+	| you are serving your assets through a different server or a CDN. If it
+	| is not set, we'll default to the application URL above.
+	|
+	*/
+
+	'asset_url' => '',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Application Index
+	|--------------------------------------------------------------------------
+	|
+	| If you are including the "index.php" in your URLs, you can ignore this.
+	| However, if you are using mod_rewrite to get cleaner URLs, just set
+	| this option to an empty string and we'll take care of the rest.
+	|
+	*/
+
+	'index' => 'index.php',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Application Key
+	|--------------------------------------------------------------------------
+	|
+	| This key is used by the encryption and cookie classes to generate secure
+	| encrypted strings and hashes. It is extremely important that this key
+	| remains secret and it should not be shared with anyone. Make it about 32
+	| characters of random gibberish.
+	|
+	*/
+
+	'key' => 'YourSecretKeyGoesHere!',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Profiler Toolbar
+	|--------------------------------------------------------------------------
+	|
+	| Laravel includes a beautiful profiler toolbar that gives you a heads
+	| up display of the queries and logs performed by your application.
+	| This is wonderful for development, but, of course, you should
+	| disable the toolbar for production applications.
+	|
+	*/
+
+	'profiler' => false,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Application Character Encoding
+	|--------------------------------------------------------------------------
+	|
+	| The default character encoding used by your application. This encoding
+	| will be used by the Str, Text, Form, and any other classes that need
+	| to know what type of encoding to use for your awesome application.
+	|
+	*/
+
+	'encoding' => 'UTF-8',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Default Application Language
+	|--------------------------------------------------------------------------
+	|
+	| The default language of your application. This language will be used by
+	| Lang library as the default language when doing string localization.
+	|
+	*/
+
+	'language' => 'en',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Supported Languages
+	|--------------------------------------------------------------------------
+	|
+	| These languages may also be supported by your application. If a request
+	| enters your application with a URI beginning with one of these values
+	| the default language will automatically be set to that language.
+	|
+	*/
+
+	'languages' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| SSL Link Generation
+	|--------------------------------------------------------------------------
+	|
+	| Many sites use SSL to protect their users' data. However, you may not be
+	| able to use SSL on your development machine, meaning all HTTPS will be
+	| broken during development.
+	|
+	| For this reason, you may wish to disable the generation of HTTPS links
+	| throughout your application. This option does just that. All attempts
+	| to generate HTTPS links will generate regular HTTP links instead.
+	|
+	*/
+
+	'ssl' => true,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Application Timezone
+	|--------------------------------------------------------------------------
+	|
+	| The default timezone of your application. The timezone will be used when
+	| Laravel needs a date, such as when writing to a log file or travelling
+	| to a distant star at warp speed.
+	|
+	*/
+
+	'timezone' => 'UTC',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Class Aliases
+	|--------------------------------------------------------------------------
+	|
+	| Here, you can specify any class aliases that you would like registered
+	| when Laravel loads. Aliases are lazy-loaded, so feel free to add!
+	|
+	| Aliases make it more convenient to use namespaced classes. Instead of
+	| referring to the class using its full namespace, you may simply use
+	| the alias defined here.
+	|
+	*/
+
+	'aliases' => array(
+		'Auth'       	=> 'Laravel\\Auth',
+		'Authenticator' => 'Laravel\\Auth\\Drivers\\Driver',
+		'Asset'      	=> 'Laravel\\Asset',
+		'Autoloader' 	=> 'Laravel\\Autoloader',
+		'Blade'      	=> 'Laravel\\Blade',
+		'Bundle'     	=> 'Laravel\\Bundle',
+		'Cache'      	=> 'Laravel\\Cache',
+		'Command'    	=> 'Laravel\\CLI\\Command',
+		'Config'     	=> 'Laravel\\Config',
+		'Controller' 	=> 'Laravel\\Routing\\Controller',
+		'Cookie'     	=> 'Laravel\\Cookie',
+		'Crypter'    	=> 'Laravel\\Crypter',
+		'DB'         	=> 'Laravel\\Database',
+		'Eloquent'   	=> 'Laravel\\Database\\Eloquent\\Model',
+		'Event'      	=> 'Laravel\\Event',
+		'File'       	=> 'Laravel\\File',
+		'Filter'     	=> 'Laravel\\Routing\\Filter',
+		'Form'       	=> 'Laravel\\Form',
+		'Hash'       	=> 'Laravel\\Hash',
+		'HTML'       	=> 'Laravel\\HTML',
+		'Input'      	=> 'Laravel\\Input',
+		'IoC'        	=> 'Laravel\\IoC',
+		'Lang'       	=> 'Laravel\\Lang',
+		'Log'        	=> 'Laravel\\Log',
+		'Memcached'  	=> 'Laravel\\Memcached',
+		'Paginator'  	=> 'Laravel\\Paginator',
+		'Profiler'  	=> 'Laravel\\Profiling\\Profiler',
+		'URL'        	=> 'Laravel\\URL',
+		'Redirect'   	=> 'Laravel\\Redirect',
+		'Redis'      	=> 'Laravel\\Redis',
+		'Request'    	=> 'Laravel\\Request',
+		'Response'   	=> 'Laravel\\Response',
+		'Route'      	=> 'Laravel\\Routing\\Route',
+		'Router'     	=> 'Laravel\\Routing\\Router',
+		'Schema'     	=> 'Laravel\\Database\\Schema',
+		'Section'    	=> 'Laravel\\Section',
+		'Session'    	=> 'Laravel\\Session',
+		'Str'        	=> 'Laravel\\Str',
+		'Task'       	=> 'Laravel\\CLI\\Tasks\\Task',
+		'URI'        	=> 'Laravel\\URI',
+		'Validator'  	=> 'Laravel\\Validator',
+		'View'       	=> 'Laravel\\View',
+	),
+
+);

+ 73 - 0
php-laravel/application/config/auth.php

@@ -0,0 +1,73 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Default Authentication Driver
+	|--------------------------------------------------------------------------
+	|
+	| Laravel uses a flexible driver-based system to handle authentication.
+	| You are free to register your own drivers using the Auth::extend
+	| method. Of course, a few great drivers are provided out of
+	| box to handle basic authentication simply and easily.
+	|
+	| Drivers: 'fluent', 'eloquent'.
+	|
+	*/
+
+	'driver' => 'eloquent',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Authentication Username
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify the database column that should be considered the
+	| "username" for your users. Typically, this will either be "username"
+	| or "email". Of course, you're free to change the value to anything.
+	|
+	*/
+
+	'username' => 'email',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Authentication Password
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify the database column that should be considered the
+	| "password" for your users. Typically, this will be "password" but, 
+	| again, you're free to change the value to anything you see fit.
+	|
+	*/
+
+	'password' => 'password',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Authentication Model
+	|--------------------------------------------------------------------------
+	|
+	| When using the "eloquent" authentication driver, you may specify the
+	| model that should be considered the "User" model. This model will
+	| be used to authenticate and load the users of your application.
+	|
+	*/
+
+	'model' => 'User',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Authentication Table
+	|--------------------------------------------------------------------------
+	|
+	| When using the "fluent" authentication driver, the database table used
+	| to load users may be specified here. This table will be used in by
+	| the fluent query builder to authenticate and load your users.
+	|
+	*/
+
+	'table' => 'users',
+
+);

+ 71 - 0
php-laravel/application/config/cache.php

@@ -0,0 +1,71 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Cache Driver
+	|--------------------------------------------------------------------------
+	|
+	| The name of the default cache driver for your application. Caching can
+	| be used to increase the performance of your application by storing any
+	| commonly accessed data in memory, a file, or some other storage.
+	|
+	| A variety of great drivers are available for you to use with Laravel.
+	| Some, like APC, are extremely fast. However, if that isn't an option
+	| in your environment, try file or database caching.
+	|
+	| Drivers: 'file', 'memcached', 'apc', 'redis', 'database'.
+	|
+	*/
+
+	'driver' => 'file',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Cache Key
+	|--------------------------------------------------------------------------
+	|
+	| This key will be prepended to item keys stored using Memcached and APC
+	| to prevent collisions with other applications on the server. Since the
+	| memory based stores could be shared by other applications, we need to
+	| be polite and use a prefix to uniquely identify our items.
+	|
+	*/
+
+	'key' => 'laravel',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Cache Database
+	|--------------------------------------------------------------------------
+	|
+	| When using the database cache driver, this database table will be used
+	| to store the cached item. You may also add a "connection" option to
+	| the array to specify which database connection should be used.
+	|
+	*/
+
+	'database' => array('table' => 'laravel_cache'),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Memcached Servers
+	|--------------------------------------------------------------------------
+	|
+	| The Memcached servers used by your application. Memcached is a free and
+	| open source, high-performance, distributed memory caching system. It is
+	| generic in nature but intended for use in speeding up web applications
+	| by alleviating database load.
+	|
+	| For more information, check out: http://memcached.org
+	|
+	*/
+
+	'memcached' => array(
+
+		array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100),
+
+	),	
+
+);

+ 125 - 0
php-laravel/application/config/database.php

@@ -0,0 +1,125 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Database Query Logging
+	|--------------------------------------------------------------------------
+	|
+	| By default, the SQL, bindings, and execution time are logged in an array
+	| for you to review. They can be retrieved via the DB::profile() method.
+	| However, in some situations, you may want to disable logging for
+	| ultra high-volume database work. You can do so here.
+	|
+	*/
+
+	'profile' => false,
+
+	/*
+	|--------------------------------------------------------------------------
+	| PDO Fetch Style
+	|--------------------------------------------------------------------------
+	|
+	| By default, database results will be returned as instances of the PHP
+	| stdClass object; however, you may wish to retrieve records as arrays
+	| instead of objects. Here you can control the PDO fetch style of the
+	| database queries run by your application.
+	|
+	*/
+
+	'fetch' => PDO::FETCH_CLASS,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Default Database Connection
+	|--------------------------------------------------------------------------
+	|
+	| The name of your default database connection. This connection will be used
+	| as the default for all database operations unless a different name is
+	| given when performing said operation. This connection name should be
+	| listed in the array of connections below.
+	|
+	*/
+
+	'default' => 'mysql',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Database Connections
+	|--------------------------------------------------------------------------
+	|
+	| All of the database connections used by your application. Many of your
+	| applications will no doubt only use one connection; however, you have
+	| the freedom to specify as many connections as you can handle.
+	|
+	| All database work in Laravel is done through the PHP's PDO facilities,
+	| so make sure you have the PDO drivers for your particular database of
+	| choice installed on your machine.
+	|
+	*/
+
+	'connections' => array(
+
+		'sqlite' => array(
+			'driver'   => 'sqlite',
+			'database' => 'application',
+			'prefix'   => '',
+		),
+
+		'mysql' => array(
+			'driver'   => 'mysql',
+			'host'     => 'localhost',
+			'database' => 'hello_world',
+			'username' => 'benchmarkdbuser',
+			'password' => 'benchmarkdbpass',
+			'charset'  => 'utf8',
+			'prefix'   => '',
+		),
+
+		'pgsql' => array(
+			'driver'   => 'pgsql',
+			'host'     => '127.0.0.1',
+			'database' => 'database',
+			'username' => 'root',
+			'password' => '',
+			'charset'  => 'utf8',
+			'prefix'   => '',
+			'schema'   => 'public',
+		),
+
+		'sqlsrv' => array(
+			'driver'   => 'sqlsrv',
+			'host'     => '127.0.0.1',
+			'database' => 'database',
+			'username' => 'root',
+			'password' => '',
+			'prefix'   => '',
+		),
+
+	),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Redis Databases
+	|--------------------------------------------------------------------------
+	|
+	| Redis is an open source, fast, and advanced key-value store. However, it
+	| provides a richer set of commands than a typical key-value store such as
+	| APC or memcached. All the cool kids are using it.
+	|
+	| To get the scoop on Redis, check out: http://redis.io
+	|
+	*/
+
+	'redis' => array(
+
+		'default' => array(
+			'host'     => '127.0.0.1',
+			'port'     => 6379,
+			'database' => 0
+		),
+
+	),
+
+);

+ 69 - 0
php-laravel/application/config/error.php

@@ -0,0 +1,69 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Ignored Error Levels
+	|--------------------------------------------------------------------------
+	|
+	| Here you simply specify the error levels that should be ignored by the
+	| Laravel error handler. These levels will still be logged; however, no
+	| information about them will be displayed.
+	|
+	*/
+
+	'ignore' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Error Detail
+	|--------------------------------------------------------------------------
+	|
+	| Detailed error messages contain information about the file in which an
+	| error occurs, as well as a PHP stack trace containing the call stack.
+	| You'll want them when you're trying to debug your application.
+	|
+	| If your application is in production, you'll want to turn off the error
+	| details for enhanced security and user experience since the exception
+	| stack trace could contain sensitive information.
+	|
+	*/
+
+	'detail' => true,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Error Logging
+	|--------------------------------------------------------------------------
+	|
+	| When error logging is enabled, the "logger" Closure defined below will
+	| be called for every error in your application. You are free to log the
+	| errors however you want. Enjoy the flexibility.
+	|
+	*/
+
+	'log' => false,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Error Logger
+	|--------------------------------------------------------------------------
+	|
+	| Because of the various ways of managing error logging, you get complete
+	| flexibility to manage error logging as you see fit. This function will
+	| be called anytime an error occurs within your application and error
+	| logging is enabled. 
+	|
+	| You may log the error message however you like; however, a simple log
+	| solution has been set up for you which will log all error messages to
+	| text files within the application storage directory.
+	|
+	*/
+
+	'logger' => function($exception)
+	{
+		Log::exception($exception);
+	},
+
+);

+ 97 - 0
php-laravel/application/config/mimes.php

@@ -0,0 +1,97 @@
+<?php
+
+return array(
+
+	'hqx'   => 'application/mac-binhex40',
+	'cpt'   => 'application/mac-compactpro',
+	'csv'   => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream'),
+	'bin'   => 'application/macbinary',
+	'dms'   => 'application/octet-stream',
+	'lha'   => 'application/octet-stream',
+	'lzh'   => 'application/octet-stream',
+	'exe'   => array('application/octet-stream', 'application/x-msdownload'),
+	'class' => 'application/octet-stream',
+	'psd'   => 'application/x-photoshop',
+	'so'    => 'application/octet-stream',
+	'sea'   => 'application/octet-stream',
+	'dll'   => 'application/octet-stream',
+	'oda'   => 'application/oda',
+	'pdf'   => array('application/pdf', 'application/x-download'),
+	'ai'    => 'application/postscript',
+	'eps'   => 'application/postscript',
+	'ps'    => 'application/postscript',
+	'smi'   => 'application/smil',
+	'smil'  => 'application/smil',
+	'mif'   => 'application/vnd.mif',
+	'xls'   => array('application/excel', 'application/vnd.ms-excel', 'application/msexcel'),
+	'ppt'   => array('application/powerpoint', 'application/vnd.ms-powerpoint'),
+	'wbxml' => 'application/wbxml',
+	'wmlc'  => 'application/wmlc',
+	'dcr'   => 'application/x-director',
+	'dir'   => 'application/x-director',
+	'dxr'   => 'application/x-director',
+	'dvi'   => 'application/x-dvi',
+	'gtar'  => 'application/x-gtar',
+	'gz'    => 'application/x-gzip',
+	'php'   => array('application/x-httpd-php', 'text/x-php'),
+	'php4'  => 'application/x-httpd-php',
+	'php3'  => 'application/x-httpd-php',
+	'phtml' => 'application/x-httpd-php',
+	'phps'  => 'application/x-httpd-php-source',
+	'js'    => 'application/x-javascript',
+	'swf'   => 'application/x-shockwave-flash',
+	'sit'   => 'application/x-stuffit',
+	'tar'   => 'application/x-tar',
+	'tgz'   => array('application/x-tar', 'application/x-gzip-compressed'),
+	'xhtml' => 'application/xhtml+xml',
+	'xht'   => 'application/xhtml+xml',
+	'zip'   => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'),
+	'mid'   => 'audio/midi',
+	'midi'  => 'audio/midi',
+	'mpga'  => 'audio/mpeg',
+	'mp2'   => 'audio/mpeg',
+	'mp3'   => array('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'),
+	'aif'   => 'audio/x-aiff',
+	'aiff'  => 'audio/x-aiff',
+	'aifc'  => 'audio/x-aiff',
+	'ram'   => 'audio/x-pn-realaudio',
+	'rm'    => 'audio/x-pn-realaudio',
+	'rpm'   => 'audio/x-pn-realaudio-plugin',
+	'ra'    => 'audio/x-realaudio',
+	'rv'    => 'video/vnd.rn-realvideo',
+	'wav'   => 'audio/x-wav',
+	'bmp'   => 'image/bmp',
+	'gif'   => 'image/gif',
+	'jpeg'  => array('image/jpeg', 'image/pjpeg'),
+	'jpg'   => array('image/jpeg', 'image/pjpeg'),
+	'jpe'   => array('image/jpeg', 'image/pjpeg'),
+	'png'   => 'image/png',
+	'tiff'  => 'image/tiff',
+	'tif'   => 'image/tiff',
+	'css'   => 'text/css',
+	'html'  => 'text/html',
+	'htm'   => 'text/html',
+	'shtml' => 'text/html',
+	'txt'   => 'text/plain',
+	'text'  => 'text/plain',
+	'log'   => array('text/plain', 'text/x-log'),
+	'rtx'   => 'text/richtext',
+	'rtf'   => 'text/rtf',
+	'xml'   => 'text/xml',
+	'xsl'   => 'text/xml',
+	'mpeg'  => 'video/mpeg',
+	'mpg'   => 'video/mpeg',
+	'mpe'   => 'video/mpeg',
+	'qt'    => 'video/quicktime',
+	'mov'   => 'video/quicktime',
+	'avi'   => 'video/x-msvideo',
+	'movie' => 'video/x-sgi-movie',
+	'doc'   => 'application/msword',
+	'docx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+	'xlsx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+	'word'  => array('application/msword', 'application/octet-stream'),
+	'xl'    => 'application/excel',
+	'eml'   => 'message/rfc822',
+	'json'  => array('application/json', 'text/json'),
+
+);

+ 117 - 0
php-laravel/application/config/session.php

@@ -0,0 +1,117 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Driver
+	|--------------------------------------------------------------------------
+	|
+	| The name of the session driver used by your application. Since HTTP is
+	| stateless, sessions are used to simulate "state" across requests made
+	| by the same user of your application. In other words, it's how an
+	| application knows who the heck you are.
+	|
+	| Drivers: 'cookie', 'file', 'database', 'memcached', 'apc', 'redis'.
+	|
+	*/
+
+	'driver' => 'cookie',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Database
+	|--------------------------------------------------------------------------
+	|
+	| The database table in which the session should be stored. It probably
+	| goes without saying that this option only matters if you are using
+	| the super slick database session driver.
+	|
+	*/
+
+	'table' => 'sessions',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Garbage Collection Probability
+	|--------------------------------------------------------------------------
+	|
+	| Some session drivers require the manual clean-up of expired sessions.
+	| This option specifies the probability of session garbage collection
+	| occuring for any given request to the application. 
+	|
+	| For example, the default value states that garbage collection has a
+	| 2% chance of occuring for any given request to the application.
+	| Feel free to tune this to your requirements.
+	|
+	*/
+
+	'sweepage' => array(2, 100),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Lifetime
+	|--------------------------------------------------------------------------
+	|
+	| The number of minutes a session can be idle before expiring.
+	|
+	*/
+
+	'lifetime' => 60,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Expiration On Close
+	|--------------------------------------------------------------------------
+	|
+	| Determines if the session should expire when the user's web browser closes.
+	|
+	*/
+
+	'expire_on_close' => false,
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Cookie Name
+	|--------------------------------------------------------------------------
+	|
+	| The name that should be given to the session cookie.
+	|
+	*/
+
+	'cookie' => 'laravel_session',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Cookie Path
+	|--------------------------------------------------------------------------
+	|
+	| The path for which the session cookie is available.
+	|
+	*/
+
+	'path' => '/',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Session Cookie Domain
+	|--------------------------------------------------------------------------
+	|
+	| The domain for which the session cookie is available.
+	|
+	*/
+
+	'domain' => null,
+
+	/*
+	|--------------------------------------------------------------------------
+	| HTTPS Only Session Cookie
+	|--------------------------------------------------------------------------
+	|
+	| Determines if the cookie should only be sent over HTTPS.
+	|
+	*/
+
+	'secure' => false,
+
+);

+ 190 - 0
php-laravel/application/config/strings.php

@@ -0,0 +1,190 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| String Inflection
+	|--------------------------------------------------------------------------
+	|
+	| This array contains the singular and plural forms of words. It's used by
+	| the "singular" and "plural" methods in the Str class to convert a given
+	| word from singular to plural and vice versa.
+	|
+	| Note that the regular expressions are only for inflecting English words.
+	| To inflect a non-English string, simply add its singular and plural
+	| form to the array of "irregular" word forms.
+	|
+	*/
+
+	'plural' => array(
+		'/(quiz)$/i' => "$1zes",
+		'/^(ox)$/i' => "$1en",
+		'/([m|l])ouse$/i' => "$1ice",
+		'/(matr|vert|ind)ix|ex$/i' => "$1ices",
+		'/(x|ch|ss|sh)$/i' => "$1es",
+		'/([^aeiouy]|qu)y$/i' => "$1ies",
+		'/(hive)$/i' => "$1s",
+		'/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
+		'/(shea|lea|loa|thie)f$/i' => "$1ves",
+		'/sis$/i' => "ses",
+		'/([ti])um$/i' => "$1a",
+		'/(tomat|potat|ech|her|vet)o$/i' => "$1oes",
+		'/(bu)s$/i' => "$1ses",
+		'/(alias)$/i' => "$1es",
+		'/(octop)us$/i' => "$1i",
+		'/(ax|test)is$/i' => "$1es",
+		'/(us)$/i' => "$1es",
+		'/s$/i' => "s",
+		'/$/' => "s"
+	),
+
+	'singular' => array(
+		'/(quiz)zes$/i' => "$1",
+		'/(matr)ices$/i' => "$1ix",
+		'/(vert|ind)ices$/i' => "$1ex",
+		'/^(ox)en$/i' => "$1",
+		'/(alias)es$/i' => "$1",
+		'/(octop|vir)i$/i' => "$1us",
+		'/(cris|ax|test)es$/i' => "$1is",
+		'/(shoe)s$/i' => "$1",
+		'/(o)es$/i' => "$1",
+		'/(bus)es$/i' => "$1",
+		'/([m|l])ice$/i' => "$1ouse",
+		'/(x|ch|ss|sh)es$/i' => "$1",
+		'/(m)ovies$/i' => "$1ovie",
+		'/(s)eries$/i' => "$1eries",
+		'/([^aeiouy]|qu)ies$/i' => "$1y",
+		'/([lr])ves$/i' => "$1f",
+		'/(tive)s$/i' => "$1",
+		'/(hive)s$/i' => "$1",
+		'/(li|wi|kni)ves$/i' => "$1fe",
+		'/(shea|loa|lea|thie)ves$/i' => "$1f",
+		'/(^analy)ses$/i' => "$1sis",
+		'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
+		'/([ti])a$/i' => "$1um",
+		'/(n)ews$/i' => "$1ews",
+		'/(h|bl)ouses$/i' => "$1ouse",
+		'/(corpse)s$/i' => "$1",
+		'/(us)es$/i' => "$1",
+		'/(us|ss)$/i' => "$1",
+		'/s$/i' => "",
+	),
+
+	'irregular' => array(
+		'child' => 'children',
+		'foot' => 'feet',
+		'goose' => 'geese',
+		'man' => 'men',
+		'move' => 'moves',
+		'person' => 'people',
+		'sex' => 'sexes',
+		'tooth' => 'teeth',
+	),
+
+	'uncountable' => array(
+		'audio',
+		'equipment',
+		'deer',
+		'fish',
+		'gold',
+		'information',
+		'money',
+		'rice',
+		'police',
+		'series',
+		'sheep',
+		'species',
+		'moose',
+		'chassis',
+		'traffic',
+	),
+
+	/*
+	|--------------------------------------------------------------------------
+	| ASCII Characters
+	|--------------------------------------------------------------------------
+	|
+	| This array contains foreign characters and their 7-bit ASCII equivalents.
+	| The array is used by the "ascii" method on the Str class to get strings
+	| ready for inclusion in a URL slug.
+	|
+	| Of course, the "ascii" method may also be used by you for whatever your
+	| application requires. Feel free to add any characters we missed, and be
+	| sure to let us know about them!
+	|
+	*/
+
+	'ascii' => array(
+
+		'/æ|ǽ/' => 'ae',
+		'/œ/' => 'oe',
+		'/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ|А/' => 'A',
+		'/à|á|â|ã|ä|å|ǻ|ā|ă|ą|ǎ|ª|а/' => 'a',
+		'/Б/' => 'B',
+		'/б/' => 'b',
+		'/Ç|Ć|Ĉ|Ċ|Č|Ц/' => 'C',
+		'/ç|ć|ĉ|ċ|č|ц/' => 'c',
+		'/Ð|Ď|Đ|Д/' => 'Dj',
+		'/ð|ď|đ|д/' => 'dj',
+		'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Е|Ё|Э/' => 'E',
+		'/è|é|ê|ë|ē|ĕ|ė|ę|ě|е|ё|э/' => 'e',
+		'/Ф/' => 'F',
+		'/ƒ|ф/' => 'f',
+		'/Ĝ|Ğ|Ġ|Ģ|Г/' => 'G',
+		'/ĝ|ğ|ġ|ģ|г/' => 'g',
+		'/Ĥ|Ħ|Х/' => 'H',
+		'/ĥ|ħ|х/' => 'h',
+		'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|И/' => 'I',
+		'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|и/' => 'i',
+		'/Ĵ|Й/' => 'J',
+		'/ĵ|й/' => 'j',
+		'/Ķ|К/' => 'K',
+		'/ķ|к/' => 'k',
+		'/Ĺ|Ļ|Ľ|Ŀ|Ł|Л/' => 'L',
+		'/ĺ|ļ|ľ|ŀ|ł|л/' => 'l',
+		'/М/' => 'M',
+		'/м/' => 'm',
+		'/Ñ|Ń|Ņ|Ň|Н/' => 'N',
+		'/ñ|ń|ņ|ň|ʼn|н/' => 'n',
+		'/Ö|Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|О/' => 'O',
+		'/ö|ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|о/' => 'o',
+		'/П/' => 'P',
+		'/п/' => 'p',
+		'/Ŕ|Ŗ|Ř|Р/' => 'R',
+		'/ŕ|ŗ|ř|р/' => 'r',
+		'/Ś|Ŝ|Ş|Ș|Š|С/' => 'S',
+		'/ś|ŝ|ş|ș|š|ſ|с/' => 's',
+		'/Ţ|Ț|Ť|Ŧ|Т/' => 'T',
+		'/ţ|ț|ť|ŧ|т/' => 't',
+		'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ü|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|У/' => 'U',
+		'/ù|ú|û|ũ|ū|ŭ|ů|ü|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|у/' => 'u',
+		'/В/' => 'V',
+		'/в/' => 'v',
+		'/Ý|Ÿ|Ŷ|Ы/' => 'Y',
+		'/ý|ÿ|ŷ|ы/' => 'y',
+		'/Ŵ/' => 'W',
+		'/ŵ/' => 'w',
+		'/Ź|Ż|Ž|З/' => 'Z',
+		'/ź|ż|ž|з/' => 'z',
+		'/Æ|Ǽ/' => 'AE',
+		'/ß/'=> 'ss',
+		'/IJ/' => 'IJ',
+		'/ij/' => 'ij',
+		'/Œ/' => 'OE',
+		'/Ч/' => 'Ch',
+		'/ч/' => 'ch',
+		'/Ю/' => 'Ju',
+		'/ю/' => 'ju',
+		'/Я/' => 'Ja',
+		'/я/' => 'ja',
+		'/Ш/' => 'Sh',
+		'/ш/' => 'sh',
+		'/Щ/' => 'Shch',
+		'/щ/' => 'shch',
+		'/Ж/' => 'Zh',
+		'/ж/' => 'zh',
+
+	),
+
+);

+ 17 - 0
php-laravel/application/controllers/base.php

@@ -0,0 +1,17 @@
+<?php
+
+class Base_Controller extends Controller {
+
+	/**
+	 * Catch-all method for requests that can't be matched.
+	 *
+	 * @param  string    $method
+	 * @param  array     $parameters
+	 * @return Response
+	 */
+	public function __call($method, $parameters)
+	{
+		return Response::error('404');
+	}
+
+}

+ 38 - 0
php-laravel/application/controllers/home.php

@@ -0,0 +1,38 @@
+<?php
+
+class Home_Controller extends Base_Controller {
+
+	/*
+	|--------------------------------------------------------------------------
+	| The Default Controller
+	|--------------------------------------------------------------------------
+	|
+	| Instead of using RESTful routes and anonymous functions, you might wish
+	| to use controllers to organize your application API. You'll love them.
+	|
+	| This controller responds to URIs beginning with "home", and it also
+	| serves as the default controller for the application, meaning it
+	| handles requests to the root of the application.
+	|
+	| You can respond to GET requests to "/home/profile" like so:
+	|
+	|		public function action_profile()
+	|		{
+	|			return "This is your profile!";
+	|		}
+	|
+	| Any extra segments are passed to the method as parameters:
+	|
+	|		public function action_profile($id)
+	|		{
+	|			return "This is the profile for user {$id}.";
+	|		}
+	|
+	*/
+
+	public function action_index()
+	{
+		return View::make('home.index');
+	}
+
+}

+ 19 - 0
php-laravel/application/language/ar/pagination.php

@@ -0,0 +1,19 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '→ السابق',
+	'next'     => 'التالي ←',
+
+);

+ 104 - 0
php-laravel/application/language/ar/validation.php

@@ -0,0 +1,104 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "القيمة :attribute يجب أن تكون مقبولة.",
+	"active_url"     => "القيمة :attribute تمثل عنوان موقع إنترنت غير صحيح.",
+	"after"          => "القيمة :attribute يجب أن تكون بعد تاريخ :date.",
+	"alpha"          => "القيمة :attribute يمكنها أن تحتوي على أحرف فقط.",
+	"alpha_dash"     => "القيمة :attribute يمكنها أن تحتوي على أحرف و أرقام و إشارة الناقص فقط.",
+	"alpha_num"      => "القيمة :attribute يمكنها أن تحتوي على أحرف و أرقام فقط.",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => "القيمة :attribute يجب أن تكون قبل تاريخ :date.",
+	"between"        => array(
+		"numeric" => "القيمة :attribute يجب أن تكون بين :min و :max.",
+		"file"    => "الملف :attribute يجب أن يكون بحجم من :min إلى :max كيلوبايت.",
+		"string"  => "النص :attribute يجب أن يكون بطول من :min إلى :max حرف.",
+	),
+	"confirmed"      => "القيمة :attribute التأكيدية غير مطابقة.",
+	"count"          => "The :attribute must have exactly :count selected elements.",
+	"countbetween"   => "The :attribute must have between :min and :max selected elements.",
+	"countmax"       => "The :attribute must have less than :max selected elements.",
+	"countmin"       => "The :attribute must have at least :min selected elements.",
+	"different"      => "القيمتان :attribute و :other يجب أن تختلفان.",
+	"email"          => "القيمة :attribute تمثل بريد إلكتروني غير صحيح.",
+	"exists"         => "القيمة المختارة :attribute غير موجودة.",
+	"image"          => "القيمة :attribute يجب أن تكون صورة.",
+	"in"             => "القيمة المختارة :attribute غير موجودة.",
+	"integer"        => "القيمة :attribute يجب أن تكون رقماً.",
+	"ip"             => "القيمة :attribute يجب أن تمثل عنوان بروتوكول إنترنت صحيح.",
+	"match"          => "القيمة :attribute هي بتنسيق غير صحيح.",
+	"max"            => array(
+		"numeric" => "القيمة :attribute يجب أن تكون أقل من :max.",
+		"file"    => "الملف :attribute يجب أن يكون بحجم أقل من :max كيلوبايت.",
+		"string"  => "النص :attribute يجب أن يكون بطول أقل من :max حرف.",
+	),
+	"mimes"          => "القيمة :attribute يجب أن تكون ملف من نوع: :values.",
+	"min"            => array(
+		"numeric" => "القيمة :attribute يجب أن تساوي :min على الأقل.",
+		"file"    => "الملف :attribute يجب أن يكون بحجم :min كيلوبايت على الأقل.",
+		"string"  => "النص :attribute يجب أن يكون بطول :min حرف على الأقل.",
+	),
+	"not_in"         => "القيمة :attribute المختارة غير صحيحة.",
+	"numeric"        => "القيمة :attribute يجب أن تكون رقماً.",
+	"required"       => "القيمة :attribute مطلوبة.",
+	"same"           => "القيمتان :attribute و :other يجب أن تتطابقان.",
+	"size"           => array(
+		"numeric" => "القيمة :attribute يجب أن تكون بحجم :size.",
+		"file"    => "الملف :attribute يجب أن يكون بحجم :size كيلوبايت.",
+		"string"  => "النص :attribute يجب أن يكون بطول :size حرف.",
+	),
+	"unique"         => "القيمة :attribute تم استخدامها من قبل.",
+	"url"            => "التنسيق :attribute غير صحيح.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/bg/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Назад',
+	'next'     => 'Напред &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/bg/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Трябва да приемете :attribute.",
+	"active_url"     => "Полето :attribute не е валиден URL адрес.",
+	"after"          => "Полето :attribute трябва да бъде дата след :date.",
+	"alpha"          => "Полето :attribute трябва да съдържа само букви.",
+	"alpha_dash"     => "Полето :attribute трябва да съдържа само букви, цифри, долна черта и тире.",
+	"alpha_num"      => "Полето :attribute трябва да съдържа само букви и цифри.",
+	"array"          => "Полето :attribute трябва да има избрани елементи.",
+	"before"         => "Полето :attribute трябва да бъде дата преди :date.",
+	"between"        => array(
+		"numeric" => "Полето :attribute трябва да бъде между :min и :max.",
+		"file"    => "Полето :attribute трябва да бъде между :min и :max килобайта.",
+		"string"  => "Полето :attribute трябва да бъде между :min и :max знака.",
+	),
+	"confirmed"      => "Полето :attribute не е потвърдено.",
+	"count"          => "Полето :attribute трябва да има точно :count избрани елементи.",
+	"countbetween"   => "Полето :attribute трябва да има от :min до :max избрани елементи.",
+	"countmax"       => "Полето :attribute трябва да има по-малко от :max избрани елементи.",
+	"countmin"       => "Полето :attribute трябва да има минимум :min избрани елементи.",
+	"different"      => "Полетата :attribute и :other трябва да са различни.",
+	"email"          => "Полето :attribute е с невалиден формат.",
+	"exists"         => "Избраната стойност на :attribute вече съществува.",
+	"image"          => "Полето :attribute трябва да бъде изображение.",
+	"in"             => "Стойността на :attribute е невалидна.",
+	"integer"        => "Полето :attribute трябва да бъде цяло число.",
+	"ip"             => "Полето :attribute трябва да бъде IP адрес.",
+	"match"          => "Полето :attribute е с невалиден формат.",
+	"max"            => array(
+		"numeric" => "Полето :attribute трябва да бъде по-малко от :max.",
+		"file"    => "Полето :attribute трябва да бъде по-малко от :max килобайта.",
+		"string"  => "Полето :attribute трябва да бъде по-малко от :max знака.",
+	),
+	"mimes"          => "Полето :attribute трябва да бъде файл от тип: :values.",
+	"min"            => array(
+		"numeric" => "Полето :attribute трябва да бъде минимум :min.",
+		"file"    => "Полето :attribute трябва да бъде минимум :min килобайта.",
+		"string"  => "Полето :attribute трябва да бъде минимум :min знака.",
+	),
+	"not_in"         => "Стойността на :attribute е невалидна.",
+	"numeric"        => "Полето :attribute трябва да бъде число.",
+	"required"       => "Полето :attribute е задължително.",
+	"same"           => "Стойностите на :attribute и :other трябва да съвпадат.",
+	"size"           => array(
+		"numeric" => "Полето :attribute трябва да бъде :size.",
+		"file"    => "Полето :attribute трябва да бъде :size килобайта.",
+		"string"  => "Полето :attribute трябва да бъде :size знака.",
+	),
+	"unique"         => "Стойността на :attribute вече съществува.",
+	"url"            => "Полето :attribute е с невалиден формат.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/da/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Forrige',
+	'next'     => 'N&aelig;ste &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/da/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute skal accepteres.",
+	"active_url"     => ":attribute er ikke en gyldig URL.",
+	"after"          => ":attribute skal v&aelig;re en dato efter :date.",
+	"alpha"          => ":attribute m&aring; kun indeholde bogstaver.",
+	"alpha_dash"     => ":attribute m&aring; kun indeholde bogstaver, numre, og skr&aring;streg.",
+	"alpha_num"      => ":attribute m&aring; kun indeholde bogstaver og numre.",
+	"array"          => ":attribute skal have valgte elementer.",
+	"before"         => ":attribute skal have en dato f&oslash;r :date.",
+	"between"        => array(
+		"numeric" => ":attribute skal v&aelig;re mellem :min - :max.",
+		"file"    => ":attribute skal v&aelig;re mellem :min - :max kilobytes.",
+		"string"  => ":attribute skal v&aelig;re mellem :min - :max karakterer.",
+	),
+	"confirmed"      => ":attribute bekr&aelig;ftelse stemmer ikke overens.",
+	"count"          => ":attribute skal v&aelig;re pr&aelig;cis :count valgte elementer.",
+	"countbetween"   => ":attribute skal v&aelig;re mellem :min and :max valgte elementer.",
+	"countmax"       => ":attribute skal have mindre end :max valgte elementer.",
+	"countmin"       => ":attribute skal have minimum :min valgte elementer.",
+	"different"      => ":attribute og :other skal v&aelig;re forskellige.",
+	"email"          => "Formatet for :attribute er ugyldigt.",
+	"exists"         => "Den valgte :attribute er ugyldig.",
+	"image"          => ":attribute skal v&aelig;re et billede.",
+	"in"             => "Den valgte :attribute er ugyldig.",
+	"integer"        => ":attribute m&aring; kun indeholde tal.",
+	"ip"             => ":attribute skal v&aelig;re en gyldig IP adresse.",
+	"match"          => "Formatet for :attribute er ugyldigt.",
+	"max"            => array(
+		"numeric" => ":attribute skal v&aelig;re mindre end :max.",
+		"file"    => ":attribute skal v&aelig;re mindre end :max kilobytes.",
+		"string"  => ":attribute skal v&aelig;re mindre end :max karakterer.",
+	),
+	"mimes"          => ":attribute skal have filtypen type: :values.",
+	"min"            => array(
+		"numeric" => ":attribute ska minimum v&aelig;re :min.",
+		"file"    => ":attribute skal v&aelig;re mindst :min kilobytes.",
+		"string"  => ":attribute skal v&aelig;re mindst :min karakterer.",
+	),
+	"not_in"         => "Den valgte :attribute er ugyldig.",
+	"numeric"        => ":attribute skal v&aelig;re et nummer.",
+	"required"       => ":attribute er kr&aelig;vet.",
+	"same"           => ":attribute og :other stemmer ikke overens.",
+	"size"           => array(
+		"numeric" => ":attribute skal v&aelig;re :size.",
+		"file"    => ":attribute skal v&aelig;re :size kilobyte.",
+		"string"  => ":attribute skal v&aelig;re :size karakterer.",
+	),
+	"unique"         => ":attribute er allerede optaget.",
+	"url"            => ":attribute formatet er ugyldigt.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/de/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Zur&uuml;ck',
+	'next'     => 'Weiter &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/de/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute muss akzeptiert werden.",
+	"active_url"     => ":attribute ist keine g&uuml;ltige URL.",
+	"after"          => ":attribute muss ein Datum nach dem :date sein.",
+	"alpha"          => ":attribute darf nur Buchstaben beinhalten.",
+	"alpha_dash"     => ":attribute darf nur aus Buchstaben, Nummern und Bindestrichen bestehen.",
+	"alpha_num"      => ":attribute darf nur aus Buchstaben und Nummern bestehen.",
+	"array"          => ":attribute muss ausgew&auml;hlte Elemente haben.",
+	"before"         => ":attribute muss ein Datum vor dem :date sein.",
+	"between"        => array(
+		"numeric" => ":attribute muss zwischen :min und :max liegen.",
+		"file"    => ":attribute muss zwischen :min und :max Kilobytes gro&szlig; sein.",
+		"string"  => ":attribute muss zwischen :min und :max Zeichen lang sein.",
+	),
+	"confirmed"      => ":attribute stimmt nicht mit der Best&auml;tigung &uuml;berein.",
+	"count"          => ":attribute muss genau :count ausgew&auml;hlte Elemente haben.",
+	"countbetween"   => ":attribute muss zwischen :min und :max ausgew&auml;hlte Elemente haben.",
+	"countmax"       => ":attribute muss weniger als :max ausgew&auml;hlte Elemente haben.",
+	"countmin"       => ":attribute muss mindestens :min ausgew&auml;hlte Elemente haben.",
+	"different"      => ":attribute und :other m&uuml;ssen verschieden sein.",
+	"email"          => ":attribute ist keine g&uuml;ltige Email-Adresse.",
+	"exists"         => "Der gew&auml;hlte Wert f&uuml;r :attribute ist ung&uuml;ltig.",
+	"image"          => ":attribute muss ein Bild sein.",
+	"in"             => "Der gew&auml;hlte Wert f&uuml;r :attribute ist ung&uuml;ltig.",
+	"integer"        => ":attribute muss eine ganze Zahl sein.",
+	"ip"             => ":attribute muss eine g&uuml;ltige IP-Adresse sein.",
+	"match"          => ":attribute hat ein ung&uuml;ltiges Format.",
+	"max"            => array(
+		"numeric" => ":attribute muss kleiner als :max sein.",
+		"file"    => ":attribute muss kleiner als :max Kilobytes gro&szlig; sein.",
+		"string"  => ":attribute muss k&uuml;rzer als :max Zeichen sein.",
+	),
+	"mimes"          => ":attribute muss den Dateityp :values haben.",
+	"min"            => array(
+		"numeric" => ":attribute muss gr&ouml;&szlig;er als :min sein.",
+		"file"    => ":attribute muss gr&ouml;&szlig;er als :min Kilobytes gro&szlig; sein.",
+		"string"  => ":attribute muss l&auml;nger als :min Zeichen sein.",
+	),
+	"not_in"         => "Der gew&auml;hlte Wert f&uuml;r :attribute ist ung&uuml;ltig.",
+	"numeric"        => ":attribute muss eine Zahl sein.",
+	"required"       => ":attribute muss ausgef&uuml;llt sein.",
+	"same"           => ":attribute und :other m&uuml;ssen &uuml;bereinstimmen.",
+	"size"           => array(
+		"numeric" => ":attribute muss gleich :size sein.",
+		"file"    => ":attribute muss :size Kilobyte gro&szlig; sein.",
+		"string"  => ":attribute muss :size Zeichen lang sein.",
+	),
+	"unique"         => ":attribute ist schon vergeben.",
+	"url"            => "Das Format von :attribute ist ung&uuml;ltig.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/el/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Προηγούμενο',
+	'next'     => 'Επόμενο &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/el/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Το πεδίο :attribute πρέπει να εγκριθεί.",
+	"active_url"     => "Το πεδίο :attribute δεν ειναι σωστό URL.",
+	"after"          => "Το πεδίο :attribute πρέπει η ημερομηνία να ειναι μετά :date.",
+	"alpha"          => "Το πεδίο :attribute μπορεί να περιλαμβάνει μόνο γράμματα.",
+	"alpha_dash"     => "Το πεδίο :attribute μπορεί να περιλαμβάνει μόνο γράμματα, αριθμούς και παύλες.",
+	"alpha_num"      => "Το πεδίο :attribute μπορεί να περιλαμβάνει μόνο γράμματα και αριθμούς.",
+	"array"          => "Το πεδίο :attribute πρέπει να περιλαμβάνει επιλεγμένα αντικείμενα.",
+	"before"         => "Το πεδίο :attribute πρέπει η ημερομηνία να ειναι πριν από :date.",
+	"between"        => array(
+		"numeric" => "Το πεδίο :attribute πρέπει να έχει τιμές μεταξύ :min - :max.",
+		"file"    => "Το πεδίο :attribute πρέπει να ειναι ανάμεσα σε :min - :max kb.",
+		"string"  => "Το πεδίο :attribute πρέπει να περιλαμβάνει :min - :max χαρακτήρες.",
+	),
+	"confirmed"      => "Το πεδίο :attribute δεν πέρασε τον έλεγχο.",
+	"count"          => "Το πεδίο :attribute πρέπει να έχει ακριβώς :count επιλεγμένα αντικείμενα.",
+	"countbetween"   => "Το πεδίο :attribute πρέπει να είναι ανάμεσα σε :min και :max επιλεγμένα αντικείμενα.",
+	"countmax"       => "Το πεδίο :attribute πρέπει να έχει λιγότερα από :max επιλεγμένα αντικείμενα.",
+	"countmin"       => "Το πεδίο :attribute πρέπει να έχει τουλάχιστον :min επιλεγμένα αντικείμενα.",
+	"different"      => "Τα πεδία :attribute και :other πρέπει να ειναι διαφορετικά.",
+	"email"          => "Στο πεδίο :attribute η μορφοποίηση ειναι άκυρη.",
+	"exists"         => "Το επιλεγμένο πεδίο :attribute είναι άκυρο.",
+	"image"          => "Το πεδίο :attribute πρέπει να είναι εικόνα.",
+	"in"             => "Το επιλεγμένο πεδίο :attribute είναι άκυρο.",
+	"integer"        => "Το πεδίο :attribute πρέπει να ειναι αριθμός.",
+	"ip"             => "Το πεδίο :attribute πρέπει να ειναι μια έγκυρη διεύθυνση IP.",
+	"match"          => "Το φορμάτ του πεδίου :attribute είναι άκυρο.",
+	"max"            => array(
+		"numeric" => "Το πεδίο :attribute πρέπει να είναι μικρότερο από :max.",
+		"file"    => "Το πεδίο :attribute πρέπει να είναι μικρότερο από :max kb.",
+		"string"  => "Το πεδίο :attribute πρέπει να έχει λιγότερους από :max χαρακτήρες.",
+	),
+	"mimes"          => "Το πεδίο :attribute πρέπει να ειναι αρχείο με τύπο: :values.",
+	"min"            => array(
+		"numeric" => "Το πεδίο :attribute πρέπει να είναι τουλάχιστον :min.",
+		"file"    => "Το πεδίο :attribute πρέπει να είναι μικρότερο από :max kb.",
+		"string"  => "Το πεδίο :attribute πρέπει να έχει λιγότερους από :max χαρακτήρες.",
+	),
+	"not_in"         => "Το επιλεγμένο πεδίο :attribute είναι άκυρο.",
+	"numeric"        => "Το πεδίο :attribute πρέπει να είναι αριθμός.",
+	"required"       => "Το πεδίο :attribute είναι απαραίτητο.",
+	"same"           => "Τα πεδία :attribute και :other πρέπει να είναι ίδια.",
+	"size"           => array(
+		"numeric" => "Το πεδίο :attribute πρέπει να ειναι :size.",
+		"file"    => "Το πεδίο :attribute πρέπει να έχει μέγεθος :size kb.",
+		"string"  => "Το πεδίο :attribute πρέπει να είναι :size χαρακτήρες.",
+	),
+	"unique"         => "Το πεδίο :attribute έχει ήδη ανατεθεί.",
+	"url"            => "Το πεδίο :attribute είναι άκυρο.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/en/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Previous',
+	'next'     => 'Next &raquo;',
+
+);

+ 106 - 0
php-laravel/application/language/en/validation.php

@@ -0,0 +1,106 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "The :attribute must be accepted.",
+	"active_url"     => "The :attribute is not a valid URL.",
+	"after"          => "The :attribute must be a date after :date.",
+	"alpha"          => "The :attribute may only contain letters.",
+	"alpha_dash"     => "The :attribute may only contain letters, numbers, and dashes.",
+	"alpha_num"      => "The :attribute may only contain letters and numbers.",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => "The :attribute must be a date before :date.",
+	"between"        => array(
+		"numeric" => "The :attribute must be between :min - :max.",
+		"file"    => "The :attribute must be between :min - :max kilobytes.",
+		"string"  => "The :attribute must be between :min - :max characters.",
+	),
+	"confirmed"      => "The :attribute confirmation does not match.",
+	"count"          => "The :attribute must have exactly :count selected elements.",
+	"countbetween"   => "The :attribute must have between :min and :max selected elements.",
+	"countmax"       => "The :attribute must have less than :max selected elements.",
+	"countmin"       => "The :attribute must have at least :min selected elements.",
+	"date_format"	 => "The :attribute must have a valid date format.",
+	"different"      => "The :attribute and :other must be different.",
+	"email"          => "The :attribute format is invalid.",
+	"exists"         => "The selected :attribute is invalid.",
+	"image"          => "The :attribute must be an image.",
+	"in"             => "The selected :attribute is invalid.",
+	"integer"        => "The :attribute must be an integer.",
+	"ip"             => "The :attribute must be a valid IP address.",
+	"match"          => "The :attribute format is invalid.",
+	"max"            => array(
+		"numeric" => "The :attribute must be less than :max.",
+		"file"    => "The :attribute must be less than :max kilobytes.",
+		"string"  => "The :attribute must be less than :max characters.",
+	),
+	"mimes"          => "The :attribute must be a file of type: :values.",
+	"min"            => array(
+		"numeric" => "The :attribute must be at least :min.",
+		"file"    => "The :attribute must be at least :min kilobytes.",
+		"string"  => "The :attribute must be at least :min characters.",
+	),
+	"not_in"         => "The selected :attribute is invalid.",
+	"numeric"        => "The :attribute must be a number.",
+	"required"       => "The :attribute field is required.",
+    "required_with"  => "The :attribute field is required with :field",
+	"same"           => "The :attribute and :other must match.",
+	"size"           => array(
+		"numeric" => "The :attribute must be :size.",
+		"file"    => "The :attribute must be :size kilobyte.",
+		"string"  => "The :attribute must be :size characters.",
+	),
+	"unique"         => "The :attribute has already been taken.",
+	"url"            => "The :attribute format is invalid.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/fi/pagination.php

@@ -0,0 +1,19 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Edellinen',
+	'next'     => 'Seuraava &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/fi/validation.php

@@ -0,0 +1,104 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute pitää hyväksyä.",
+	"active_url"     => ":attribute pitää olla validi URL-osoite.",
+	"after"          => ":attribute pitää olla päiväys :date päiväyksen jälkeen.",
+	"alpha"          => ":attribute voi vain sisältää kirjaimia.",
+	"alpha_dash"     => ":attribute voi vain sisältää kirjaimia, numeroita ja viivoja.",
+	"alpha_num"      => ":attribute voi vain sisältää kirjaimia ja numeroita.",
+	"array"          => ":attribute pitää sisältää elementin.",
+	"before"         => ":attribute pitää olla päiväys ennen :date.",
+	"between"        => array(
+		"numeric" => ":attribute numeron pitää olla välillä :min - :max.",
+		"file"    => ":attribute tiedoston pitää olla välillä :min - :max kilobittiä.",
+		"string"  => ":attribute elementin pitää olla välillä :min - :max kirjainta.",
+	),
+	"confirmed"      => ":attribute vahvistus ei täsmää.",
+	"count"          => ":attribute pitää olla tarkalleen :count määrä elementtejä.",
+	"countbetween"   => ":attribute pitää olla välillä :min ja :max määrä elementtejä.",
+	"countmax"       => ":attribute pitää olla vähemmän kun :max määrä elementtejä.",
+	"countmin"       => ":attribute pitää olla vähintään :min määrä elementtejä.",
+	"different"      => ":attribute ja :other tulee olla eri arvoisia.",
+	"email"          => ":attribute muoto on virheellinen.",
+	"exists"         => "valittu :attribute on virheellinen.",
+	"image"          => ":attribute pitää olla kuva.",
+	"in"             => "valittu :attribute on virheellinen.",
+	"integer"        => ":attribute pitää olla numero.",
+	"ip"             => ":attribute pitää olla validi IP-osoite.",
+	"match"          => ":attribute muoto on virheellinen.",
+	"max"            => array(
+		"numeric" => ":attribute pitää olla pienempi kuin :max.",
+		"file"    => ":attribute pitää olla pienempi :max kilobittiä.",
+		"string"  => ":attribute pitää olla pienempi :max kirjainta.",
+	),
+	"mimes"          => ":attribute pitää olla tiedostotyyppi: :values.",
+	"min"            => array(
+		"numeric" => ":attribute pitää olla vähintään :min.",
+		"file"    => ":attribute pitää olla vähintään :min kilobittiä.",
+		"string"  => ":attribute pitää olla vähintään :min kirjainta.",
+	),
+	"not_in"         => "valittu :attribute on virheellinen.",
+	"numeric"        => ":attribute pitää olla numero.",
+	"required"       => ":attribute kenttä on pakollinen.",
+	"same"           => ":attribute ja :other on oltava samat.",
+	"size"           => array(
+		"numeric" => ":attribute pitää olla kokoa: :size.",
+		"file"    => ":attribute pitää olla kokoa: :size kilobittiä.",
+		"string"  => ":attribute pitää olla kokoa: :size kirjainta.",
+	),
+	"unique"         => ":attribute on jo valittu.",
+	"url"            => ":attribute URL-osoite on virheellinen.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/fr/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Précédent',
+	'next'     => 'Suivant &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/fr/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Le champ :attribute doit être accepté.",
+	"active_url"     => "Le champ :attribute n'est pas une URL valide.",
+	"after"          => "Le champ :attribute doit être une date après :date.",
+	"alpha"          => "Le champ :attribute ne doit contenir que des lettres.",
+	"alpha_dash"     => "Le champ :attribute ne doit contenir que des lettres, nombres et des tirets.",
+	"alpha_num"      => "Le champ :attribute ne doit contenir que des lettres et nombres.",
+	"array"          => "Le champ :attribute doit avoir des éléments selectionnés.",
+	"before"         => "Le champ :attribute doit être une date avant :date.",
+	"between"        => array(
+		"numeric" => "Le champ :attribute doit être entre :min - :max.",
+		"file"    => "Le champ :attribute doit être entre :min - :max kilo-octets.",
+		"string"  => "Le champ :attribute doit être entre :min - :max caractères.",
+	),
+	"confirmed"      => "Le champ :attribute confirmation est différent.",
+	"count"          => "Le champ :attribute doit avoir exactement :count éléments sélectionnés.",
+	"countbetween"   => "Le champ :attribute doit avoir entre :min et :max éléments sélectionnés.",
+	"countmax"       => "Le champ :attribute doit avoir moins de :max éléments sélectionnés.",
+	"countmin"       => "Le champ :attribute doit avoir au moins :min éléments sélectionnés.",
+	"different"      => "Les champs :attribute et :other doivent être différents.",
+	"email"          => "Le format du champ :attribute est invalide.",
+	"exists"         => "Le champ sélectionné :attribute est invalide.",
+	"image"          => "Le champ :attribute doit être une image.",
+	"in"             => "Le champ sélectionné :attribute est invalide.",
+	"integer"        => "Le champ :attribute doit être un entier.",
+	"ip"             => "Le champ :attribute doit être une adresse IP valide.",
+	"match"          => "Le format du champ :attribute est invalide.",
+	"max"            => array(
+		"numeric" => "Le champ :attribute doit être plus petit que :max.",
+		"file"    => "Le champ :attribute doit être plus petit que :max kilo-octets.",
+		"string"  => "Le champ :attribute doit être plus petit que :max caractères.",
+	),
+	"mimes"          => "Le champ :attribute doit être un fichier de type: :values.",
+	"min"            => array(
+		"numeric" => "Le champ :attribute doit être au moins :min.",
+		"file"    => "Le champ :attribute doit être au moins de :min kilo-octets.",
+		"string"  => "Le champ :attribute doit avoir au moins :min caractères.",
+	),
+	"not_in"         => "Le champ sélectionné :attribute est invalide.",
+	"numeric"        => "Le champ :attribute doit être un nombre.",
+	"required"       => "Le champ :attribute est requis",
+	"same"           => "Les champs :attribute et :other doivent être identique.",
+	"size"           => array(
+		"numeric" => "Le champ :attribute doit être :size.",
+		"file"    => "Le champ :attribute doit être de :size kilo-octets.",
+		"string"  => "Le champ :attribute doit être de :size caractères.",
+	),
+	"unique"         => "Le champ :attribute est déjà utilisé.",
+	"url"            => "Le champ :attribute a un format invalide.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/he/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&rarr; אחורה',
+	'next'     => 'קדימה &larr;',
+
+);

+ 107 - 0
php-laravel/application/language/he/validation.php

@@ -0,0 +1,107 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	| Hebrew Translation:
+	| Nir Lahad - www.nirlah.com
+	|
+	*/
+
+	"accepted"       => "חובה להסכים ל-:attribute.",
+	"active_url"     => "הערך :attribute חייב להכיל כתובת אינטרנט פעילה.",
+	"after"          => "הערך :attribute חייב להכיל תאריך אחרי :date.",
+	"alpha"          => "הערך :attribute יכול להכיל רק אותיות.",
+	"alpha_dash"     => "הערך :attribute יכול להכיל רק אותיות, מספרים ומקפים.",
+	"alpha_num"      => "הערך :attribute יכול להכיל רק אותיות ומספרים.",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => "הערך :attribute חייב להכיל תאריך לפני :date.",
+	"between"        => array(
+		"numeric" => "הערך :attribute חייב להיות בין :min ל-:max.",
+		"file"    => "הערך :attribute חייב לשקול בין :min ל-:max ק&quot;ב.",
+		"string"  => "הערך :attribute חייב להכיל בין :min ל-:max תווים.",
+	),
+	"confirmed"      => "הערכים של :attribute חייבים להיות זהים.",
+	"count"          => "The :attribute must have exactly :count selected elements.",
+	"countbetween"   => "The :attribute must have between :min and :max selected elements.",
+	"countmax"       => "The :attribute must have less than :max selected elements.",
+	"countmin"       => "The :attribute must have at least :min selected elements.",
+	"different"      => "הערכים של :attribute ו-:other חייבים להיות שונים.",
+	"email"          => "הערך :attribute חייב להכיל כתובת אימייל תקינה.",
+	"exists"         => "הערך :attribute לא קיים.",
+	"image"          => "הערך :attribute חייב להיות תמונה.",
+	"in"             => "הערך :attribute חייב להיות ברשימה המאשרת.",
+	"integer"        => "הערך :attribute חייב להיות מספר שלם.",
+	"ip"             => "הערך :attribute חייב להיות כתובת IP תקינה.",
+	"match"          => "התבנית של הערך :attribute אינה תקינה.",
+	"max"            => array(
+		"numeric" => "הערך :attribute חייב להיות פחות מ-:max.",
+		"file"    => "הערך :attribute חייב לשקול פחות מ-:max ק&quotב.",
+		"string"  => "הערך :attribute חייב להכיל פחות מ-:max תווים.",
+	),
+	"mimes"          => "הערך :attribute חייב להיות קובץ מסוג: :values.",
+	"min"            => array(
+		"numeric" => "הערך :attribute חייב להיות לפחות :min.",
+		"file"    => "הערך :attribute חייב לשקול לפחות :min ק&quot;ב.",
+		"string"  => "הערך :attribute חייב להכיל לפחות :min תווים.",
+	),
+	"not_in"         => "הערך :attribute נמצא ברשימה השחורה.",
+	"numeric"        => "הערך :attribute חייב להיות מספר.",
+	"required"       => "חובה למלא את הערך :attribute.",
+	"same"           => "הערכים :attribute ו-:other חייבים להיות זהים.",
+	"size"           => array(
+		"numeric" => "הערך :attribute חייב להיות :size.",
+		"file"    => "הערך :attribute חייב לשקול :size ק&quot;ב.",
+		"string"  => "הערך :attribute חייב להכיל :size תווים.",
+	),
+	"unique"         => "הערך :attribute כבר קיים.",
+	"url"            => "הערך :attribute חייב להכיל כתובת אינטרנט תקינה.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/hu/pagination.php

@@ -0,0 +1,19 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Előző',
+	'next'     => 'Következő &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/hu/validation.php

@@ -0,0 +1,104 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "A(z) :attribute el kell legyen fogadva.",
+	"active_url"     => "A :attribute nem valós URL.",
+	"after"          => "A :attribute :date utáni dátum kell legyen.",
+	"alpha"          => "A(z) :attribute csak betűket tartalmazhat.",
+	"alpha_dash"     => "A(z) :attribute betűket, számokat és kötőjeleket tartalmazhat.",
+	"alpha_num"      => "A(z) :attribute csak betűket és számokat tartalmazhat.",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => "A :attribute :date előtti dátum kell legyen.",
+	"between"        => array(
+		"numeric" => "A(z) :attribute :min - :max közötti érték kell legyen.",
+		"file"    => "A(z) :attribute :min - :max kilobyte között kell legyen.",
+		"string"  => "A(z) :attribute :min - :max karakterhossz között kell legyen",
+	),
+	"confirmed"      => "A(z) :attribute megerősítése nem egyezett meg.",
+	"count"          => "The :attribute must have exactly :count selected elements.",
+	"countbetween"   => "The :attribute must have between :min and :max selected elements.",
+	"countmax"       => "The :attribute must have less than :max selected elements.",
+	"countmin"       => "The :attribute must have at least :min selected elements.",
+	"different"      => "A(z) :attribute és :other különböző kell legyen.",
+	"email"          => "A(z) :attribute formátuma nem megfelelő.",
+	"exists"         => "A(z) választott :attribute nem megfelelő.",
+	"image"          => "A(z) :attribute kép kell legyen.",
+	"in"             => "A(z) választott :attribute nem megfelelő.",
+	"integer"        => "A :attribute szám kell legyen.",
+	"ip"             => "A :attribute valós IP cím kell legyen.",
+	"match"          => "A(z) :attribute formátuma nem megfelelő.",
+	"max"            => array(
+		"numeric" => "A :attribute kevesebb kell legyen, mint :max.",
+		"file"    => "A :attribute kevesebb kell legyen :max kilobytenál.",
+		"string"  => "A :attribute kevesebb karakterből kell álljon, mint :max.",
+	),
+	"mimes"          => "A :attribute az alábbi tipusokból való kell legyen :values.",
+	"min"            => array(
+		"numeric" => "A :attribute legalább :min kell legyen.",
+		"file"    => "A :attribute legalább :min kilobyte kell legyen.",
+		"string"  => "A :attribute legalább :min karakter hosszú kell legyen.",
+	),
+	"not_in"         => "A választott :attribute nem megfelelő.",
+	"numeric"        => "A :attribute szám kell legyen.",
+	"required"       => "A(z) :attribute megadása kötelező.",
+	"same"           => "A :attribute és a :other muszáj hogy megegyezzen.",
+	"size"           => array(
+		"numeric" => "A(z) :attribute :size kell legyen.",
+		"file"    => "A(z) :attribute :size kilobyteos kell legyen.",
+		"string"  => "A(z) :attribute :size karakteres kell legyen.",
+	),
+	"unique"         => "A(z) :attribute már foglalt.",
+	"url"            => "A(z) :attribute formátuma nem megfelelő.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/id/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Sebelumnya',
+	'next'     => 'Berikutnya &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/id/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Isian :attribute harus diterima.",
+	"active_url"     => "Isian :attribute bukan URL yang valid.",
+	"after"          => "Isian :attribute harus tanggal setelah :date.",
+	"alpha"          => "Isian :attribute hanya boleh berisi huruf.",
+	"alpha_dash"     => "Isian :attribute hanya boleh berisi huruf, angka, dan strip.",
+	"alpha_num"      => "Isian :attribute hanya boleh berisi huruf dan angka.",
+	"array"          => "Isian :attribute harus memiliki elemen yang dipilih.",
+	"before"         => "Isian :attribute harus tanggal sebelum :date.",
+	"between"        => array(
+		"numeric" => "Isian :attribute harus antara :min - :max.",
+		"file"    => "Isian :attribute harus antara :min - :max kilobytes.",
+		"string"  => "Isian :attribute harus antara  :min - :max karakter.",
+	),
+	"confirmed"      => "Konfirmasi :attribute tidak cocok.",
+	"count"          => "Isian :attribute harus memiliki tepat :count elemen.",
+	"countbetween"   => "Isian :attribute harus diantara :min dan :max elemen.",
+	"countmax"       => "Isian :attribute harus lebih kurang dari :max elemen.",
+	"countmin"       => "Isian :attribute harus paling sedikit :min elemen.",
+	"different"      => "Isian :attribute dan :other harus berbeda.",
+	"email"          => "Format isian :attribute tidak valid.",
+	"exists"         => "Isian :attribute yang dipilih tidak valid.",
+	"image"          => ":attribute harus berupa gambar.",
+	"in"             => "Isian :attribute yang dipilih tidak valid.",
+	"integer"        => "Isian :attribute harus merupakan bilangan.",
+	"ip"             => "Isian :attribute harus alamat IP yang valid.",
+	"match"          => "Format isian :attribute tidak valid.",
+	"max"            => array(
+		"numeric" => "Isian :attribute harus kurang dari :max.",
+		"file"    => "Isian :attribute harus kurang dari :max kilobytes.",
+		"string"  => "Isian :attribute harus kurang dari :max karakter.",
+	),
+	"mimes"          => "Isian :attribute harus dokumen berjenis : :values.",
+	"min"            => array(
+		"numeric" => "Isian :attribute harus minimal :min.",
+		"file"    => "Isian :attribute harus minimal :min kilobytes.",
+		"string"  => "Isian :attribute harus minimal :min karakter.",
+	),
+	"not_in"         => "Isian :attribute yang dipilih tidak valid.",
+	"numeric"        => "Isian :attribute harus berupa angka.",
+	"required"       => "Isian :attribute wajib diisi.",
+	"same"           => "Isian :attribute dan :other harus sama.",
+	"size"           => array(
+		"numeric" => "Isian :attribute harus berukuran :size.",
+		"file"    => "Isian :attribute harus berukuran :size kilobyte.",
+		"string"  => "Isian :attribute harus berukuran :size karakter.",
+	),
+	"unique"         => "Isian :attribute sudah ada sebelumnya.",
+	"url"            => "Format isian :attribute tidak valid.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/it/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Precedente',
+	'next'     => 'Successivo &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/it/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute deve essere accettato.",
+	"active_url"     => ":attribute non &egrave; un URL valido.",
+	"after"          => ":attribute deve essere una data successiva al :date.",
+	"alpha"          => ":attribute pu&ograve; contenere solo lettere.",
+	"alpha_dash"     => ":attribute pu&ograve; contenere solo numeri lettere e dashes.",
+	"alpha_num"      => ":attribute pu&ograve; contenere solo lettere e numeri.",
+	"array"          => ":attribute deve avere almeno un elemento selezionato.",
+	"before"         => ":attribute deve essere una data che precede :date.",
+	"between"        => array(
+		"numeric" => ":attribute deve trovarsi tra :min - :max.",
+		"file"    => ":attribute deve trovarsi tra :min - :max kilobytes.",
+		"string"  => ":attribute deve trovarsi tra :min - :max caratteri.",
+	),
+	"confirmed"      => "Il campo di conferma per :attribute non coincide.",
+	"count"          => ":attribute deve avere esattamente :count elementi selezionati.",
+	"countbetween"   => ":attribute deve avere esattamente almeno :min o al pi&ugrave; :max elementi selezionati.",
+	"countmax"       => ":attribute deve avere meno di :max elementi selezionati.",
+	"countmin"       => ":attribute deve avere almeno :min elementi selezionati.",
+	"different"      => ":attribute e :other devono essere differenti.",
+	"email"          => ":attribute non &egrave; valido.",
+	"exists"         => ":attribute selezionato/a non &egrave; valido.",
+	"image"          => ":attribute deve essere un'immagine.",
+	"in"             => ":attribute selezionato non &egrave; valido.",
+	"integer"        => ":attribute deve essere intero.",
+	"ip"             => ":attribute deve essere un indirizzo IP valido.",
+	"match"          => ":attribute non &egrave; valido.",
+	"max"            => array(
+		"numeric" => ":attribute deve essere minore di :max.",
+		"file"    => ":attribute non deve essere pi&ugrave grande di :max kilobytes.",
+		"string"  => ":attribute non pu&ograve; contenere pi&ugrave; di :max caratteri.",
+	),
+	"mimes"          => ":attribute deve essere del tipo: :values.",
+	"min"            => array(
+		"numeric" => ":attribute deve valere almeno :min.",
+		"file"    => ":attribute deve essere pi&ugrave; grande di :min kilobytes.",
+		"string"  => ":attribute deve contenere almeno :min caratteri.",
+	),
+	"not_in"         => "Il valore selezionato per :attribute non &egrave; valido.",
+	"numeric"        => ":attribute deve essere un numero.",
+	"required"       => ":attribute non pu&ograve; essere omesso.",
+	"same"           => ":attribute e :other devono coincidere.",
+	"size"           => array(
+		"numeric" => ":attribute deve valere :size.",
+		"file"    => ":attribute deve essere grande :size kilobyte.",
+		"string"  => ":attribute deve contenere :size caratteri.",
+	),
+	"unique"         => ":attribute &egrave; stato gi&agrave; usato.",
+	"url"            => ":attribute deve essere un URL.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 31 - 0
php-laravel/application/language/ja/pagination.php

@@ -0,0 +1,31 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	/*
+	|--------------------------------------------------------------------------
+	| ペギネーション言語ライン
+	|--------------------------------------------------------------------------
+	|
+	| 以下の言語設定行はpaginatorライブラリーにより、ペギネーションリンクを作成するため
+	| 使用されます。お好きなように変更してください。
+	| もっとエキサイトするアイデアが思い浮かんだら、私達に教えて下さい。
+	|
+	*/
+
+
+	'previous' => '&laquo; 前',
+	'next'     => '次 &raquo;',
+
+);

+ 147 - 0
php-laravel/application/language/ja/validation.php

@@ -0,0 +1,147 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	/*
+	|--------------------------------------------------------------------------
+	| バリデーション言語設定
+	|--------------------------------------------------------------------------
+	|
+	| 以下の言語設定はvalidatorクラスで使用しているデフォルトのエラーメッセージを構成しています。
+	| 幾つかのルールは複数の設定を持っています。例えばサイズ(max,min,between)ルールです。
+	| (訳注:(numeric, file, string)の間違いと思われる。
+	| これらの設定は、文字列やファイルのように入力のタイプの違いにより、使い分けられます。
+	|
+	| これらの言語設定はあなたのアプリケーションでカスタムエラーメッセージとして表示するため
+	| 気軽に変更してください。カスタムバリデーションルールのためのエラーメッセージも、
+	| 同様にこのファイルに追加していただけます。
+	|
+	*/
+
+	"accepted"       => ":attributeを承認してください。",
+	"active_url"     => ":attributeが有効なURLではありません。",
+	"after"          => ":attributeには、:date以降の日付を指定してください。",
+	"alpha"          => ":attributeはアルファベッドのみがご利用できます。",
+	"alpha_dash"     => ":attributeは英数字とダッシュ(-)及び下線(_)がご利用できます。",
+	"alpha_num"      => ":attributeは英数字がご利用できます。",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => ":attributeには、:date以前の日付をご利用ください。",
+	"between"        => array(
+		"numeric" => ":attributeは、:minから、:maxまでの数字をご指定ください。",
+		"file"    => ":attributeには、:min kBから:max kBまでのサイズのファイルをご指定ください。",
+		"string"  => ":attributeは、:min文字から:max文字の間でご指定ください。",
+	),
+	"confirmed"      => ":attributeと、確認フィールドとが、一致していません。",
+	"count"          => ":attributeは、:count個選択してください。",
+	"countbetween"   => ":attributeは、:min個から:max個の間で選択してください。",
+	"countmax"       => ":attributeは、:max個以下で選択してください。",
+	"countmin"       => ":attributeは、最低:min個選択してください。",
+	"different"      => ":attributeと:otherには、異なった内容を指定してください。",
+	"email"          => ":attributeには正しいメールアドレスの形式をご指定ください。",
+	"exists"         => "選択された:attributeは正しくありません。",
+	"image"          => ":attributeには画像ファイルを指定してください。",
+	"in"             => "選択された:attributeは正しくありません。",
+	"integer"        => ":attributeは整数でご指定ください。",
+	"ip"             => ":attributeには、有効なIPアドレスをご指定ください。",
+	"match"          => ":attributeの入力フォーマットが間違っています。",
+	"max"            => array(
+		"numeric" => ":attributeには、:max以下の数字をご指定ください。",
+		"file"    => ":attributeには、:max kB以下のファイルをご指定ください。",
+		"string"  => ":attributeは、:max文字以下でご指定ください。",
+	),
+	"mimes"          => ":attributeには:valuesタイプのファイルを指定してください。",
+	"min"            => array(
+		"numeric" => ":attributeには、:min以上の数字をご指定ください。",
+		"file"    => ":attributeには、:min kB以上のファイルをご指定ください。",
+		"string"  => ":attributeは、:min文字以上でご指定ください。",
+	),
+	"not_in"         => "選択された:attributeは正しくありません。",
+	"numeric"        => ":attributeには、数字を指定してください。",
+	"required"       => ":attributeは必ず指定してください。",
+	"same"           => ":attributeと:otherには同じ値を指定してください。",
+	"size"           => array(
+		"numeric" => ":attributeには:sizeを指定してください。",
+		"file"    => ":attributeのファイルは、:sizeキロバイトでなくてはなりません。",
+		"string"  => ":attributeは:size文字で指定してください。",
+	),
+	"unique"         => ":attributeに指定された値は既に存在しています。",
+	"url"            => ":attributeのフォーマットが正しくありません。",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	/*
+	|--------------------------------------------------------------------------
+	| カスタムバリデーション言語設定
+	|--------------------------------------------------------------------------
+	|
+	| ここでは、"属性_ルール"の記法を使用し、属性に対するカスタムバリデーションメッセージを
+	| 指定してください。これにより、カスタムバリデーションをきれいに美しく保てます。
+	|
+	| 例えば、"email"属性のuniqueバリデーションで、カスタムバリデーションメッセージを
+	| 使いたいならば、"email_unique"をカスタムメッセージとともに、配列に追加してください。
+	| Validatorクラスが残りの面倒を見ます!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	/*
+	|--------------------------------------------------------------------------
+	| バリデーション属性
+	|--------------------------------------------------------------------------
+	|
+	| 以下の言語設定は属性のプレースホルダーを例えば"email"属性を"E-Mailアドレス"という風に
+	| 読み手に親切になるよう置き換えるために使用されます。
+	| あなたのユーザーは、あなたに感謝するでしょう。
+	|
+	| Validatorクラスは、自動的にメッセージに含まれる:attributeプレースホルダーを
+	| この配列の値に置き換えようと試みます。絶妙ですね。あなたも気に入ってくれるでしょう。
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/nl/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Vorige',
+	'next'     => 'Volgende &raquo;',
+
+);

+ 95 - 0
php-laravel/application/language/nl/validation.php

@@ -0,0 +1,95 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Dutch validation language file
+	|--------------------------------------------------------------------------
+	|
+	*/
+
+	"accepted"       => ":attribute moet geaccepteerd zijn.",
+	"active_url"     => ":attribute is geen geldige URL.",
+	"after"          => ":attribute moet een datum na :date zijn.",
+	"alpha"          => ":attribute mag alleen letters bevatten.",
+	"alpha_dash"     => ":attribute mag alleen letters, nummers, onderstreep(_) en strepen(-) bevatten.",
+	"alpha_num"      => ":attribute mag alleen letters en nummers bevatten.",
+	"array"          => ":attribute moet geselecteerde elementen bevatten.",
+	"before"         => ":attribute moet een datum voor :date zijn.",
+	"between"        => array(
+		"numeric" => ":attribute moet tussen :min en :max zijn.",
+		"file"    => ":attribute moet tussen :min en :max kilobytes zijn.",
+		"string"  => ":attribute moet tussen :min en :max karakters zijn.",
+	),
+	"confirmed"      => ":attribute bevestiging komt niet overeen.",
+	"count"          => ":attribute moet precies :count geselecteerde elementen bevatten.",
+	"countbetween"   => ":attribute moet tussen :min en :max geselecteerde elementen bevatten.",
+	"countmax"       => ":attribute moet minder dan :max geselecteerde elementen bevatten.",
+	"countmin"       => ":attribute moet minimaal :min geselecteerde elementen bevatten.",
+	"different"      => ":attribute en :other moeten verschillend zijn.",
+	"email"          => ":attribute is geen geldig e-mailadres.",
+	"exists"         => ":attribute bestaat niet.",
+	"image"          => ":attribute moet een afbeelding zijn.",
+	"in"             => ":attribute is ongeldig.",
+	"integer"        => ":attribute moet een getal zijn.",
+	"ip"             => ":attribute moet een geldig IP-adres zijn.",
+	"match"          => "Het formaat van :attribute is ongeldig.",
+	"max"            => array(
+		"numeric" => ":attribute moet minder dan :max zijn.",
+		"file"    => ":attribute moet minder dan :max kilobytes zijn.",
+		"string"  => ":attribute moet minder dan :max karakters zijn.",
+	),
+	"mimes"          => ":attribute moet een bestand zijn van het bestandstype :values.",
+	"min"            => array(
+		"numeric" => ":attribute moet minimaal :min zijn.",
+		"file"    => ":attribute moet minimaal :min kilobytes zijn.",
+		"string"  => ":attribute moet minimaal :min karakters zijn.",
+	),
+	"not_in"         => "Het formaat van :attribute is ongeldig.",
+	"numeric"        => ":attribute moet een nummer zijn.",
+	"required"       => ":attribute is verplicht.",
+	"same"           => ":attribute en :other moeten overeenkomen.",
+	"size"           => array(
+		"numeric" => ":attribute moet :size zijn.",
+		"file"    => ":attribute moet :size kilobyte zijn.",
+		"string"  => ":attribute moet :size characters zijn.",
+	),
+	"unique"         => ":attribute is al in gebruik.",
+	"url"            => ":attribute is geen geldige URL.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/pl/pagination.php

@@ -0,0 +1,19 @@
+<?php
+
+return array(
+
+    /*
+    |--------------------------------------------------------------------------
+    | Pagination Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used by the paginator library to build
+    | the pagination links. You're free to change them to anything you want.
+    | If you come up with something more exciting, let us know.
+    |
+    */
+
+    'previous' => '&laquo; Poprzednia',
+    'next'     => 'Następna &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/pl/validation.php

@@ -0,0 +1,104 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute musi zostać zaakceptowane.",
+	"active_url"     => ":attribute nie jest prawidłowym adresem URL.",
+	"after"          => ":attribute musi zawierać datę, która jest po :date.",
+	"alpha"          => ":attribute może zawierać jedynie litery.",
+	"alpha_dash"     => ":attribute może zawierać jedynie litery, cyfry i myślniki.",
+	"alpha_num"      => ":attribute może zawierać jedynie litery i cyfry.",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => ":attribute musi zawierać datę, która jest przed :date.",
+	"between"        => array(
+		"numeric" => ":attribute musi mieścić się w granicach :min - :max.",
+		"file"    => ":attribute musi mieć :min - :max kilobajtów.",
+		"string"  => ":attribute musi mieć :min - :max znaków.",
+	),
+	"confirmed"      => "Potwierdzenie :attribute się nie zgadza.",
+	"count"          => "The :attribute must have exactly :count selected elements.",
+	"countbetween"   => "The :attribute must have between :min and :max selected elements.",
+	"countmax"       => "The :attribute must have less than :max selected elements.",
+	"countmin"       => "The :attribute must have at least :min selected elements.",
+	"different"      => ":attribute i :other muszą się od siebie różnić.",
+	"email"          => "The :attribute format is invalid.",
+	"exists"         => "Zaznaczona opcja :attribute jest nieprawidłowa.",
+	"image"          => ":attribute musi być obrazkiem.",
+	"in"             => "Zaznaczona opcja :attribute jest nieprawidłowa.",
+	"integer"        => ":attribute musi być liczbą całkowitą.",
+	"ip"             => ":attribute musi być prawidłowym adresem IP.",
+	"match"          => "Format :attribute jest nieprawidłowy.",
+	"max"            => array(
+		"numeric" => ":attribute musi być poniżej :max.",
+		"file"    => ":attribute musi mieć poniżej :max kilobajtów.",
+		"string"  => ":attribute musi mieć poniżej :max znaków.",
+	),
+	"mimes"          => ":attribute musi być plikiem rodzaju :values.",
+	"min"            => array(
+		"numeric" => ":attribute musi być co najmniej :min.",
+		"file"    => "Plik :attribute musi mieć co najmniej :min kilobajtów.",
+		"string"  => ":attribute musi mieć co najmniej :min znaków.",
+	),
+	"not_in"         => "Zaznaczona opcja :attribute jest nieprawidłowa.",
+	"numeric"        => ":attribute musi być numeryczne.",
+	"required"       => "Pole :attribute jest wymagane.",
+	"same"           => ":attribute i :other muszą być takie same.",
+	"size"           => array(
+		"numeric" => ":attribute musi mieć rozmiary :size.",
+		"file"    => ":attribute musi mieć :size kilobajtów.",
+		"string"  => ":attribute musi mieć :size znaków.",
+	),
+	"unique"         => ":attribute zostało już użyte.",
+	"url"            => "Format pola :attribute jest nieprawidłowy.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/pt/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Anterior',
+	'next'     => 'Próxima &raquo;',
+
+);

+ 99 - 0
php-laravel/application/language/pt/validation.php

@@ -0,0 +1,99 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "O :attribute deve ser aceite.",
+	"active_url"     => "O :attribute não é uma URL válida.",
+	"after"          => "O :attribute deve ser uma data após :date.",
+	"alpha"          => "O :attribute só pode conter letras.",
+	"alpha_dash"     => "O :attribute só pode conter letras, números e traços.",
+	"alpha_num"      => "O :attribute só pode conter letras e números.",
+	"before"         => "O :attribute deve ser uma data anterior à :date.",
+	"between"        => array(
+		"numeric" => "O :attribute deve estar entre :min - :max.",
+		"file"    => "O :attribute deve estar entre :min - :max kilobytes.",
+		"string"  => "O :attribute deve estar entre :min - :max caracteres.",
+	),
+	"confirmed"      => "O :attribute confirmação não coincide.",
+	"different"      => "O :attribute e :other devem ser diferentes.",
+	"email"          => "O :attribute não é um e-mail válido.",
+	"exists"         => "O :attribute selecionado é inválido.",
+	"image"          => "O :attribute deve ser uma imagem.",
+	"in"             => "O :attribute selecionado é inválido.",
+	"integer"        => "O :attribute deve ser um inteiro.",
+	"ip"             => "O :attribute deve ser um endereço IP válido.",
+	"match"          => "O formato :attribute é inválido.",
+	"max"            => array(
+		"numeric" => "O :attribute deve ser inferior a :max.",
+		"file"    => "O :attribute deve ser inferior a :max kilobytes.",
+		"string"  => "O :attribute deve ser inferior a :max caracteres.",
+	),
+	"mimes"          => "O :attribute deve ser um arquivo do tipo: :values.",
+	"min"            => array(
+		"numeric" => "O :attribute deve conter pelo menos :min.",
+		"file"    => "O :attribute deve conter pelo menos :min kilobytes.",
+		"string"  => "O :attribute deve conter pelo menos :min caracteres.",
+	),
+	"not_in"         => "O :attribute selecionado é inválido.",
+	"numeric"        => "O :attribute deve ser um número.",
+	"required"       => "O campo :attribute deve ser preenchido.",
+	"same"           => "O :attribute e :other devem ser iguais.",
+	"size"           => array(
+		"numeric" => "O :attribute deve ser :size.",
+		"file"    => "O :attribute deve ter :size kilobyte.",
+		"string"  => "O :attribute deve ter :size caracteres.",
+	),
+	"unique"         => "Este :attribute já existe.",
+	"url"            => "O formato :attribute é inválido.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/ro/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Inapoi',
+	'next'     => 'Inainte &raquo;',
+
+);

+ 106 - 0
php-laravel/application/language/ro/validation.php

@@ -0,0 +1,106 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Campul :attribute trebuie sa fie acceptat.",
+	"active_url"     => "Campul :attribute nu este un URL valid.",
+	"after"          => "Campul :attribute trebuie sa fie o data dupa :date.",
+	"alpha"          => "Campul :attribute poate contine numai litere.",
+	"alpha_dash"     => "Campul :attribute poate contine numai litere, numere si liniute.",
+	"alpha_num"      => "Campul :attribute poate contine numai litere si numere.",
+	"array"          => "Campul :attribute trebuie sa aiba elemente selectate.",
+	"before"         => "Campul :attribute trebuie sa fie o data inainte de :date.",
+	"between"        => array(
+		"numeric" => "Campul :attribute trebuie sa fie intre :min si :max.",
+		"file"    => "Campul :attribute trebuie sa fie intre :min si :max kilobytes.",
+		"string"  => "Campul :attribute trebuie sa fie intre :min si :max caractere.",
+	),
+	"confirmed"      => "Confirmarea :attribute nu se potriveste.",
+	"count"          => "Campul :attribute trebuie sa aiba exact :count elemente selectate.",
+	"countbetween"   => "Campul :attribute trebuie sa aiba intre :min si :max elemente selectate.",
+	"countmax"       => "Campul :attribute trebuie sa aiba mai putin de :max elemente selectate.",
+	"countmin"       => "Campul :attribute trebuie sa aiba cel putin :min elemente selectate.",
+	"date_format"	 => "Campul :attribute trebuie sa fie intr-un format valid.",
+	"different"      => "Campurile :attribute si :other trebuie sa fie diferite.",
+	"email"          => "Formatul campului :attribute este invalid.",
+	"exists"         => "Campul :attribute selectat este invalid.",
+	"image"          => "Campul :attribute trebuie sa fie o imagine.",
+	"in"             => "Campul :attribute selectat este invalid.",
+	"integer"        => "Campul :attribute trebuie sa fie un numar intreg.",
+	"ip"             => "Campul :attribute trebuie sa fie o adresa IP valida.",
+	"match"          => "Formatul campului :attribute este invalid.",
+	"max"            => array(
+		"numeric" => "Campul :attribute trebuie sa fie mai mic de :max.",
+		"file"    => "Campul :attribute trebuie sa fie mai mic de :max kilobytes.",
+		"string"  => "Campul :attribute trebuie sa fie mai mic de :max caractere.",
+	),
+	"mimes"          => "Campul :attribute trebuie sa fie un fisier de tipul: :values.",
+	"min"            => array(
+		"numeric" => "Campul :attribute trebuie sa fie cel putin :min.",
+		"file"    => "Campul :attribute trebuie sa aiba cel putin :min kilobytes.",
+		"string"  => "Campul :attribute trebuie sa aiba cel putin :min caractere.",
+	),
+	"not_in"         => "Campul :attribute selectat este invalid.",
+	"numeric"        => "Campul :attribute trebuie sa fie un numar.",
+	"required"       => "Campul :attribute este obligatoriu.",
+    "required_with"  => "Campul :attribute este obligatoriu cu :field",
+	"same"           => "Campul :attribute si :other trebuie sa fie identice.",
+	"size"           => array(
+		"numeric" => "Campul :attribute trebuie sa fie :size.",
+		"file"    => "Campul :attribute trebuie sa aiba :size kilobyte.",
+		"string"  => "Campul :attribute trebuie sa aiba :size caractere.",
+	),
+	"unique"         => "Campul :attribute a fost deja folosit.",
+	"url"            => "Campul :attribute nu este intr-un format valid.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/ru/pagination.php

@@ -0,0 +1,19 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '← Назад',
+	'next'     => 'Вперёд →',
+
+);

+ 104 - 0
php-laravel/application/language/ru/validation.php

@@ -0,0 +1,104 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Вы должны принять :attribute.",
+	"active_url"     => "Поле :attribute должно быть полным URL.",
+	"after"          => "Поле :attribute должно быть датой после :date.",
+	"alpha"          => "Поле :attribute может содержать только буквы.",
+	"alpha_dash"     => "Поле :attribute может содержать только буквы, цифры и тире.",
+	"alpha_num"      => "Поле :attribute может содержать только буквы и цифры.",
+	"array"          => "The :attribute must have selected elements.",
+	"before"         => "Поле :attribute должно быть датой перед :date.",
+	"between"        => array(
+		"numeric" => "Поле :attribute должно быть между :min и :max.",
+		"file"    => "Поле :attribute должно быть от :min до :max Килобайт.",
+		"string"  => "Поле :attribute должно быть от :min до :max символов.",
+	),
+	"confirmed"      => "Поле :attribute не совпадает с подтверждением.",
+	"count"          => "The :attribute must have exactly :count selected elements.",
+	"countbetween"   => "The :attribute must have between :min and :max selected elements.",
+	"countmax"       => "The :attribute must have less than :max selected elements.",
+	"countmin"       => "The :attribute must have at least :min selected elements.",
+	"different"      => "Поля :attribute и :other должны различаться.",
+	"email"          => "Поле :attribute имеет неверный формат.",
+	"exists"         => "Выбранное значение для :attribute уже существует.",
+	"image"          => "Поле :attribute должно быть картинкой.",
+	"in"             => "Выбранное значение для :attribute не верно.",
+	"integer"        => "Поле :attribute должно быть целым числом.",
+	"ip"             => "Поле :attribute должно быть полным IP-адресом.",
+	"match"          => "Поле :attribute имеет неверный формат.",
+	"max"            => array(
+		"numeric" => "Поле :attribute должно быть меньше :max.",
+		"file"    => "Поле :attribute должно быть меньше :max Килобайт.",
+		"string"  => "Поле :attribute должно быть короче :max символов.",
+	),
+	"mimes"          => "Поле :attribute должно быть файлом одного из типов: :values.",
+	"min"            => array(
+		"numeric" => "Поле :attribute должно быть не менее :min.",
+		"file"    => "Поле :attribute должно быть не менее :min Килобайт.",
+		"string"  => "Поле :attribute должно быть не короче :min символов.",
+	),
+	"not_in"         => "Выбранное значение для :attribute не верно.",
+	"numeric"        => "Поле :attribute должно быть числом.",
+	"required"       => "Поле :attribute обязательно для заполнения.",
+	"same"           => "Значение :attribute должно совпадать с :other.",
+	"size"           => array(
+		"numeric" => "Поле :attribute должно быть :size.",
+		"file"    => "Поле :attribute должно быть :size Килобайт.",
+		"string"  => "Поле :attribute должно быть длиной :size символов.",
+	),
+	"unique"         => "Такое значение поля :attribute уже существует.",
+	"url"            => "Поле :attribute имеет неверный формат.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/sq/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Prapa',
+	'next'     => 'Para &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/sq/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute duhet të pranohet.",
+	"active_url"     => ":attribute nuk është URL valide.",
+	"after"          => ":attribute duhet të jetë datë pas :date.",
+	"alpha"          => ":attribute mund të përmbajë vetëm shkronja.",
+	"alpha_dash"     => ":attribute mund të përmbajë vetëm shkronja, numra dhe viza.",
+	"alpha_num"      => ":attribute mund të përmbajë vetëm shkronja dhe numra.",
+	"array"          => ":attribute duhet të ketë elemente të përzgjedhura.",
+	"before"         => ":attribute duhet të jetë datë para :date.",
+	"between"        => array(
+		"numeric" => ":attribute duhet të jetë në mes :min - :max.",
+		"file"    => ":attribute duhet të jetë në mes :min - :max kilobajtëve.",
+		"string"  => ":attribute duhet të jetë në mes :min - :max karaktereve.",
+	),
+	"confirmed"      => ":attribute konfirmimi nuk përputhet.",
+	"count"          => ":attributeduhet të ketë saktësisht :count elemente te përzgjedhura.",
+	"countbetween"   => ":attribute duhet të jetë në mes :min and :max elemente te përzgjedhura.",
+	"countmax"       => ":attribute duhet të ketë me pak se :max elemente te përzgjedhura.",
+	"countmin"       => ":attribute duhet të ketë së paku :min elemente te përzgjedhura.",
+	"different"      => ":attribute dhe :other duhet të jenë të ndryshme.",
+	"email"          => ":attribute formati është jo valid.",
+	"exists"         => ":attribute e përzgjedhur është jo valid.",
+	"image"          => ":attribute duhet të jetë imazh.",
+	"in"             => ":attribute e përzgjedhur është jo valid.",
+	"integer"        => ":attribute duhet të jete numër i plotë.",
+	"ip"             => ":attribute duhet të jetë një IP adresë e vlefshme.",
+	"match"          => ":attribute formati është i pavlefshëm.",
+	"max"            => array(
+		"numeric" => ":attribute duhet të jetë më e vogël se :max.",
+		"file"    => ":attribute duhet të jetë më e vogël se :max kilobytes.",
+		"string"  => ":attribute duhet të jetë më e vogël se :max characters.",
+	),
+	"mimes"          => ":attribute duhet të jetë një fajll i tipit: :values.",
+	"min"            => array(
+		"numeric" => ":attribute duhet të jetë së paku :min.",
+		"file"    => ":attribute duhet të jetë së paku :min kilobajt.",
+		"string"  => ":attribute duhet të jetë së paku :min karaktere.",
+	),
+	"not_in"         => ":attribute e përzgjedhur është jo valid.",
+	"numeric"        => ":attribute duhet të jetë numër.",
+	"required"       => ":attribute fusha është e nevojshme.",
+	"same"           => ":attribute dhe :other duhet të përputhen.",
+	"size"           => array(
+		"numeric" => ":attribute duhet të jetë :size.",
+		"file"    => ":attribute duhet të jetë :size kilobajt.",
+		"string"  => ":attribute duhet të jetë :size karaktere.",
+	),
+	"unique"         => ":attribute tashmë është marrë.",
+	"url"            => ":attribute formati është i pavlefshëm.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/sr/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Nazad',
+	'next'     => 'Napred &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/sr/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => "Polje :attribute mora biti prihvaćeno.",
+	"active_url"     => "Polje :attribute nije validan URL.",
+	"after"          => "Polje :attribute mora biti datum posle :date.",
+	"alpha"          => "Polje :attribute može sadržati samo slova.",
+	"alpha_dash"     => "Polje :attribute može sadržati samo slova, brojeve i povlake.",
+	"alpha_num"      => "Polje :attribute može sadržati samo slova i brojeve.",
+	"array"          => "Polje :attribute mora imati odabrane elemente.",
+	"before"         => "Polje :attribute mora biti datum pre :date.",
+	"between"        => array(
+		"numeric" => "Polje :attribute mora biti izmedju :min - :max.",
+		"file"    => "Fajl :attribute mora biti izmedju :min - :max kilobajta.",
+		"string"  => "Polje :attribute mora biti izmedju :min - :max karaktera.",
+	),
+	"confirmed"      => "Potvrda polja :attribute se ne poklapa.",
+	"count"          => "Polje :attribute mora imati tačno :count odabranih elemenata.",
+	"countbetween"   => "Polje :attribute mora imati izmedju :min i :max odabranih elemenata.",
+	"countmax"       => "Polje :attribute mora imati manje od :max odabranih elemenata.",
+	"countmin"       => "Polje :attribute mora imati najmanje :min odabranih elemenata.",
+	"different"      => "Polja :attribute i :other moraju biti različita.",
+	"email"          => "Format polja :attribute nije validan.",
+	"exists"         => "Odabrano polje :attribute nije validno.",
+	"image"          => "Polje :attribute mora biti slika.",
+	"in"             => "Odabrano polje :attribute nije validno.",
+	"integer"        => "Polje :attribute mora biti broj.",
+	"ip"             => "Polje :attribute mora biti validna IP adresa.",
+	"match"          => "Format polja :attribute nije validan.",
+	"max"            => array(
+		"numeric" => "Polje :attribute mora biti manje od :max.",
+		"file"    => "Polje :attribute mora biti manje od :max kilobajta.",
+		"string"  => "Polje :attribute mora sadržati manje od :max karaktera.",
+	),
+	"mimes"          => "Polje :attribute mora biti fajl tipa: :values.",
+	"min"            => array(
+		"numeric" => "Polje :attribute mora biti najmanje :min.",
+		"file"    => "Fajl :attribute mora biti najmanje :min kilobajta.",
+		"string"  => "Polje :attribute mora sadržati najmanje :min karaktera.",
+	),
+	"not_in"         => "Odabrani element polja :attribute nije validan.",
+	"numeric"        => "Polje :attribute mora biti broj.",
+	"required"       => "Polje :attribute je obavezno.",
+	"same"           => "Polja :attribute i :other se moraju poklapati.",
+	"size"           => array(
+		"numeric" => "Polje :attribute mora biti :size.",
+		"file"    => "Fajl :attribute mora biti :size kilobajta.",
+		"string"  => "Polje :attribute mora biti :size karaktera.",
+	),
+	"unique"         => "Polje :attribute već postoji.",
+	"url"            => "Format polja :attribute nije validan.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 19 - 0
php-laravel/application/language/sv/pagination.php

@@ -0,0 +1,19 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Föregående',
+	'next'     => 'Nästa &raquo;',
+
+);

+ 104 - 0
php-laravel/application/language/sv/validation.php

@@ -0,0 +1,104 @@
+<?php 
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute m&aring;ste accepteras.",
+	"active_url"     => ":attribute &auml;r inte en giltig webbadress.",
+	"after"          => ":attribute m&aring;ste vara ett datum efter den :date.",
+	"alpha"          => ":attribute f&aring;r endast inneh&aring;lla bokst&auml;ver.",
+	"alpha_dash"     => ":attribute f&aring;r endast inneh&aring;lla bokst&auml;ver, nummer och bindestreck.",
+	"alpha_num"      => ":attribute f&aring;r endast inneh&aring;lla bokst&auml;ver och nummer.",
+	"array"          => ":attribute m&aring;ste ha valda element.",
+	"before"         => ":attribute m&aring;ste vara ett datum innan den :date.",
+	"between"        => array(
+		"numeric" => ":attribute m&aring;ste vara ett nummer mellan :min och :max.",
+		"file"    => ":attribute m&aring;ste vara mellan :min till :max kilobytes stor.",
+		"string"  => ":attribute m&aring;ste inneh&aring;lla :min till :max tecken.",
+	),
+	"confirmed"      => ":attribute bekr&auml;ftelsen matchar inte.",
+	"count"          => ":attribute m&aring;ste exakt ha :count valda element.",
+	"countbetween"   => ":attribute f&aring;r endast ha :min till :max valda element.",
+	"countmax"       => ":attribute f&aring;r max ha :max valda element.",
+	"countmin"       => ":attribute m&aring;ste minst ha :min valda element.",
+	"different"      => ":attribute och :other f&aring;r ej vara lika.",
+	"email"          => ":attribute formatet &auml;r ogiltig.",
+	"exists"         => "Det valda :attribute &auml;r ogiltigt.",
+	"image"          => ":attribute m&aring;ste vara en bild.",
+	"in"             => "Det valda :attribute &auml;r ogiltigt.",
+	"integer"        => ":attribute m&aring;ste vara en siffra.",
+	"ip"             => ":attribute m&aring;ste vara en giltig IP-adress.",
+	"match"          => ":attribute formatet &auml;r ogiltig.",
+	"max"            => array(
+		"numeric" => ":attribute f&aring;r inte vara st&ouml;rre &auml;n :max.",
+		"file"    => ":attribute f&aring;r max vara :max kilobytes stor.",
+		"string"  => ":attribute f&aring;r max inneh&aring;lla :max tecken.",
+	),
+	"mimes"          => ":attribute m&aring;ste vara en fil av typen: :values.",
+	"min"            => array(
+		"numeric" => ":attribute m&aring;ste vara st&ouml;rre &auml;n :min.",
+		"file"    => ":attribute m&aring;ste minst vara :min kilobytes stor.",
+		"string"  => ":attribute m&aring;ste minst inneh&aring;lla :min tecken.",
+	),
+	"not_in"         => "Det valda :attribute &auml;r ogiltigt.",
+	"numeric"        => ":attribute m&aring;ste vara ett nummer.",
+	"required"       => ":attribute f&auml;ltet &auml;r obligatoriskt.",
+	"same"           => ":attribute och :other m&aring;ste vara likadana.",
+	"size"           => array(
+		"numeric" => ":attribute m&aring;ste vara :size.",
+		"file"    => ":attribute f&aring;r endast vara :size kilobyte stor.",
+		"string"  => ":attribute m&aring;ste inneh&aring;lla :size tecken.",
+	),
+	"unique"         => ":attribute anv&auml;nds redan.",
+	"url"            => ":attribute formatet &auml;r ogiltig",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 28 - 0
php-laravel/application/language/tr/pagination.php

@@ -0,0 +1,28 @@
+<?php 
+
+/**
+ * Laravel - A PHP Framework For Web Artisans
+ *
+ * @package  Language
+ * @version  3.2.3
+ * @author   Sinan Eldem <[email protected]>
+ * @link     http://sinaneldem.com.tr
+ */
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Pagination Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used by the paginator library to build
+	| the pagination links. You're free to change them to anything you want.
+	| If you come up with something more exciting, let us know.
+	|
+	*/
+
+	'previous' => '&laquo; Önceki',
+	'next'     => 'Sonraki &raquo;',
+
+);

+ 108 - 0
php-laravel/application/language/tr/validation.php

@@ -0,0 +1,108 @@
+<?php 
+
+/**
+ * Laravel - A PHP Framework For Web Artisans
+ *
+ * @package  Language
+ * @version  3.2.3
+ * @author   Sinan Eldem <[email protected]>
+ * @link     http://sinaneldem.com.tr
+ */
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines contain the default error messages used
+	| by the validator class. Some of the rules contain multiple versions,
+	| such as the size (max, min, between) rules. These versions are used
+	| for different input types such as strings and files.
+	|
+	| These language lines may be easily changed to provide custom error
+	| messages in your application. Error messages for custom validation
+	| rules may also be added to this file.
+	|
+	*/
+
+	"accepted"       => ":attribute kabul edilmelidir.",
+	"active_url"     => ":attribute geçerli bir URL olmalıdır.",
+	"after"          => ":attribute şundan daha eski bir tarih olmalıdır :date.",
+	"alpha"          => ":attribute sadece harflerden oluşmalıdır.",
+	"alpha_dash"     => ":attribute sadece harfler, rakamlar ve tirelerden oluşmalıdır.",
+	"alpha_num"      => ":attribute sadece harfler ve rakamlar içermelidir.",
+	"before"         => ":attribute şundan daha önceki bir tarih olmalıdır :date.",
+	"between"        => array(
+		"numeric" => ":attribute :min - :max arasında olmalıdır.",
+		"file"    => ":attribute :min - :max arasındaki kilobyte değeri olmalıdır.",
+		"string"  => ":attribute :min - :max arasında karakterden oluşmalıdır.",
+	),
+	"confirmed"      => ":attribute onayı eşleşmiyor.",
+	"different"      => ":attribute ile :other birbirinden farklı olmalıdır.",
+	"email"          => ":attribute biçimi geçersiz.",
+	"exists"         => "Seçili :attribute geçersiz.",
+	"image"          => ":attribute resim dosyası olmalıdır.",
+	"in"             => "selected :attribute geçersiz.",
+	"integer"        => ":attribute rakam olmalıdır.",
+	"ip"             => ":attribute geçerli bir IP adresi olmalıdır.",
+	"match"          => ":attribute biçimi geçersiz.",
+	"max"            => array(
+		"numeric" => ":attribute şundan küçük olmalıdır :max.",
+		"file"    => ":attribute şundan küçük olmalıdır :max kilobyte.",
+		"string"  => ":attribute şundan küçük olmalıdır :max karakter.",
+	),
+	"mimes"          => ":attribute dosya biçimi :values olmalıdır.",
+	"min"            => array(
+		"numeric" => ":attribute en az :min olmalıdır.",
+		"file"    => ":attribute en az :min kilobyte olmalıdır.",
+		"string"  => ":attribute en az :min karakter olmalıdır.",
+	),
+	"not_in"         => "Seçili :attribute geçersiz.",
+	"numeric"        => ":attribute rakam olmalıdır.",
+	"required"       => ":attribute alanı gereklidir.",
+	"same"           => ":attribute ile :other eşleşmelidir.",
+	"size"           => array(
+		"numeric" => ":attribute :size olmalıdır.",
+		"file"    => ":attribute :size kilobyte olmalıdır.",
+		"string"  => ":attribute :size karakter olmalıdır.",
+	),
+	"unique"         => ":attribute daha önceden kayıt edilmiş.",
+	"url"            => ":attribute biçimi geçersiz.",
+
+	/*
+	|--------------------------------------------------------------------------
+	| Custom Validation Language Lines
+	|--------------------------------------------------------------------------
+	|
+	| Here you may specify custom validation messages for attributes using the
+	| convention "attribute_rule" to name the lines. This helps keep your
+	| custom validation clean and tidy.
+	|
+	| So, say you want to use a custom validation message when validating that
+	| the "email" attribute is unique. Just add "email_unique" to this array
+	| with your custom message. The Validator will handle the rest!
+	|
+	*/
+
+	'custom' => array(),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Validation Attributes
+	|--------------------------------------------------------------------------
+	|
+	| The following language lines are used to swap attribute place-holders
+	| with something more reader friendly such as "E-Mail Address" instead
+	| of "email". Your users will thank you.
+	|
+	| The Validator class will automatically search this array of lines it
+	| is attempting to replace the :attribute place-holder in messages.
+	| It's pretty slick. We think you'll like it.
+	|
+	*/
+
+	'attributes' => array(),
+
+);

+ 0 - 0
php-laravel/application/libraries/.gitignore


+ 0 - 0
php-laravel/application/migrations/.gitignore


+ 0 - 0
php-laravel/application/models/.gitignore


+ 126 - 0
php-laravel/application/routes.php

@@ -0,0 +1,126 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Application Routes
+|--------------------------------------------------------------------------
+|
+| Simply tell Laravel the HTTP verbs and URIs it should respond to. It is a
+| breeze to setup your application using Laravel's RESTful routing and it
+| is perfectly suited for building large applications and simple APIs.
+|
+| Let's respond to a simple GET request to http://example.com/hello:
+|
+|		Route::get('hello', function()
+|		{
+|			return 'Hello World!';
+|		});
+|
+| You can even respond to more than one URI:
+|
+|		Route::post(array('hello', 'world'), function()
+|		{
+|			return 'Hello World!';
+|		});
+|
+| It's easy to allow URI wildcards using (:num) or (:any):
+|
+|		Route::put('hello/(:any)', function($name)
+|		{
+|			return "Welcome, $name.";
+|		});
+|
+*/
+
+Route::get('/json', function()
+{
+    return Response::json(array('message' => 'Hello World!'));
+});
+
+
+Route::get('/db', function()
+{
+    $queries = Input::get('queries', 1);
+    $worlds = array();
+
+    for($i = 0; $i < $queries; ++$i) {
+        $worlds[] = DB::table('World')->find(mt_rand(1, 10000));
+    }
+
+    return Response::json($worlds);
+});
+
+
+/*
+|--------------------------------------------------------------------------
+| Application 404 & 500 Error Handlers
+|--------------------------------------------------------------------------
+|
+| To centralize and simplify 404 handling, Laravel uses an awesome event
+| system to retrieve the response. Feel free to modify this function to
+| your tastes and the needs of your application.
+|
+| Similarly, we use an event to handle the display of 500 level errors
+| within the application. These errors are fired when there is an
+| uncaught exception thrown in the application. The exception object
+| that is captured during execution is then passed to the 500 listener.
+|
+*/
+
+Event::listen('404', function()
+{
+	return Response::error('404');
+});
+
+Event::listen('500', function($exception)
+{
+	return Response::error('500');
+});
+
+/*
+|--------------------------------------------------------------------------
+| Route Filters
+|--------------------------------------------------------------------------
+|
+| Filters provide a convenient method for attaching functionality to your
+| routes. The built-in before and after filters are called before and
+| after every request to your application, and you may even create
+| other filters that can be attached to individual routes.
+|
+| Let's walk through an example...
+|
+| First, define a filter:
+|
+|		Route::filter('filter', function()
+|		{
+|			return 'Filtered!';
+|		});
+|
+| Next, attach the filter to a route:
+|
+|		Route::get('/', array('before' => 'filter', function()
+|		{
+|			return 'Hello World!';
+|		}));
+|
+*/
+
+Route::filter('before', function()
+{
+	// Do stuff before every request to your application...
+});
+
+Route::filter('after', function($response)
+{
+	// Do stuff after every request to your application...
+});
+
+Route::filter('csrf', function()
+{
+	if (Request::forged()) return Response::error('500');
+});
+
+Route::filter('auth', function()
+{
+	if (Auth::guest()) return Redirect::to('login');
+});

+ 173 - 0
php-laravel/application/start.php

@@ -0,0 +1,173 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| PHP Display Errors Configuration
+|--------------------------------------------------------------------------
+|
+| Since Laravel intercepts and displays all errors with a detailed stack
+| trace, we can turn off the display_errors ini directive. However, you
+| may want to enable this option if you ever run into a dreaded white
+| screen of death, as it can provide some clues.
+|
+*/
+
+ini_set('display_errors', 'On');
+
+/*
+|--------------------------------------------------------------------------
+| Laravel Configuration Loader
+|--------------------------------------------------------------------------
+|
+| The Laravel configuration loader is responsible for returning an array
+| of configuration options for a given bundle and file. By default, we
+| use the files provided with Laravel; however, you are free to use
+| your own storage mechanism for configuration arrays.
+|
+*/
+
+Laravel\Event::listen(Laravel\Config::loader, function($bundle, $file)
+{
+	return Laravel\Config::file($bundle, $file);
+});
+
+/*
+|--------------------------------------------------------------------------
+| Register Class Aliases
+|--------------------------------------------------------------------------
+|
+| Aliases allow you to use classes without always specifying their fully
+| namespaced path. This is convenient for working with any library that
+| makes a heavy use of namespace for class organization. Here we will
+| simply register the configured class aliases.
+|
+*/
+
+$aliases = Laravel\Config::get('application.aliases');
+
+Laravel\Autoloader::$aliases = $aliases;
+
+/*
+|--------------------------------------------------------------------------
+| Auto-Loader Mappings
+|--------------------------------------------------------------------------
+|
+| Registering a mapping couldn't be easier. Just pass an array of class
+| to path maps into the "map" function of Autoloader. Then, when you
+| want to use that class, just use it. It's simple!
+|
+*/
+
+Autoloader::map(array(
+	'Base_Controller' => path('app').'controllers/base.php',
+));
+
+/*
+|--------------------------------------------------------------------------
+| Auto-Loader Directories
+|--------------------------------------------------------------------------
+|
+| The Laravel auto-loader can search directories for files using the PSR-0
+| naming convention. This convention basically organizes classes by using
+| the class namespace to indicate the directory structure.
+|
+*/
+
+Autoloader::directories(array(
+	path('app').'models',
+	path('app').'libraries',
+));
+
+/*
+|--------------------------------------------------------------------------
+| Laravel View Loader
+|--------------------------------------------------------------------------
+|
+| The Laravel view loader is responsible for returning the full file path
+| for the given bundle and view. Of course, a default implementation is
+| provided to load views according to typical Laravel conventions but
+| you may change this to customize how your views are organized.
+|
+*/
+
+Event::listen(View::loader, function($bundle, $view)
+{
+	return View::file($bundle, $view, Bundle::path($bundle).'views');
+});
+
+/*
+|--------------------------------------------------------------------------
+| Laravel Language Loader
+|--------------------------------------------------------------------------
+|
+| The Laravel language loader is responsible for returning the array of
+| language lines for a given bundle, language, and "file". A default
+| implementation has been provided which uses the default language
+| directories included with Laravel.
+|
+*/
+
+Event::listen(Lang::loader, function($bundle, $language, $file)
+{
+	return Lang::file($bundle, $language, $file);
+});
+
+/*
+|--------------------------------------------------------------------------
+| Attach The Laravel Profiler
+|--------------------------------------------------------------------------
+|
+| If the profiler is enabled, we will attach it to the Laravel events
+| for both queries and logs. This allows the profiler to intercept
+| any of the queries or logs performed by the application.
+|
+*/
+
+if (Config::get('application.profiler'))
+{
+	Profiler::attach();
+}
+
+/*
+|--------------------------------------------------------------------------
+| Enable The Blade View Engine
+|--------------------------------------------------------------------------
+|
+| The Blade view engine provides a clean, beautiful templating language
+| for your application, including syntax for echoing data and all of
+| the typical PHP control structures. We'll simply enable it here.
+|
+*/
+
+Blade::sharpen();
+
+/*
+|--------------------------------------------------------------------------
+| Set The Default Timezone
+|--------------------------------------------------------------------------
+|
+| We need to set the default timezone for the application. This controls
+| the timezone that will be used by any of the date methods and classes
+| utilized by Laravel or your application. The timezone may be set in
+| your application configuration file.
+|
+*/
+
+date_default_timezone_set(Config::get('application.timezone'));
+
+/*
+|--------------------------------------------------------------------------
+| Start / Load The User Session
+|--------------------------------------------------------------------------
+|
+| Sessions allow the web, which is stateless, to simulate state. In other
+| words, sessions allow you to store information about the current user
+| and state of your application. Here we'll just fire up the session
+| if a session driver has been configured.
+|
+*/
+
+if ( ! Request::cli() and Config::get('session.driver') !== '')
+{
+	Session::load();
+}

+ 0 - 0
php-laravel/application/tasks/.gitignore


+ 15 - 0
php-laravel/application/tests/example.test.php

@@ -0,0 +1,15 @@
+<?php
+
+class TestExample extends PHPUnit_Framework_TestCase {
+
+	/**
+	 * Test that a given condition is met.
+	 *
+	 * @return void
+	 */
+	public function testSomethingIsTrue()
+	{
+		$this->assertTrue(true);	
+	}
+
+}

+ 125 - 0
php-laravel/application/views/error/404.php

@@ -0,0 +1,125 @@
+<!doctype html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+	<title>Error 404 - Not Found</title>
+	<meta name="viewport" content="width=device-width">
+	<style type="text/css">
+		@import url(http://fonts.googleapis.com/css?family=Droid+Sans);
+
+		article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
+		audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
+		audio:not([controls]) { display: none; }
+		[hidden] { display: none; }
+		html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
+		html, button, input, select, textarea { font-family: sans-serif; color: #222; }
+		body { margin: 0; font-size: 1em; line-height: 1.4; }
+		::-moz-selection { background: #E37B52; color: #fff; text-shadow: none; }
+		::selection { background: #E37B52; color: #fff; text-shadow: none; }
+		a { color: #00e; }
+		a:visited { color: #551a8b; }
+		a:hover { color: #06e; }
+		a:focus { outline: thin dotted; }
+		a:hover, a:active { outline: 0; }
+		abbr[title] { border-bottom: 1px dotted; }
+		b, strong { font-weight: bold; }
+		blockquote { margin: 1em 40px; }
+		dfn { font-style: italic; }
+		hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
+		ins { background: #ff9; color: #000; text-decoration: none; }
+		mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
+		pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
+		pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
+		q { quotes: none; }
+		q:before, q:after { content: ""; content: none; }
+		small { font-size: 85%; }
+		sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+		sup { top: -0.5em; }
+		sub { bottom: -0.25em; }
+		ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
+		dd { margin: 0 0 0 40px; }
+		nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
+		img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
+		svg:not(:root) { overflow: hidden; }
+		figure { margin: 0; }
+		form { margin: 0; }
+		fieldset { border: 0; margin: 0; padding: 0; }
+		label { cursor: pointer; }
+		legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
+		button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
+		button, input { line-height: normal; }
+		button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
+		button[disabled], input[disabled] { cursor: default; }
+		input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
+		input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
+		input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
+		button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+		textarea { overflow: auto; vertical-align: top; resize: vertical; }
+		input:valid, textarea:valid {  }
+		input:invalid, textarea:invalid { background-color: #f0dddd; }
+		table { border-collapse: collapse; border-spacing: 0; }
+		td { vertical-align: top; }
+
+		body
+		{
+			font-family:'Droid Sans', sans-serif;
+			font-size:10pt;
+			color:#555;
+			line-height: 25px;
+		}
+
+		.wrapper
+		{
+			width:760px;
+			margin:0 auto 5em auto;
+		}
+
+		.main
+		{
+			overflow:hidden;
+		}
+
+		.error-spacer
+		{
+			height:4em;
+		}
+
+		a, a:visited
+		{
+			color:#2972A3;
+		}
+
+		a:hover
+		{
+			color:#72ADD4;
+		}
+	</style>
+</head>
+<body>
+	<div class="wrapper">
+		<div class="error-spacer"></div>
+		<div role="main" class="main">
+			<?php $messages = array('We need a map.', 'I think we\'re lost.', 'We took a wrong turn.'); ?>
+
+			<h1><?php echo $messages[mt_rand(0, 2)]; ?></h1>
+
+			<h2>Server Error: 404 (Not Found)</h2>
+
+			<hr>
+
+			<h3>What does this mean?</h3>
+
+			<p>
+				We couldn't find the page you requested on our servers. We're really sorry
+				about that. It's our fault, not yours. We'll work hard to get this page
+				back online as soon as possible.
+			</p>
+
+			<p>
+				Perhaps you would like to go to our <?php echo HTML::link('/', 'home page'); ?>?
+			</p>
+		</div>
+	</div>
+</body>
+</html>

+ 125 - 0
php-laravel/application/views/error/500.php

@@ -0,0 +1,125 @@
+<!doctype html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+	<title>Error 500 - Internal Server Error</title>
+	<meta name="viewport" content="width=device-width">
+	<style type="text/css">
+		@import url(http://fonts.googleapis.com/css?family=Droid+Sans);
+
+		article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
+		audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
+		audio:not([controls]) { display: none; }
+		[hidden] { display: none; }
+		html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
+		html, button, input, select, textarea { font-family: sans-serif; color: #222; }
+		body { margin: 0; font-size: 1em; line-height: 1.4; }
+		::-moz-selection { background: #E37B52; color: #fff; text-shadow: none; }
+		::selection { background: #E37B52; color: #fff; text-shadow: none; }
+		a { color: #00e; }
+		a:visited { color: #551a8b; }
+		a:hover { color: #06e; }
+		a:focus { outline: thin dotted; }
+		a:hover, a:active { outline: 0; }
+		abbr[title] { border-bottom: 1px dotted; }
+		b, strong { font-weight: bold; }
+		blockquote { margin: 1em 40px; }
+		dfn { font-style: italic; }
+		hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
+		ins { background: #ff9; color: #000; text-decoration: none; }
+		mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
+		pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
+		pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
+		q { quotes: none; }
+		q:before, q:after { content: ""; content: none; }
+		small { font-size: 85%; }
+		sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+		sup { top: -0.5em; }
+		sub { bottom: -0.25em; }
+		ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
+		dd { margin: 0 0 0 40px; }
+		nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
+		img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
+		svg:not(:root) { overflow: hidden; }
+		figure { margin: 0; }
+		form { margin: 0; }
+		fieldset { border: 0; margin: 0; padding: 0; }
+		label { cursor: pointer; }
+		legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
+		button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
+		button, input { line-height: normal; }
+		button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
+		button[disabled], input[disabled] { cursor: default; }
+		input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
+		input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
+		input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
+		button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+		textarea { overflow: auto; vertical-align: top; resize: vertical; }
+		input:valid, textarea:valid {  }
+		input:invalid, textarea:invalid { background-color: #f0dddd; }
+		table { border-collapse: collapse; border-spacing: 0; }
+		td { vertical-align: top; }
+
+		body
+		{
+			font-family:'Droid Sans', sans-serif;
+			font-size:10pt;
+			color:#555;
+			line-height: 25px;
+		}
+
+		.wrapper
+		{
+			width:760px;
+			margin:0 auto 5em auto;
+		}
+
+		.main
+		{
+			overflow:hidden;
+		}
+
+		.error-spacer
+		{
+			height:4em;
+		}
+
+		a, a:visited
+		{
+			color:#2972A3;
+		}
+
+		a:hover
+		{
+			color:#72ADD4;
+		}
+	</style>
+</head>
+<body>
+	<div class="wrapper">
+		<div class="error-spacer"></div>
+		<div role="main" class="main">
+			<?php $messages = array('Ouch.', 'Oh no!', 'Whoops!'); ?>
+
+			<h1><?php echo $messages[mt_rand(0, 2)]; ?></h1>
+
+			<h2>Server Error: 500 (Internal Server Error)</h2>
+
+			<hr>
+
+			<h3>What does this mean?</h3>
+
+			<p>
+				Something went wrong on our servers while we were processing your request.
+				We're really sorry about this, and will work hard to get this resolved as
+				soon as possible.
+			</p>
+
+			<p>
+				Perhaps you would like to go to our <?php echo HTML::link('/', 'home page'); ?>?
+			</p>
+		</div>
+	</div>
+</body>
+</html>

+ 57 - 0
php-laravel/application/views/home/index.blade.php

@@ -0,0 +1,57 @@
+<!doctype html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+	<title>Laravel: A Framework For Web Artisans</title>
+	<meta name="viewport" content="width=device-width">
+	{{ HTML::style('laravel/css/style.css') }}
+</head>
+<body>
+	<div class="wrapper">
+		<header>
+			<h1>Laravel</h1>
+			<h2>A Framework For Web Artisans</h2>
+
+			<p class="intro-text" style="margin-top: 45px;">
+			</p>
+		</header>
+		<div role="main" class="main">
+			<div class="home">
+				<h2>Learn the terrain.</h2>
+
+				<p>
+					You've landed yourself on our default home page. The route that
+					is generating this page lives at:
+				</p>
+
+				<pre>{{ path('app') }}routes.php</pre>
+
+				<p>And the view sitting before you can be found at:</p>
+
+				<pre>{{ path('app') }}views/home/index.blade.php</pre>
+
+				<h2>Grow in knowledge.</h2>
+
+				<p>
+					Learning to use Laravel is amazingly simple thanks to
+					its {{ HTML::link('docs', 'wonderful documentation') }}.
+				</p>
+
+				<h2>Create something beautiful.</h2>
+
+				<p>
+					Now that you're up and running, it's time to start creating!
+					Here are some links to help you get started:
+				</p>
+
+				<ul class="out-links">
+					<li><a href="http://laravel.com">Official Website</a></li>
+					<li><a href="http://forums.laravel.com">Laravel Forums</a></li>
+					<li><a href="http://github.com/laravel/laravel">GitHub Repository</a></li>
+				</ul>
+			</div>
+		</div>
+	</div>
+</body>
+</html>

+ 24 - 0
php-laravel/artisan

@@ -0,0 +1,24 @@
+<?php
+/**
+ * Laravel - A PHP Framework For Web Artisans
+ *
+ * @package  Laravel
+ * @version  3.2.14
+ * @author   Taylor Otwell <[email protected]>
+ * @link     http://laravel.com
+ */
+
+// --------------------------------------------------------------
+// Set the core Laravel path constants.
+// --------------------------------------------------------------
+require 'paths.php';
+
+// --------------------------------------------------------------
+// Bootstrap the Laravel core.
+// --------------------------------------------------------------
+require path('sys').'core.php';
+
+// --------------------------------------------------------------
+// Launch the Laravel "Artisan" CLI.
+// --------------------------------------------------------------
+require path('sys').'cli/artisan'.EXT;

+ 13 - 0
php-laravel/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "php-laravel",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 59
+    }
+  }]
+}

+ 0 - 0
php-laravel/bundles/.gitignore


+ 2934 - 0
php-laravel/bundles/docs/libraries/markdown.php

@@ -0,0 +1,2934 @@
+<?php
+#
+# Markdown Extra  -  A text-to-HTML conversion tool for web writers
+#
+# PHP Markdown & Extra
+# Copyright (c) 2004-2012 Michel Fortin  
+# <http://michelf.com/projects/php-markdown/>
+#
+# Original Markdown
+# Copyright (c) 2004-2006 John Gruber  
+# <http://daringfireball.net/projects/markdown/>
+#
+
+
+define( 'MARKDOWN_VERSION',  "1.0.1o" ); # Sun 8 Jan 2012
+define( 'MARKDOWNEXTRA_VERSION',  "1.2.5" ); # Sun 8 Jan 2012
+
+
+#
+# Global default settings:
+#
+
+# Change to ">" for HTML output
+@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX',  " />");
+
+# Define the width of a tab for code blocks.
+@define( 'MARKDOWN_TAB_WIDTH',     4 );
+
+# Optional title attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_TITLE',         "" );
+@define( 'MARKDOWN_FN_BACKLINK_TITLE',     "" );
+
+# Optional class attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_CLASS',         "" );
+@define( 'MARKDOWN_FN_BACKLINK_CLASS',     "" );
+
+
+#
+# WordPress settings:
+#
+
+# Change to false to remove Markdown from posts and/or comments.
+@define( 'MARKDOWN_WP_POSTS',      true );
+@define( 'MARKDOWN_WP_COMMENTS',   true );
+
+
+
+### Standard Function Interface ###
+
+@define( 'MARKDOWN_PARSER_CLASS',  'MarkdownExtra_Parser' );
+
+function Markdown($text) {
+#
+# Initialize the parser and return the result of its transform method.
+#
+	# Setup static parser variable.
+	static $parser;
+	if (!isset($parser)) {
+		$parser_class = MARKDOWN_PARSER_CLASS;
+		$parser = new $parser_class;
+	}
+
+	# Transform text using parser.
+	return $parser->transform($text);
+}
+
+
+### WordPress Plugin Interface ###
+
+/*
+Plugin Name: Markdown Extra
+Plugin URI: http://michelf.com/projects/php-markdown/
+Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.com/projects/php-markdown/">More...</a>
+Version: 1.2.5
+Author: Michel Fortin
+Author URI: http://michelf.com/
+*/
+
+if (isset($wp_version)) {
+	# More details about how it works here:
+	# <http://michelf.com/weblog/2005/wordpress-text-flow-vs-markdown/>
+	
+	# Post content and excerpts
+	# - Remove WordPress paragraph generator.
+	# - Run Markdown on excerpt, then remove all tags.
+	# - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
+	if (MARKDOWN_WP_POSTS) {
+		remove_filter('the_content',     'wpautop');
+        remove_filter('the_content_rss', 'wpautop');
+		remove_filter('the_excerpt',     'wpautop');
+		add_filter('the_content',     'mdwp_MarkdownPost', 6);
+        add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
+		add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
+		add_filter('get_the_excerpt', 'trim', 7);
+		add_filter('the_excerpt',     'mdwp_add_p');
+		add_filter('the_excerpt_rss', 'mdwp_strip_p');
+		
+		remove_filter('content_save_pre',  'balanceTags', 50);
+		remove_filter('excerpt_save_pre',  'balanceTags', 50);
+		add_filter('the_content',  	  'balanceTags', 50);
+		add_filter('get_the_excerpt', 'balanceTags', 9);
+	}
+	
+	# Add a footnote id prefix to posts when inside a loop.
+	function mdwp_MarkdownPost($text) {
+		static $parser;
+		if (!$parser) {
+			$parser_class = MARKDOWN_PARSER_CLASS;
+			$parser = new $parser_class;
+		}
+		if (is_single() || is_page() || is_feed()) {
+			$parser->fn_id_prefix = "";
+		} else {
+			$parser->fn_id_prefix = get_the_ID() . ".";
+		}
+		return $parser->transform($text);
+	}
+	
+	# Comments
+	# - Remove WordPress paragraph generator.
+	# - Remove WordPress auto-link generator.
+	# - Scramble important tags before passing them to the kses filter.
+	# - Run Markdown on excerpt then remove paragraph tags.
+	if (MARKDOWN_WP_COMMENTS) {
+		remove_filter('comment_text', 'wpautop', 30);
+		remove_filter('comment_text', 'make_clickable');
+		add_filter('pre_comment_content', 'Markdown', 6);
+		add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
+		add_filter('pre_comment_content', 'mdwp_show_tags', 12);
+		add_filter('get_comment_text',    'Markdown', 6);
+		add_filter('get_comment_excerpt', 'Markdown', 6);
+		add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
+	
+		global $mdwp_hidden_tags, $mdwp_placeholders;
+		$mdwp_hidden_tags = explode(' ',
+			'<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
+		$mdwp_placeholders = explode(' ', str_rot13(
+			'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
+			'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
+	}
+	
+	function mdwp_add_p($text) {
+		if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
+			$text = '<p>'.$text.'</p>';
+			$text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
+		}
+		return $text;
+	}
+	
+	function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
+
+	function mdwp_hide_tags($text) {
+		global $mdwp_hidden_tags, $mdwp_placeholders;
+		return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
+	}
+	function mdwp_show_tags($text) {
+		global $mdwp_hidden_tags, $mdwp_placeholders;
+		return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
+	}
+}
+
+
+### bBlog Plugin Info ###
+
+function identify_modifier_markdown() {
+	return array(
+		'name' => 'markdown',
+		'type' => 'modifier',
+		'nicename' => 'PHP Markdown Extra',
+		'description' => 'A text-to-HTML conversion tool for web writers',
+		'authors' => 'Michel Fortin and John Gruber',
+		'licence' => 'GPL',
+		'version' => MARKDOWNEXTRA_VERSION,
+		'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.com/projects/php-markdown/">More...</a>',
+		);
+}
+
+
+### Smarty Modifier Interface ###
+
+function smarty_modifier_markdown($text) {
+	return Markdown($text);
+}
+
+
+### Textile Compatibility Mode ###
+
+# Rename this file to "classTextile.php" and it can replace Textile everywhere.
+
+if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
+	# Try to include PHP SmartyPants. Should be in the same directory.
+	@include_once 'smartypants.php';
+	# Fake Textile class. It calls Markdown instead.
+	class Textile {
+		function TextileThis($text, $lite='', $encode='') {
+			if ($lite == '' && $encode == '')    $text = Markdown($text);
+			if (function_exists('SmartyPants'))  $text = SmartyPants($text);
+			return $text;
+		}
+		# Fake restricted version: restrictions are not supported for now.
+		function TextileRestricted($text, $lite='', $noimage='') {
+			return $this->TextileThis($text, $lite);
+		}
+		# Workaround to ensure compatibility with TextPattern 4.0.3.
+		function blockLite($text) { return $text; }
+	}
+}
+
+
+
+#
+# Markdown Parser Class
+#
+
+class Markdown_Parser {
+
+	# Regex to match balanced [brackets].
+	# Needed to insert a maximum bracked depth while converting to PHP.
+	var $nested_brackets_depth = 6;
+	var $nested_brackets_re;
+	
+	var $nested_url_parenthesis_depth = 4;
+	var $nested_url_parenthesis_re;
+
+	# Table of hash values for escaped characters:
+	var $escape_chars = '\`*_{}[]()>#+-.!';
+	var $escape_chars_re;
+
+	# Change to ">" for HTML output.
+	var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
+	var $tab_width = MARKDOWN_TAB_WIDTH;
+	
+	# Change to `true` to disallow markup or entities.
+	var $no_markup = false;
+	var $no_entities = false;
+	
+	# Predefined urls and titles for reference links and images.
+	var $predef_urls = array();
+	var $predef_titles = array();
+
+
+	function Markdown_Parser() {
+	#
+	# Constructor function. Initialize appropriate member variables.
+	#
+		$this->_initDetab();
+		$this->prepareItalicsAndBold();
+	
+		$this->nested_brackets_re = 
+			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
+			str_repeat('\])*', $this->nested_brackets_depth);
+	
+		$this->nested_url_parenthesis_re = 
+			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
+			str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
+		
+		$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
+		
+		# Sort document, block, and span gamut in ascendent priority order.
+		asort($this->document_gamut);
+		asort($this->block_gamut);
+		asort($this->span_gamut);
+	}
+
+
+	# Internal hashes used during transformation.
+	var $urls = array();
+	var $titles = array();
+	var $html_hashes = array();
+	
+	# Status flag to avoid invalid nesting.
+	var $in_anchor = false;
+	
+	
+	function setup() {
+	#
+	# Called before the transformation process starts to setup parser 
+	# states.
+	#
+		# Clear global hashes.
+		$this->urls = $this->predef_urls;
+		$this->titles = $this->predef_titles;
+		$this->html_hashes = array();
+		
+		$in_anchor = false;
+	}
+	
+	function teardown() {
+	#
+	# Called after the transformation process to clear any variable 
+	# which may be taking up memory unnecessarly.
+	#
+		$this->urls = array();
+		$this->titles = array();
+		$this->html_hashes = array();
+	}
+
+
+	function transform($text) {
+	#
+	# Main function. Performs some preprocessing on the input text
+	# and pass it through the document gamut.
+	#
+		$this->setup();
+	
+		# Remove UTF-8 BOM and marker character in input, if present.
+		$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
+
+		# Standardize line endings:
+		#   DOS to Unix and Mac to Unix
+		$text = preg_replace('{\r\n?}', "\n", $text);
+
+		# Make sure $text ends with a couple of newlines:
+		$text .= "\n\n";
+
+		# Convert all tabs to spaces.
+		$text = $this->detab($text);
+
+		# Turn block-level HTML blocks into hash entries
+		$text = $this->hashHTMLBlocks($text);
+
+		# Strip any lines consisting only of spaces and tabs.
+		# This makes subsequent regexen easier to write, because we can
+		# match consecutive blank lines with /\n+/ instead of something
+		# contorted like /[ ]*\n+/ .
+		$text = preg_replace('/^[ ]+$/m', '', $text);
+
+		# Run document gamut methods.
+		foreach ($this->document_gamut as $method => $priority) {
+			$text = $this->$method($text);
+		}
+		
+		$this->teardown();
+
+		return $text . "\n";
+	}
+	
+	var $document_gamut = array(
+		# Strip link definitions, store in hashes.
+		"stripLinkDefinitions" => 20,
+		
+		"runBasicBlockGamut"   => 30,
+		);
+
+
+	function stripLinkDefinitions($text) {
+	#
+	# Strips link definitions from text, stores the URLs and titles in
+	# hash references.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Link defs are in the form: ^[id]: url "optional title"
+		$text = preg_replace_callback('{
+							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
+							  [ ]*
+							  \n?				# maybe *one* newline
+							  [ ]*
+							(?:
+							  <(.+?)>			# url = $2
+							|
+							  (\S+?)			# url = $3
+							)
+							  [ ]*
+							  \n?				# maybe one newline
+							  [ ]*
+							(?:
+								(?<=\s)			# lookbehind for whitespace
+								["(]
+								(.*?)			# title = $4
+								[")]
+								[ ]*
+							)?	# title is optional
+							(?:\n+|\Z)
+			}xm',
+			array(&$this, '_stripLinkDefinitions_callback'),
+			$text);
+		return $text;
+	}
+	function _stripLinkDefinitions_callback($matches) {
+		$link_id = strtolower($matches[1]);
+		$url = $matches[2] == '' ? $matches[3] : $matches[2];
+		$this->urls[$link_id] = $url;
+		$this->titles[$link_id] =& $matches[4];
+		return ''; # String that will replace the block
+	}
+
+
+	function hashHTMLBlocks($text) {
+		if ($this->no_markup)  return $text;
+
+		$less_than_tab = $this->tab_width - 1;
+
+		# Hashify HTML blocks:
+		# We only want to do this for block-level HTML tags, such as headers,
+		# lists, and tables. That's because we still want to wrap <p>s around
+		# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+		# phrase emphasis, and spans. The list of tags we're looking for is
+		# hard-coded:
+		#
+		# *  List "a" is made of tags which can be both inline or block-level.
+		#    These will be treated block-level when the start tag is alone on 
+		#    its line, otherwise they're not matched here and will be taken as 
+		#    inline later.
+		# *  List "b" is made of tags which are always block-level;
+		#
+		$block_tags_a_re = 'ins|del';
+		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
+						   'script|noscript|form|fieldset|iframe|math';
+
+		# Regular expression for the content of a block tag.
+		$nested_tags_level = 4;
+		$attr = '
+			(?>				# optional tag attributes
+			  \s			# starts with whitespace
+			  (?>
+				[^>"/]+		# text outside quotes
+			  |
+				/+(?!>)		# slash not followed by ">"
+			  |
+				"[^"]*"		# text inside double quotes (tolerate ">")
+			  |
+				\'[^\']*\'	# text inside single quotes (tolerate ">")
+			  )*
+			)?	
+			';
+		$content =
+			str_repeat('
+				(?>
+				  [^<]+			# content without tag
+				|
+				  <\2			# nested opening tag
+					'.$attr.'	# attributes
+					(?>
+					  />
+					|
+					  >', $nested_tags_level).	# end of opening tag
+					  '.*?'.					# last level nested tag content
+			str_repeat('
+					  </\2\s*>	# closing nested tag
+					)
+				  |				
+					<(?!/\2\s*>	# other tags with a different name
+				  )
+				)*',
+				$nested_tags_level);
+		$content2 = str_replace('\2', '\3', $content);
+
+		# First, look for nested blocks, e.g.:
+		# 	<div>
+		# 		<div>
+		# 		tags for inner block must be indented.
+		# 		</div>
+		# 	</div>
+		#
+		# The outermost tags must start at the left margin for this to match, and
+		# the inner nested divs must be indented.
+		# We need to do this before the next, more liberal match, because the next
+		# match will start at the first `<div>` and stop at the first `</div>`.
+		$text = preg_replace_callback('{(?>
+			(?>
+				(?<=\n\n)		# Starting after a blank line
+				|				# or
+				\A\n?			# the beginning of the doc
+			)
+			(						# save in $1
+
+			  # Match from `\n<tag>` to `</tag>\n`, handling nested tags 
+			  # in between.
+					
+						[ ]{0,'.$less_than_tab.'}
+						<('.$block_tags_b_re.')# start tag = $2
+						'.$attr.'>			# attributes followed by > and \n
+						'.$content.'		# content, support nesting
+						</\2>				# the matching end tag
+						[ ]*				# trailing spaces/tabs
+						(?=\n+|\Z)	# followed by a newline or end of document
+
+			| # Special version for tags of group a.
+
+						[ ]{0,'.$less_than_tab.'}
+						<('.$block_tags_a_re.')# start tag = $3
+						'.$attr.'>[ ]*\n	# attributes followed by >
+						'.$content2.'		# content, support nesting
+						</\3>				# the matching end tag
+						[ ]*				# trailing spaces/tabs
+						(?=\n+|\Z)	# followed by a newline or end of document
+					
+			| # Special case just for <hr />. It was easier to make a special 
+			  # case than to make the other regex more complicated.
+			
+						[ ]{0,'.$less_than_tab.'}
+						<(hr)				# start tag = $2
+						'.$attr.'			# attributes
+						/?>					# the matching end tag
+						[ ]*
+						(?=\n{2,}|\Z)		# followed by a blank line or end of document
+			
+			| # Special case for standalone HTML comments:
+			
+					[ ]{0,'.$less_than_tab.'}
+					(?s:
+						<!-- .*? -->
+					)
+					[ ]*
+					(?=\n{2,}|\Z)		# followed by a blank line or end of document
+			
+			| # PHP and ASP-style processor instructions (<? and <%)
+			
+					[ ]{0,'.$less_than_tab.'}
+					(?s:
+						<([?%])			# $2
+						.*?
+						\2>
+					)
+					[ ]*
+					(?=\n{2,}|\Z)		# followed by a blank line or end of document
+					
+			)
+			)}Sxmi',
+			array(&$this, '_hashHTMLBlocks_callback'),
+			$text);
+
+		return $text;
+	}
+	function _hashHTMLBlocks_callback($matches) {
+		$text = $matches[1];
+		$key  = $this->hashBlock($text);
+		return "\n\n$key\n\n";
+	}
+	
+	
+	function hashPart($text, $boundary = 'X') {
+	#
+	# Called whenever a tag must be hashed when a function insert an atomic 
+	# element in the text stream. Passing $text to through this function gives
+	# a unique text-token which will be reverted back when calling unhash.
+	#
+	# The $boundary argument specify what character should be used to surround
+	# the token. By convension, "B" is used for block elements that needs not
+	# to be wrapped into paragraph tags at the end, ":" is used for elements
+	# that are word separators and "X" is used in the general case.
+	#
+		# Swap back any tag hash found in $text so we do not have to `unhash`
+		# multiple times at the end.
+		$text = $this->unhash($text);
+		
+		# Then hash the block.
+		static $i = 0;
+		$key = "$boundary\x1A" . ++$i . $boundary;
+		$this->html_hashes[$key] = $text;
+		return $key; # String that will replace the tag.
+	}
+
+
+	function hashBlock($text) {
+	#
+	# Shortcut function for hashPart with block-level boundaries.
+	#
+		return $this->hashPart($text, 'B');
+	}
+
+
+	var $block_gamut = array(
+	#
+	# These are all the transformations that form block-level
+	# tags like paragraphs, headers, and list items.
+	#
+		"doHeaders"         => 10,
+		"doHorizontalRules" => 20,
+		
+		"doLists"           => 40,
+		"doCodeBlocks"      => 50,
+		"doBlockQuotes"     => 60,
+		);
+
+	function runBlockGamut($text) {
+	#
+	# Run block gamut tranformations.
+	#
+		# We need to escape raw HTML in Markdown source before doing anything 
+		# else. This need to be done for each block, and not only at the 
+		# begining in the Markdown function since hashed blocks can be part of
+		# list items and could have been indented. Indented blocks would have 
+		# been seen as a code block in a previous pass of hashHTMLBlocks.
+		$text = $this->hashHTMLBlocks($text);
+		
+		return $this->runBasicBlockGamut($text);
+	}
+	
+	function runBasicBlockGamut($text) {
+	#
+	# Run block gamut tranformations, without hashing HTML blocks. This is 
+	# useful when HTML blocks are known to be already hashed, like in the first
+	# whole-document pass.
+	#
+		foreach ($this->block_gamut as $method => $priority) {
+			$text = $this->$method($text);
+		}
+		
+		# Finally form paragraph and restore hashed blocks.
+		$text = $this->formParagraphs($text);
+
+		return $text;
+	}
+	
+	
+	function doHorizontalRules($text) {
+		# Do Horizontal Rules:
+		return preg_replace(
+			'{
+				^[ ]{0,3}	# Leading space
+				([-*_])		# $1: First marker
+				(?>			# Repeated marker group
+					[ ]{0,2}	# Zero, one, or two spaces.
+					\1			# Marker character
+				){2,}		# Group repeated at least twice
+				[ ]*		# Tailing spaces
+				$			# End of line.
+			}mx',
+			"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n", 
+			$text);
+	}
+
+
+	var $span_gamut = array(
+	#
+	# These are all the transformations that occur *within* block-level
+	# tags like paragraphs, headers, and list items.
+	#
+		# Process character escapes, code spans, and inline HTML
+		# in one shot.
+		"parseSpan"           => -30,
+
+		# Process anchor and image tags. Images must come first,
+		# because ![foo][f] looks like an anchor.
+		"doImages"            =>  10,
+		"doAnchors"           =>  20,
+		
+		# Make links out of things like `<http://example.com/>`
+		# Must come after doAnchors, because you can use < and >
+		# delimiters in inline links like [this](<url>).
+		"doAutoLinks"         =>  30,
+		"encodeAmpsAndAngles" =>  40,
+
+		"doItalicsAndBold"    =>  50,
+		"doHardBreaks"        =>  60,
+		);
+
+	function runSpanGamut($text) {
+	#
+	# Run span gamut tranformations.
+	#
+		foreach ($this->span_gamut as $method => $priority) {
+			$text = $this->$method($text);
+		}
+
+		return $text;
+	}
+	
+	
+	function doHardBreaks($text) {
+		# Do hard breaks:
+		return preg_replace_callback('/ {2,}\n/', 
+			array(&$this, '_doHardBreaks_callback'), $text);
+	}
+	function _doHardBreaks_callback($matches) {
+		return $this->hashPart("<br$this->empty_element_suffix\n");
+	}
+
+
+	function doAnchors($text) {
+	#
+	# Turn Markdown link shortcuts into XHTML <a> tags.
+	#
+		if ($this->in_anchor) return $text;
+		$this->in_anchor = true;
+		
+		#
+		# First, handle reference-style links: [link text] [id]
+		#
+		$text = preg_replace_callback('{
+			(					# wrap whole match in $1
+			  \[
+				('.$this->nested_brackets_re.')	# link text = $2
+			  \]
+
+			  [ ]?				# one optional space
+			  (?:\n[ ]*)?		# one optional newline followed by spaces
+
+			  \[
+				(.*?)		# id = $3
+			  \]
+			)
+			}xs',
+			array(&$this, '_doAnchors_reference_callback'), $text);
+
+		#
+		# Next, inline-style links: [link text](url "optional title")
+		#
+		$text = preg_replace_callback('{
+			(				# wrap whole match in $1
+			  \[
+				('.$this->nested_brackets_re.')	# link text = $2
+			  \]
+			  \(			# literal paren
+				[ \n]*
+				(?:
+					<(.+?)>	# href = $3
+				|
+					('.$this->nested_url_parenthesis_re.')	# href = $4
+				)
+				[ \n]*
+				(			# $5
+				  ([\'"])	# quote char = $6
+				  (.*?)		# Title = $7
+				  \6		# matching quote
+				  [ \n]*	# ignore any spaces/tabs between closing quote and )
+				)?			# title is optional
+			  \)
+			)
+			}xs',
+			array(&$this, '_doAnchors_inline_callback'), $text);
+
+		#
+		# Last, handle reference-style shortcuts: [link text]
+		# These must come last in case you've also got [link text][1]
+		# or [link text](/foo)
+		#
+		$text = preg_replace_callback('{
+			(					# wrap whole match in $1
+			  \[
+				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
+			  \]
+			)
+			}xs',
+			array(&$this, '_doAnchors_reference_callback'), $text);
+
+		$this->in_anchor = false;
+		return $text;
+	}
+	function _doAnchors_reference_callback($matches) {
+		$whole_match =  $matches[1];
+		$link_text   =  $matches[2];
+		$link_id     =& $matches[3];
+
+		if ($link_id == "") {
+			# for shortcut links like [this][] or [this].
+			$link_id = $link_text;
+		}
+		
+		# lower-case and turn embedded newlines into spaces
+		$link_id = strtolower($link_id);
+		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+		if (isset($this->urls[$link_id])) {
+			$url = $this->urls[$link_id];
+			$url = URL::to($url);
+			$url = $this->encodeAttribute($url);
+			
+			$result = "<a href=\"$url\"";
+			if ( isset( $this->titles[$link_id] ) ) {
+				$title = $this->titles[$link_id];
+				$title = $this->encodeAttribute($title);
+				$result .=  " title=\"$title\"";
+			}
+		
+			$link_text = $this->runSpanGamut($link_text);
+			$result .= ">$link_text</a>";
+			$result = $this->hashPart($result);
+		}
+		else {
+			$result = $whole_match;
+		}
+		return $result;
+	}
+	function _doAnchors_inline_callback($matches) {
+		$whole_match	=  $matches[1];
+		$link_text		=  $this->runSpanGamut($matches[2]);
+		$url			=  $matches[3] == '' ? $matches[4] : $matches[3];
+		$title			=& $matches[7];
+
+		$url = URL::to($url);
+		$url = $this->encodeAttribute($url);
+
+		$result = "<a href=\"$url\"";
+		if (isset($title)) {
+			$title = $this->encodeAttribute($title);
+			$result .=  " title=\"$title\"";
+		}
+		
+		$link_text = $this->runSpanGamut($link_text);
+		$result .= ">$link_text</a>";
+
+		return $this->hashPart($result);
+	}
+
+
+	function doImages($text) {
+	#
+	# Turn Markdown image shortcuts into <img> tags.
+	#
+		#
+		# First, handle reference-style labeled images: ![alt text][id]
+		#
+		$text = preg_replace_callback('{
+			(				# wrap whole match in $1
+			  !\[
+				('.$this->nested_brackets_re.')		# alt text = $2
+			  \]
+
+			  [ ]?				# one optional space
+			  (?:\n[ ]*)?		# one optional newline followed by spaces
+
+			  \[
+				(.*?)		# id = $3
+			  \]
+
+			)
+			}xs', 
+			array(&$this, '_doImages_reference_callback'), $text);
+
+		#
+		# Next, handle inline images:  ![alt text](url "optional title")
+		# Don't forget: encode * and _
+		#
+		$text = preg_replace_callback('{
+			(				# wrap whole match in $1
+			  !\[
+				('.$this->nested_brackets_re.')		# alt text = $2
+			  \]
+			  \s?			# One optional whitespace character
+			  \(			# literal paren
+				[ \n]*
+				(?:
+					<(\S*)>	# src url = $3
+				|
+					('.$this->nested_url_parenthesis_re.')	# src url = $4
+				)
+				[ \n]*
+				(			# $5
+				  ([\'"])	# quote char = $6
+				  (.*?)		# title = $7
+				  \6		# matching quote
+				  [ \n]*
+				)?			# title is optional
+			  \)
+			)
+			}xs',
+			array(&$this, '_doImages_inline_callback'), $text);
+
+		return $text;
+	}
+	function _doImages_reference_callback($matches) {
+		$whole_match = $matches[1];
+		$alt_text    = $matches[2];
+		$link_id     = strtolower($matches[3]);
+
+		if ($link_id == "") {
+			$link_id = strtolower($alt_text); # for shortcut links like ![this][].
+		}
+
+		$alt_text = $this->encodeAttribute($alt_text);
+		if (isset($this->urls[$link_id])) {
+			$url = $this->encodeAttribute($this->urls[$link_id]);
+			$result = "<img src=\"$url\" alt=\"$alt_text\"";
+			if (isset($this->titles[$link_id])) {
+				$title = $this->titles[$link_id];
+				$title = $this->encodeAttribute($title);
+				$result .=  " title=\"$title\"";
+			}
+			$result .= $this->empty_element_suffix;
+			$result = $this->hashPart($result);
+		}
+		else {
+			# If there's no such link ID, leave intact:
+			$result = $whole_match;
+		}
+
+		return $result;
+	}
+	function _doImages_inline_callback($matches) {
+		$whole_match	= $matches[1];
+		$alt_text		= $matches[2];
+		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
+		$title			=& $matches[7];
+
+		$alt_text = $this->encodeAttribute($alt_text);
+		$url = $this->encodeAttribute($url);
+		$result = "<img src=\"$url\" alt=\"$alt_text\"";
+		if (isset($title)) {
+			$title = $this->encodeAttribute($title);
+			$result .=  " title=\"$title\""; # $title already quoted
+		}
+		$result .= $this->empty_element_suffix;
+
+		return $this->hashPart($result);
+	}
+
+
+	function doHeaders($text) {
+		# Setext-style headers:
+		#	  Header 1
+		#	  ========
+		#  
+		#	  Header 2
+		#	  --------
+		#
+		$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
+			array(&$this, '_doHeaders_callback_setext'), $text);
+
+		# atx-style headers:
+		#	# Header 1
+		#	## Header 2
+		#	## Header 2 with closing hashes ##
+		#	...
+		#	###### Header 6
+		#
+		$text = preg_replace_callback('{
+				^(\#{1,6})	# $1 = string of #\'s
+				[ ]*
+				(.+?)		# $2 = Header text
+				[ ]*
+				\#*			# optional closing #\'s (not counted)
+				\n+
+			}xm',
+			array(&$this, '_doHeaders_callback_atx'), $text);
+
+		return $text;
+	}
+	function _doHeaders_callback_setext($matches) {
+		# Terrible hack to check we haven't found an empty list item.
+		if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
+			return $matches[0];
+		
+		$level = $matches[2]{0} == '=' ? 1 : 2;
+		$block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+	function _doHeaders_callback_atx($matches) {
+		$level = strlen($matches[1]);
+		$block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+
+
+	function doLists($text) {
+	#
+	# Form HTML ordered (numbered) and unordered (bulleted) lists.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Re-usable patterns to match list item bullets and number markers:
+		$marker_ul_re  = '[*+-]';
+		$marker_ol_re  = '\d+[\.]';
+		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+
+		$markers_relist = array(
+			$marker_ul_re => $marker_ol_re,
+			$marker_ol_re => $marker_ul_re,
+			);
+
+		foreach ($markers_relist as $marker_re => $other_marker_re) {
+			# Re-usable pattern to match any entirel ul or ol list:
+			$whole_list_re = '
+				(								# $1 = whole list
+				  (								# $2
+					([ ]{0,'.$less_than_tab.'})	# $3 = number of spaces
+					('.$marker_re.')			# $4 = first list item marker
+					[ ]+
+				  )
+				  (?s:.+?)
+				  (								# $5
+					  \z
+					|
+					  \n{2,}
+					  (?=\S)
+					  (?!						# Negative lookahead for another list item marker
+						[ ]*
+						'.$marker_re.'[ ]+
+					  )
+					|
+					  (?=						# Lookahead for another kind of list
+					    \n
+						\3						# Must have the same indentation
+						'.$other_marker_re.'[ ]+
+					  )
+				  )
+				)
+			'; // mx
+			
+			# We use a different prefix before nested lists than top-level lists.
+			# See extended comment in _ProcessListItems().
+		
+			if ($this->list_level) {
+				$text = preg_replace_callback('{
+						^
+						'.$whole_list_re.'
+					}mx',
+					array(&$this, '_doLists_callback'), $text);
+			}
+			else {
+				$text = preg_replace_callback('{
+						(?:(?<=\n)\n|\A\n?) # Must eat the newline
+						'.$whole_list_re.'
+					}mx',
+					array(&$this, '_doLists_callback'), $text);
+			}
+		}
+
+		return $text;
+	}
+	function _doLists_callback($matches) {
+		# Re-usable patterns to match list item bullets and number markers:
+		$marker_ul_re  = '[*+-]';
+		$marker_ol_re  = '\d+[\.]';
+		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+		
+		$list = $matches[1];
+		$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
+		
+		$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
+		
+		$list .= "\n";
+		$result = $this->processListItems($list, $marker_any_re);
+		
+		$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
+		return "\n". $result ."\n\n";
+	}
+
+	var $list_level = 0;
+
+	function processListItems($list_str, $marker_any_re) {
+	#
+	#	Process the contents of a single ordered or unordered list, splitting it
+	#	into individual list items.
+	#
+		# The $this->list_level global keeps track of when we're inside a list.
+		# Each time we enter a list, we increment it; when we leave a list,
+		# we decrement. If it's zero, we're not in a list anymore.
+		#
+		# We do this because when we're not inside a list, we want to treat
+		# something like this:
+		#
+		#		I recommend upgrading to version
+		#		8. Oops, now this line is treated
+		#		as a sub-list.
+		#
+		# As a single paragraph, despite the fact that the second line starts
+		# with a digit-period-space sequence.
+		#
+		# Whereas when we're inside a list (or sub-list), that line will be
+		# treated as the start of a sub-list. What a kludge, huh? This is
+		# an aspect of Markdown's syntax that's hard to parse perfectly
+		# without resorting to mind-reading. Perhaps the solution is to
+		# change the syntax rules such that sub-lists must start with a
+		# starting cardinal number; e.g. "1." or "a.".
+		
+		$this->list_level++;
+
+		# trim trailing blank lines:
+		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+		$list_str = preg_replace_callback('{
+			(\n)?							# leading line = $1
+			(^[ ]*)							# leading whitespace = $2
+			('.$marker_any_re.'				# list marker and space = $3
+				(?:[ ]+|(?=\n))	# space only required if item is not empty
+			)
+			((?s:.*?))						# list item text   = $4
+			(?:(\n+(?=\n))|\n)				# tailing blank line = $5
+			(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
+			}xm',
+			array(&$this, '_processListItems_callback'), $list_str);
+
+		$this->list_level--;
+		return $list_str;
+	}
+	function _processListItems_callback($matches) {
+		$item = $matches[4];
+		$leading_line =& $matches[1];
+		$leading_space =& $matches[2];
+		$marker_space = $matches[3];
+		$tailing_blank_line =& $matches[5];
+
+		if ($leading_line || $tailing_blank_line || 
+			preg_match('/\n{2,}/', $item))
+		{
+			# Replace marker with the appropriate whitespace indentation
+			$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
+			$item = $this->runBlockGamut($this->outdent($item)."\n");
+		}
+		else {
+			# Recursion for sub-lists:
+			$item = $this->doLists($this->outdent($item));
+			$item = preg_replace('/\n+$/', '', $item);
+			$item = $this->runSpanGamut($item);
+		}
+
+		return "<li>" . $item . "</li>\n";
+	}
+
+
+	function doCodeBlocks($text) {
+	#
+	#	Process Markdown `<pre><code>` blocks.
+	#
+		$text = preg_replace_callback('{
+				(?:\n\n|\A\n?)
+				(	            # $1 = the code block -- one or more lines, starting with a space/tab
+				  (?>
+					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
+					.*\n+
+				  )+
+				)
+				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
+			}xm',
+			array(&$this, '_doCodeBlocks_callback'), $text);
+
+		return $text;
+	}
+	function _doCodeBlocks_callback($matches) {
+		$codeblock = $matches[1];
+
+		$codeblock = $this->outdent($codeblock);
+		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+
+		# trim leading newlines and trailing newlines
+		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+
+		$codeblock = "<pre class=\"prettyprint linenums\">$codeblock\n</pre>";
+		return "\n\n".$this->hashBlock($codeblock)."\n\n";
+	}
+
+
+	function makeCodeSpan($code) {
+	#
+	# Create a code span markup for $code. Called from handleSpanToken.
+	#
+		$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+		return $this->hashPart("<code>$code</code>");
+	}
+
+
+	var $em_relist = array(
+		''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
+		'_' => '(?<=\S|^)(?<!_)_(?!_)',
+		);
+	var $strong_relist = array(
+		''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
+		'__' => '(?<=\S|^)(?<!_)__(?!_)',
+		);
+	var $em_strong_relist = array(
+		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
+		'___' => '(?<=\S|^)(?<!_)___(?!_)',
+		);
+	var $em_strong_prepared_relist;
+	
+	function prepareItalicsAndBold() {
+	#
+	# Prepare regular expressions for searching emphasis tokens in any
+	# context.
+	#
+		foreach ($this->em_relist as $em => $em_re) {
+			foreach ($this->strong_relist as $strong => $strong_re) {
+				# Construct list of allowed token expressions.
+				$token_relist = array();
+				if (isset($this->em_strong_relist["$em$strong"])) {
+					$token_relist[] = $this->em_strong_relist["$em$strong"];
+				}
+				$token_relist[] = $em_re;
+				$token_relist[] = $strong_re;
+				
+				# Construct master expression from list.
+				$token_re = '{('. implode('|', $token_relist) .')}';
+				$this->em_strong_prepared_relist["$em$strong"] = $token_re;
+			}
+		}
+	}
+	
+	function doItalicsAndBold($text) {
+		$token_stack = array('');
+		$text_stack = array('');
+		$em = '';
+		$strong = '';
+		$tree_char_em = false;
+		
+		while (1) {
+			#
+			# Get prepared regular expression for seraching emphasis tokens
+			# in current context.
+			#
+			$token_re = $this->em_strong_prepared_relist["$em$strong"];
+			
+			#
+			# Each loop iteration search for the next emphasis token. 
+			# Each token is then passed to handleSpanToken.
+			#
+			$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+			$text_stack[0] .= $parts[0];
+			$token =& $parts[1];
+			$text =& $parts[2];
+			
+			if (empty($token)) {
+				# Reached end of text span: empty stack without emitting.
+				# any more emphasis.
+				while ($token_stack[0]) {
+					$text_stack[1] .= array_shift($token_stack);
+					$text_stack[0] .= array_shift($text_stack);
+				}
+				break;
+			}
+			
+			$token_len = strlen($token);
+			if ($tree_char_em) {
+				# Reached closing marker while inside a three-char emphasis.
+				if ($token_len == 3) {
+					# Three-char closing marker, close em and strong.
+					array_shift($token_stack);
+					$span = array_shift($text_stack);
+					$span = $this->runSpanGamut($span);
+					$span = "<strong><em>$span</em></strong>";
+					$text_stack[0] .= $this->hashPart($span);
+					$em = '';
+					$strong = '';
+				} else {
+					# Other closing marker: close one em or strong and
+					# change current token state to match the other
+					$token_stack[0] = str_repeat($token{0}, 3-$token_len);
+					$tag = $token_len == 2 ? "strong" : "em";
+					$span = $text_stack[0];
+					$span = $this->runSpanGamut($span);
+					$span = "<$tag>$span</$tag>";
+					$text_stack[0] = $this->hashPart($span);
+					$$tag = ''; # $$tag stands for $em or $strong
+				}
+				$tree_char_em = false;
+			} else if ($token_len == 3) {
+				if ($em) {
+					# Reached closing marker for both em and strong.
+					# Closing strong marker:
+					for ($i = 0; $i < 2; ++$i) {
+						$shifted_token = array_shift($token_stack);
+						$tag = strlen($shifted_token) == 2 ? "strong" : "em";
+						$span = array_shift($text_stack);
+						$span = $this->runSpanGamut($span);
+						$span = "<$tag>$span</$tag>";
+						$text_stack[0] .= $this->hashPart($span);
+						$$tag = ''; # $$tag stands for $em or $strong
+					}
+				} else {
+					# Reached opening three-char emphasis marker. Push on token 
+					# stack; will be handled by the special condition above.
+					$em = $token{0};
+					$strong = "$em$em";
+					array_unshift($token_stack, $token);
+					array_unshift($text_stack, '');
+					$tree_char_em = true;
+				}
+			} else if ($token_len == 2) {
+				if ($strong) {
+					# Unwind any dangling emphasis marker:
+					if (strlen($token_stack[0]) == 1) {
+						$text_stack[1] .= array_shift($token_stack);
+						$text_stack[0] .= array_shift($text_stack);
+					}
+					# Closing strong marker:
+					array_shift($token_stack);
+					$span = array_shift($text_stack);
+					$span = $this->runSpanGamut($span);
+					$span = "<strong>$span</strong>";
+					$text_stack[0] .= $this->hashPart($span);
+					$strong = '';
+				} else {
+					array_unshift($token_stack, $token);
+					array_unshift($text_stack, '');
+					$strong = $token;
+				}
+			} else {
+				# Here $token_len == 1
+				if ($em) {
+					if (strlen($token_stack[0]) == 1) {
+						# Closing emphasis marker:
+						array_shift($token_stack);
+						$span = array_shift($text_stack);
+						$span = $this->runSpanGamut($span);
+						$span = "<em>$span</em>";
+						$text_stack[0] .= $this->hashPart($span);
+						$em = '';
+					} else {
+						$text_stack[0] .= $token;
+					}
+				} else {
+					array_unshift($token_stack, $token);
+					array_unshift($text_stack, '');
+					$em = $token;
+				}
+			}
+		}
+		return $text_stack[0];
+	}
+
+
+	function doBlockQuotes($text) {
+		$text = preg_replace_callback('/
+			  (								# Wrap whole match in $1
+				(?>
+				  ^[ ]*>[ ]?			# ">" at the start of a line
+					.+\n					# rest of the first line
+				  (.+\n)*					# subsequent consecutive lines
+				  \n*						# blanks
+				)+
+			  )
+			/xm',
+			array(&$this, '_doBlockQuotes_callback'), $text);
+
+		return $text;
+	}
+	function _doBlockQuotes_callback($matches) {
+		$bq = $matches[1];
+		# trim one level of quoting - trim whitespace-only lines
+		$bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+		$bq = $this->runBlockGamut($bq);		# recurse
+
+		$bq = preg_replace('/^/m', "  ", $bq);
+		# These leading spaces cause problem with <pre> content, 
+		# so we need to fix that:
+		$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', 
+			array(&$this, '_doBlockQuotes_callback2'), $bq);
+
+		return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
+	}
+	function _doBlockQuotes_callback2($matches) {
+		$pre = $matches[1];
+		$pre = preg_replace('/^  /m', '', $pre);
+		return $pre;
+	}
+
+
+	function formParagraphs($text) {
+	#
+	#	Params:
+	#		$text - string to process with html <p> tags
+	#
+		# Strip leading and trailing lines:
+		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+		#
+		# Wrap <p> tags and unhashify HTML blocks
+		#
+		foreach ($grafs as $key => $value) {
+			if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+				# Is a paragraph.
+				$value = $this->runSpanGamut($value);
+				$value = preg_replace('/^([ ]*)/', "<p>", $value);
+				$value .= "</p>";
+				$grafs[$key] = $this->unhash($value);
+			}
+			else {
+				# Is a block.
+				# Modify elements of @grafs in-place...
+				$graf = $value;
+				$block = $this->html_hashes[$graf];
+				$graf = $block;
+//				if (preg_match('{
+//					\A
+//					(							# $1 = <div> tag
+//					  <div  \s+
+//					  [^>]*
+//					  \b
+//					  markdown\s*=\s*  ([\'"])	#	$2 = attr quote char
+//					  1
+//					  \2
+//					  [^>]*
+//					  >
+//					)
+//					(							# $3 = contents
+//					.*
+//					)
+//					(</div>)					# $4 = closing tag
+//					\z
+//					}xs', $block, $matches))
+//				{
+//					list(, $div_open, , $div_content, $div_close) = $matches;
+//
+//					# We can't call Markdown(), because that resets the hash;
+//					# that initialization code should be pulled into its own sub, though.
+//					$div_content = $this->hashHTMLBlocks($div_content);
+//					
+//					# Run document gamut methods on the content.
+//					foreach ($this->document_gamut as $method => $priority) {
+//						$div_content = $this->$method($div_content);
+//					}
+//
+//					$div_open = preg_replace(
+//						'{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+//
+//					$graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+//				}
+				$grafs[$key] = $graf;
+			}
+		}
+
+		return implode("\n\n", $grafs);
+	}
+
+
+	function encodeAttribute($text) {
+	#
+	# Encode text for a double-quoted HTML attribute. This function
+	# is *not* suitable for attributes enclosed in single quotes.
+	#
+		$text = $this->encodeAmpsAndAngles($text);
+		$text = str_replace('"', '&quot;', $text);
+		return $text;
+	}
+	
+	
+	function encodeAmpsAndAngles($text) {
+	#
+	# Smart processing for ampersands and angle brackets that need to 
+	# be encoded. Valid character entities are left alone unless the
+	# no-entities mode is set.
+	#
+		if ($this->no_entities) {
+			$text = str_replace('&', '&amp;', $text);
+		} else {
+			# Ampersand-encoding based entirely on Nat Irons's Amputator
+			# MT plugin: <http://bumppo.net/projects/amputator/>
+			$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
+								'&amp;', $text);;
+		}
+		# Encode remaining <'s
+		$text = str_replace('<', '&lt;', $text);
+
+		return $text;
+	}
+
+
+	function doAutoLinks($text) {
+		$text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', 
+			array(&$this, '_doAutoLinks_url_callback'), $text);
+
+		# Email addresses: <[email protected]>
+		$text = preg_replace_callback('{
+			<
+			(?:mailto:)?
+			(
+				(?:
+					[-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
+				|
+					".*?"
+				)
+				\@
+				(?:
+					[-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+				|
+					\[[\d.a-fA-F:]+\]	# IPv4 & IPv6
+				)
+			)
+			>
+			}xi',
+			array(&$this, '_doAutoLinks_email_callback'), $text);
+
+		return $text;
+	}
+	function _doAutoLinks_url_callback($matches) {
+		$url = $this->encodeAttribute($matches[1]);
+		$link = "<a href=\"$url\">$url</a>";
+		return $this->hashPart($link);
+	}
+	function _doAutoLinks_email_callback($matches) {
+		$address = $matches[1];
+		$link = $this->encodeEmailAddress($address);
+		return $this->hashPart($link);
+	}
+
+
+	function encodeEmailAddress($addr) {
+	#
+	#	Input: an email address, e.g. "[email protected]"
+	#
+	#	Output: the email address as a mailto link, with each character
+	#		of the address encoded as either a decimal or hex entity, in
+	#		the hopes of foiling most address harvesting spam bots. E.g.:
+	#
+	#	  <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
+	#        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
+	#        &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
+	#        &#101;&#46;&#x63;&#111;&#x6d;</a></p>
+	#
+	#	Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+	#   With some optimizations by Milian Wolff.
+	#
+		$addr = "mailto:" . $addr;
+		$chars = preg_split('/(?<!^)(?!$)/', $addr);
+		$seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
+		
+		foreach ($chars as $key => $char) {
+			$ord = ord($char);
+			# Ignore non-ascii chars.
+			if ($ord < 128) {
+				$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
+				# roughly 10% raw, 45% hex, 45% dec
+				# '@' *must* be encoded. I insist.
+				if ($r > 90 && $char != '@') /* do nothing */;
+				else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
+				else              $chars[$key] = '&#'.$ord.';';
+			}
+		}
+		
+		$addr = implode('', $chars);
+		$text = implode('', array_slice($chars, 7)); # text without `mailto:`
+		$addr = "<a href=\"$addr\">$text</a>";
+
+		return $addr;
+	}
+
+
+	function parseSpan($str) {
+	#
+	# Take the string $str and parse it into tokens, hashing embeded HTML,
+	# escaped characters and handling code spans.
+	#
+		$output = '';
+		
+		$span_re = '{
+				(
+					\\\\'.$this->escape_chars_re.'
+				|
+					(?<![`\\\\])
+					`+						# code span marker
+			'.( $this->no_markup ? '' : '
+				|
+					<!--    .*?     -->		# comment
+				|
+					<\?.*?\?> | <%.*?%>		# processing instruction
+				|
+					<[/!$]?[-a-zA-Z0-9:_]+	# regular tags
+					(?>
+						\s
+						(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+					)?
+					>
+			').'
+				)
+				}xs';
+
+		while (1) {
+			#
+			# Each loop iteration seach for either the next tag, the next 
+			# openning code span marker, or the next escaped character. 
+			# Each token is then passed to handleSpanToken.
+			#
+			$parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+			
+			# Create token from text preceding tag.
+			if ($parts[0] != "") {
+				$output .= $parts[0];
+			}
+			
+			# Check if we reach the end.
+			if (isset($parts[1])) {
+				$output .= $this->handleSpanToken($parts[1], $parts[2]);
+				$str = $parts[2];
+			}
+			else {
+				break;
+			}
+		}
+		
+		return $output;
+	}
+	
+	
+	function handleSpanToken($token, &$str) {
+	#
+	# Handle $token provided by parseSpan by determining its nature and 
+	# returning the corresponding value that should replace it.
+	#
+		switch ($token{0}) {
+			case "\\":
+				return $this->hashPart("&#". ord($token{1}). ";");
+			case "`":
+				# Search for end marker in remaining text.
+				if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', 
+					$str, $matches))
+				{
+					$str = $matches[2];
+					$codespan = $this->makeCodeSpan($matches[1]);
+					return $this->hashPart($codespan);
+				}
+				return $token; // return as text since no ending marker found.
+			default:
+				return $this->hashPart($token);
+		}
+	}
+
+
+	function outdent($text) {
+	#
+	# Remove one level of line-leading tabs or spaces
+	#
+		return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
+	}
+
+
+	# String length function for detab. `_initDetab` will create a function to 
+	# hanlde UTF-8 if the default function does not exist.
+	var $utf8_strlen = 'mb_strlen';
+	
+	function detab($text) {
+	#
+	# Replace tabs with the appropriate amount of space.
+	#
+		# For each line we separate the line in blocks delemited by
+		# tab characters. Then we reconstruct every line by adding the 
+		# appropriate number of space between each blocks.
+		
+		$text = preg_replace_callback('/^.*\t.*$/m',
+			array(&$this, '_detab_callback'), $text);
+
+		return $text;
+	}
+	function _detab_callback($matches) {
+		$line = $matches[0];
+		$strlen = $this->utf8_strlen; # strlen function for UTF-8.
+		
+		# Split in blocks.
+		$blocks = explode("\t", $line);
+		# Add each blocks to the line.
+		$line = $blocks[0];
+		unset($blocks[0]); # Do not add first block twice.
+		foreach ($blocks as $block) {
+			# Calculate amount of space, insert spaces, insert block.
+			$amount = $this->tab_width - 
+				$strlen($line, 'UTF-8') % $this->tab_width;
+			$line .= str_repeat(" ", $amount) . $block;
+		}
+		return $line;
+	}
+	function _initDetab() {
+	#
+	# Check for the availability of the function in the `utf8_strlen` property
+	# (initially `mb_strlen`). If the function is not available, create a 
+	# function that will loosely count the number of UTF-8 characters with a
+	# regular expression.
+	#
+		if (function_exists($this->utf8_strlen)) return;
+		$this->utf8_strlen = create_function('$text', 'return preg_match_all(
+			"/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", 
+			$text, $m);');
+	}
+
+
+	function unhash($text) {
+	#
+	# Swap back in all the tags hashed by _HashHTMLBlocks.
+	#
+		return preg_replace_callback('/(.)\x1A[0-9]+\1/', 
+			array(&$this, '_unhash_callback'), $text);
+	}
+	function _unhash_callback($matches) {
+		return $this->html_hashes[$matches[0]];
+	}
+
+}
+
+
+#
+# Markdown Extra Parser Class
+#
+
+class MarkdownExtra_Parser extends Markdown_Parser {
+
+	# Prefix for footnote ids.
+	var $fn_id_prefix = "";
+	
+	# Optional title attribute for footnote links and backlinks.
+	var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
+	var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
+	
+	# Optional class attribute for footnote links and backlinks.
+	var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
+	var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
+	
+	# Predefined abbreviations.
+	var $predef_abbr = array();
+
+
+	function MarkdownExtra_Parser() {
+	#
+	# Constructor function. Initialize the parser object.
+	#
+		# Add extra escapable characters before parent constructor 
+		# initialize the table.
+		$this->escape_chars .= ':|';
+		
+		# Insert extra document, block, and span transformations. 
+		# Parent constructor will do the sorting.
+		$this->document_gamut += array(
+			"doFencedCodeBlocks" => 5,
+			"stripFootnotes"     => 15,
+			"stripAbbreviations" => 25,
+			"appendFootnotes"    => 50,
+			);
+		$this->block_gamut += array(
+			"doFencedCodeBlocks" => 5,
+			"doTables"           => 15,
+			"doDefLists"         => 45,
+			);
+		$this->span_gamut += array(
+			"doFootnotes"        => 5,
+			"doAbbreviations"    => 70,
+			);
+		
+		parent::Markdown_Parser();
+	}
+	
+	
+	# Extra variables used during extra transformations.
+	var $footnotes = array();
+	var $footnotes_ordered = array();
+	var $abbr_desciptions = array();
+	var $abbr_word_re = '';
+	
+	# Give the current footnote number.
+	var $footnote_counter = 1;
+	
+	
+	function setup() {
+	#
+	# Setting up Extra-specific variables.
+	#
+		parent::setup();
+		
+		$this->footnotes = array();
+		$this->footnotes_ordered = array();
+		$this->abbr_desciptions = array();
+		$this->abbr_word_re = '';
+		$this->footnote_counter = 1;
+		
+		foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+			if ($this->abbr_word_re)
+				$this->abbr_word_re .= '|';
+			$this->abbr_word_re .= preg_quote($abbr_word);
+			$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+		}
+	}
+	
+	function teardown() {
+	#
+	# Clearing Extra-specific variables.
+	#
+		$this->footnotes = array();
+		$this->footnotes_ordered = array();
+		$this->abbr_desciptions = array();
+		$this->abbr_word_re = '';
+		
+		parent::teardown();
+	}
+	
+	
+	### HTML Block Parser ###
+	
+	# Tags that are always treated as block tags:
+	var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend';
+	
+	# Tags treated as block tags only if the opening tag is alone on it's line:
+	var $context_block_tags_re = 'script|noscript|math|ins|del';
+	
+	# Tags where markdown="1" default to span mode:
+	var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+	
+	# Tags which must not have their contents modified, no matter where 
+	# they appear:
+	var $clean_tags_re = 'script|math';
+	
+	# Tags that do not need to be closed.
+	var $auto_close_tags_re = 'hr|img';
+	
+
+	function hashHTMLBlocks($text) {
+	#
+	# Hashify HTML Blocks and "clean tags".
+	#
+	# We only want to do this for block-level HTML tags, such as headers,
+	# lists, and tables. That's because we still want to wrap <p>s around
+	# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+	# phrase emphasis, and spans. The list of tags we're looking for is
+	# hard-coded.
+	#
+	# This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+	# _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" 
+	# attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back
+	#  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+	# These two functions are calling each other. It's recursive!
+	#
+		#
+		# Call the HTML-in-Markdown hasher.
+		#
+		list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+		
+		return $text;
+	}
+	function _hashHTMLBlocks_inMarkdown($text, $indent = 0, 
+										$enclosing_tag_re = '', $span = false)
+	{
+	#
+	# Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+	#
+	# *   $indent is the number of space to be ignored when checking for code 
+	#     blocks. This is important because if we don't take the indent into 
+	#     account, something like this (which looks right) won't work as expected:
+	#
+	#     <div>
+	#         <div markdown="1">
+	#         Hello World.  <-- Is this a Markdown code block or text?
+	#         </div>  <-- Is this a Markdown code block or a real tag?
+	#     <div>
+	#
+	#     If you don't like this, just don't indent the tag on which
+	#     you apply the markdown="1" attribute.
+	#
+	# *   If $enclosing_tag_re is not empty, stops at the first unmatched closing 
+	#     tag with that name. Nested tags supported.
+	#
+	# *   If $span is true, text inside must treated as span. So any double 
+	#     newline will be replaced by a single newline so that it does not create 
+	#     paragraphs.
+	#
+	# Returns an array of that form: ( processed text , remaining text )
+	#
+		if ($text === '') return array('', '');
+
+		# Regex to check for the presense of newlines around a block tag.
+		$newline_before_re = '/(?:^\n?|\n\n)*$/';
+		$newline_after_re = 
+			'{
+				^						# Start of text following the tag.
+				(?>[ ]*<!--.*?-->)?		# Optional comment.
+				[ ]*\n					# Must be followed by newline.
+			}xs';
+		
+		# Regex to match any tag.
+		$block_tag_re =
+			'{
+				(					# $2: Capture hole tag.
+					</?					# Any opening or closing tag.
+						(?>				# Tag name.
+							'.$this->block_tags_re.'			|
+							'.$this->context_block_tags_re.'	|
+							'.$this->clean_tags_re.'        	|
+							(?!\s)'.$enclosing_tag_re.'
+						)
+						(?:
+							(?=[\s"\'/a-zA-Z0-9])	# Allowed characters after tag name.
+							(?>
+								".*?"		|	# Double quotes (can contain `>`)
+								\'.*?\'   	|	# Single quotes (can contain `>`)
+								.+?				# Anything but quotes and `>`.
+							)*?
+						)?
+					>					# End of tag.
+				|
+					<!--    .*?     -->	# HTML Comment
+				|
+					<\?.*?\?> | <%.*?%>	# Processing instruction
+				|
+					<!\[CDATA\[.*?\]\]>	# CData Block
+				|
+					# Code span marker
+					`+
+				'. ( !$span ? ' # If not in span.
+				|
+					# Indented code block
+					(?: ^[ ]*\n | ^ | \n[ ]*\n )
+					[ ]{'.($indent+4).'}[^\n]* \n
+					(?>
+						(?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
+					)*
+				|
+					# Fenced code block marker
+					(?> ^ | \n )
+					[ ]{0,'.($indent).'}~~~+[ ]*\n
+				' : '' ). ' # End (if not is span).
+				)
+			}xs';
+
+		
+		$depth = 0;		# Current depth inside the tag tree.
+		$parsed = "";	# Parsed text that will be returned.
+
+		#
+		# Loop through every tag until we find the closing tag of the parent
+		# or loop until reaching the end of text if no parent tag specified.
+		#
+		do {
+			#
+			# Split the text using the first $tag_match pattern found.
+			# Text before  pattern will be first in the array, text after
+			# pattern will be at the end, and between will be any catches made 
+			# by the pattern.
+			#
+			$parts = preg_split($block_tag_re, $text, 2, 
+								PREG_SPLIT_DELIM_CAPTURE);
+			
+			# If in Markdown span mode, add a empty-string span-level hash 
+			# after each newline to prevent triggering any block element.
+			if ($span) {
+				$void = $this->hashPart("", ':');
+				$newline = "$void\n";
+				$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+			}
+			
+			$parsed .= $parts[0]; # Text before current tag.
+			
+			# If end of $text has been reached. Stop loop.
+			if (count($parts) < 3) {
+				$text = "";
+				break;
+			}
+			
+			$tag  = $parts[1]; # Tag to handle.
+			$text = $parts[2]; # Remaining text after current tag.
+			$tag_re = preg_quote($tag); # For use in a regular expression.
+			
+			#
+			# Check for: Code span marker
+			#
+			if ($tag{0} == "`") {
+				# Find corresponding end marker.
+				$tag_re = preg_quote($tag);
+				if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
+					$text, $matches))
+				{
+					# End marker found: pass text unchanged until marker.
+					$parsed .= $tag . $matches[0];
+					$text = substr($text, strlen($matches[0]));
+				}
+				else {
+					# Unmatched marker: just skip it.
+					$parsed .= $tag;
+				}
+			}
+			#
+			# Check for: Fenced code block marker.
+			#
+			else if (preg_match('{^\n?[ ]{0,'.($indent+3).'}~}', $tag)) {
+				# Fenced code block marker: find matching end marker.
+				$tag_re = preg_quote(trim($tag));
+				if (preg_match('{^(?>.*\n)+?[ ]{0,'.($indent).'}'.$tag_re.'[ ]*\n}', $text, 
+					$matches)) 
+				{
+					# End marker found: pass text unchanged until marker.
+					$parsed .= $tag . $matches[0];
+					$text = substr($text, strlen($matches[0]));
+				}
+				else {
+					# No end marker: just skip it.
+					$parsed .= $tag;
+				}
+			}
+			#
+			# Check for: Indented code block.
+			#
+			else if ($tag{0} == "\n" || $tag{0} == " ") {
+				# Indented code block: pass it unchanged, will be handled 
+				# later.
+				$parsed .= $tag;
+			}
+			#
+			# Check for: Opening Block level tag or
+			#            Opening Context Block tag (like ins and del) 
+			#               used as a block tag (tag is alone on it's line).
+			#
+			else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
+				(	preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
+					preg_match($newline_before_re, $parsed) &&
+					preg_match($newline_after_re, $text)	)
+				)
+			{
+				# Need to parse tag and following text using the HTML parser.
+				list($block_text, $text) = 
+					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+				
+				# Make sure it stays outside of any paragraph by adding newlines.
+				$parsed .= "\n\n$block_text\n\n";
+			}
+			#
+			# Check for: Clean tag (like script, math)
+			#            HTML Comments, processing instructions.
+			#
+			else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
+				$tag{1} == '!' || $tag{1} == '?')
+			{
+				# Need to parse tag and following text using the HTML parser.
+				# (don't check for markdown attribute)
+				list($block_text, $text) = 
+					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+				
+				$parsed .= $block_text;
+			}
+			#
+			# Check for: Tag with same name as enclosing tag.
+			#
+			else if ($enclosing_tag_re !== '' &&
+				# Same name as enclosing tag.
+				preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
+			{
+				#
+				# Increase/decrease nested tag count.
+				#
+				if ($tag{1} == '/')						$depth--;
+				else if ($tag{strlen($tag)-2} != '/')	$depth++;
+
+				if ($depth < 0) {
+					#
+					# Going out of parent element. Clean up and break so we
+					# return to the calling function.
+					#
+					$text = $tag . $text;
+					break;
+				}
+				
+				$parsed .= $tag;
+			}
+			else {
+				$parsed .= $tag;
+			}
+		} while ($depth >= 0);
+		
+		return array($parsed, $text);
+	}
+	function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+	#
+	# Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+	#
+	# *   Calls $hash_method to convert any blocks.
+	# *   Stops when the first opening tag closes.
+	# *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+	#     (it is not inside clean tags)
+	#
+	# Returns an array of that form: ( processed text , remaining text )
+	#
+		if ($text === '') return array('', '');
+		
+		# Regex to match `markdown` attribute inside of a tag.
+		$markdown_attr_re = '
+			{
+				\s*			# Eat whitespace before the `markdown` attribute
+				markdown
+				\s*=\s*
+				(?>
+					(["\'])		# $1: quote delimiter		
+					(.*?)		# $2: attribute value
+					\1			# matching delimiter	
+				|
+					([^\s>]*)	# $3: unquoted attribute value
+				)
+				()				# $4: make $3 always defined (avoid warnings)
+			}xs';
+		
+		# Regex to match any tag.
+		$tag_re = '{
+				(					# $2: Capture hole tag.
+					</?					# Any opening or closing tag.
+						[\w:$]+			# Tag name.
+						(?:
+							(?=[\s"\'/a-zA-Z0-9])	# Allowed characters after tag name.
+							(?>
+								".*?"		|	# Double quotes (can contain `>`)
+								\'.*?\'   	|	# Single quotes (can contain `>`)
+								.+?				# Anything but quotes and `>`.
+							)*?
+						)?
+					>					# End of tag.
+				|
+					<!--    .*?     -->	# HTML Comment
+				|
+					<\?.*?\?> | <%.*?%>	# Processing instruction
+				|
+					<!\[CDATA\[.*?\]\]>	# CData Block
+				)
+			}xs';
+		
+		$original_text = $text;		# Save original text in case of faliure.
+		
+		$depth		= 0;	# Current depth inside the tag tree.
+		$block_text	= "";	# Temporary text holder for current text.
+		$parsed		= "";	# Parsed text that will be returned.
+
+		#
+		# Get the name of the starting tag.
+		# (This pattern makes $base_tag_name_re safe without quoting.)
+		#
+		if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+			$base_tag_name_re = $matches[1];
+
+		#
+		# Loop through every tag until we find the corresponding closing tag.
+		#
+		do {
+			#
+			# Split the text using the first $tag_match pattern found.
+			# Text before  pattern will be first in the array, text after
+			# pattern will be at the end, and between will be any catches made 
+			# by the pattern.
+			#
+			$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+			
+			if (count($parts) < 3) {
+				#
+				# End of $text reached with unbalenced tag(s).
+				# In that case, we return original text unchanged and pass the
+				# first character as filtered to prevent an infinite loop in the 
+				# parent function.
+				#
+				return array($original_text{0}, substr($original_text, 1));
+			}
+			
+			$block_text .= $parts[0]; # Text before current tag.
+			$tag         = $parts[1]; # Tag to handle.
+			$text        = $parts[2]; # Remaining text after current tag.
+			
+			#
+			# Check for: Auto-close tag (like <hr/>)
+			#			 Comments and Processing Instructions.
+			#
+			if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
+				$tag{1} == '!' || $tag{1} == '?')
+			{
+				# Just add the tag to the block as if it was text.
+				$block_text .= $tag;
+			}
+			else {
+				#
+				# Increase/decrease nested tag count. Only do so if
+				# the tag's name match base tag's.
+				#
+				if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
+					if ($tag{1} == '/')						$depth--;
+					else if ($tag{strlen($tag)-2} != '/')	$depth++;
+				}
+				
+				#
+				# Check for `markdown="1"` attribute and handle it.
+				#
+				if ($md_attr && 
+					preg_match($markdown_attr_re, $tag, $attr_m) &&
+					preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+				{
+					# Remove `markdown` attribute from opening tag.
+					$tag = preg_replace($markdown_attr_re, '', $tag);
+					
+					# Check if text inside this tag must be parsed in span mode.
+					$this->mode = $attr_m[2] . $attr_m[3];
+					$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+						preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
+					
+					# Calculate indent before tag.
+					if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+						$strlen = $this->utf8_strlen;
+						$indent = $strlen($matches[1], 'UTF-8');
+					} else {
+						$indent = 0;
+					}
+					
+					# End preceding block with this tag.
+					$block_text .= $tag;
+					$parsed .= $this->$hash_method($block_text);
+					
+					# Get enclosing tag name for the ParseMarkdown function.
+					# (This pattern makes $tag_name_re safe without quoting.)
+					preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+					$tag_name_re = $matches[1];
+					
+					# Parse the content using the HTML-in-Markdown parser.
+					list ($block_text, $text)
+						= $this->_hashHTMLBlocks_inMarkdown($text, $indent, 
+							$tag_name_re, $span_mode);
+					
+					# Outdent markdown text.
+					if ($indent > 0) {
+						$block_text = preg_replace("/^[ ]{1,$indent}/m", "", 
+													$block_text);
+					}
+					
+					# Append tag content to parsed text.
+					if (!$span_mode)	$parsed .= "\n\n$block_text\n\n";
+					else				$parsed .= "$block_text";
+					
+					# Start over a new block.
+					$block_text = "";
+				}
+				else $block_text .= $tag;
+			}
+			
+		} while ($depth > 0);
+		
+		#
+		# Hash last block text that wasn't processed inside the loop.
+		#
+		$parsed .= $this->$hash_method($block_text);
+		
+		return array($parsed, $text);
+	}
+
+
+	function hashClean($text) {
+	#
+	# Called whenever a tag must be hashed when a function insert a "clean" tag
+	# in $text, it pass through this function and is automaticaly escaped, 
+	# blocking invalid nested overlap.
+	#
+		return $this->hashPart($text, 'C');
+	}
+
+
+	function doHeaders($text) {
+	#
+	# Redefined to add id attribute support.
+	#
+		# Setext-style headers:
+		#	  Header 1  {#header1}
+		#	  ========
+		#  
+		#	  Header 2  {#header2}
+		#	  --------
+		#
+		$text = preg_replace_callback(
+			'{
+				(^.+?)								# $1: Header text
+				(?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})?	# $2: Id attribute
+				[ ]*\n(=+|-+)[ ]*\n+				# $3: Header footer
+			}mx',
+			array(&$this, '_doHeaders_callback_setext'), $text);
+
+		# atx-style headers:
+		#	# Header 1        {#header1}
+		#	## Header 2       {#header2}
+		#	## Header 2 with closing hashes ##  {#header3}
+		#	...
+		#	###### Header 6   {#header2}
+		#
+		$text = preg_replace_callback('{
+				^(\#{1,6})	# $1 = string of #\'s
+				[ ]*
+				(.+?)		# $2 = Header text
+				[ ]*
+				\#*			# optional closing #\'s (not counted)
+				(?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
+				[ ]*
+				\n+
+			}xm',
+			array(&$this, '_doHeaders_callback_atx'), $text);
+
+		return $text;
+	}
+	function _doHeaders_attr($attr) {
+		if (empty($attr))  return "";
+		return " id=\"$attr\"";
+	}
+	function _doHeaders_callback_setext($matches) {
+		if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
+			return $matches[0];
+		$level = $matches[3]{0} == '=' ? 1 : 2;
+		$attr  = $this->_doHeaders_attr($id =& $matches[2]);
+		$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+	function _doHeaders_callback_atx($matches) {
+		$level = strlen($matches[1]);
+		$attr  = $this->_doHeaders_attr($id =& $matches[3]);
+		$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+
+
+	function doTables($text) {
+	#
+	# Form HTML tables.
+	#
+		$less_than_tab = $this->tab_width - 1;
+		#
+		# Find tables with leading pipe.
+		#
+		#	| Header 1 | Header 2
+		#	| -------- | --------
+		#	| Cell 1   | Cell 2
+		#	| Cell 3   | Cell 4
+		#
+		$text = preg_replace_callback('
+			{
+				^							# Start of a line
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				[|]							# Optional leading pipe (present)
+				(.+) \n						# $1: Header row (at least one pipe)
+				
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				[|] ([ ]*[-:]+[-| :]*) \n	# $2: Header underline
+				
+				(							# $3: Cells
+					(?>
+						[ ]*				# Allowed whitespace.
+						[|] .* \n			# Row content.
+					)*
+				)
+				(?=\n|\Z)					# Stop at final double newline.
+			}xm',
+			array(&$this, '_doTable_leadingPipe_callback'), $text);
+		
+		#
+		# Find tables without leading pipe.
+		#
+		#	Header 1 | Header 2
+		#	-------- | --------
+		#	Cell 1   | Cell 2
+		#	Cell 3   | Cell 4
+		#
+		$text = preg_replace_callback('
+			{
+				^							# Start of a line
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				(\S.*[|].*) \n				# $1: Header row (at least one pipe)
+				
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				([-:]+[ ]*[|][-| :]*) \n	# $2: Header underline
+				
+				(							# $3: Cells
+					(?>
+						.* [|] .* \n		# Row content
+					)*
+				)
+				(?=\n|\Z)					# Stop at final double newline.
+			}xm',
+			array(&$this, '_DoTable_callback'), $text);
+
+		return $text;
+	}
+	function _doTable_leadingPipe_callback($matches) {
+		$head		= $matches[1];
+		$underline	= $matches[2];
+		$content	= $matches[3];
+		
+		# Remove leading pipe for each row.
+		$content	= preg_replace('/^ *[|]/m', '', $content);
+		
+		return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+	}
+	function _doTable_callback($matches) {
+		$head		= $matches[1];
+		$underline	= $matches[2];
+		$content	= $matches[3];
+
+		# Remove any tailing pipes for each line.
+		$head		= preg_replace('/[|] *$/m', '', $head);
+		$underline	= preg_replace('/[|] *$/m', '', $underline);
+		$content	= preg_replace('/[|] *$/m', '', $content);
+		
+		# Reading alignement from header underline.
+		$separators	= preg_split('/ *[|] */', $underline);
+		foreach ($separators as $n => $s) {
+			if (preg_match('/^ *-+: *$/', $s))		$attr[$n] = ' align="right"';
+			else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
+			else if (preg_match('/^ *:-+ *$/', $s))	$attr[$n] = ' align="left"';
+			else									$attr[$n] = '';
+		}
+		
+		# Parsing span elements, including code spans, character escapes, 
+		# and inline HTML tags, so that pipes inside those gets ignored.
+		$head		= $this->parseSpan($head);
+		$headers	= preg_split('/ *[|] */', $head);
+		$col_count	= count($headers);
+		
+		# Write column headers.
+		$text = "<table>\n";
+		$text .= "<thead>\n";
+		$text .= "<tr>\n";
+		foreach ($headers as $n => $header)
+			$text .= "  <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
+		$text .= "</tr>\n";
+		$text .= "</thead>\n";
+		
+		# Split content by row.
+		$rows = explode("\n", trim($content, "\n"));
+		
+		$text .= "<tbody>\n";
+		foreach ($rows as $row) {
+			# Parsing span elements, including code spans, character escapes, 
+			# and inline HTML tags, so that pipes inside those gets ignored.
+			$row = $this->parseSpan($row);
+			
+			# Split row by cell.
+			$row_cells = preg_split('/ *[|] */', $row, $col_count);
+			$row_cells = array_pad($row_cells, $col_count, '');
+			
+			$text .= "<tr>\n";
+			foreach ($row_cells as $n => $cell)
+				$text .= "  <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
+			$text .= "</tr>\n";
+		}
+		$text .= "</tbody>\n";
+		$text .= "</table>";
+		
+		return $this->hashBlock($text) . "\n";
+	}
+
+	
+	function doDefLists($text) {
+	#
+	# Form HTML definition lists.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Re-usable pattern to match any entire dl list:
+		$whole_list_re = '(?>
+			(								# $1 = whole list
+			  (								# $2
+				[ ]{0,'.$less_than_tab.'}
+				((?>.*\S.*\n)+)				# $3 = defined term
+				\n?
+				[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+			  )
+			  (?s:.+?)
+			  (								# $4
+				  \z
+				|
+				  \n{2,}
+				  (?=\S)
+				  (?!						# Negative lookahead for another term
+					[ ]{0,'.$less_than_tab.'}
+					(?: \S.*\n )+?			# defined term
+					\n?
+					[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+				  )
+				  (?!						# Negative lookahead for another definition
+					[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+				  )
+			  )
+			)
+		)'; // mx
+
+		$text = preg_replace_callback('{
+				(?>\A\n?|(?<=\n\n))
+				'.$whole_list_re.'
+			}mx',
+			array(&$this, '_doDefLists_callback'), $text);
+
+		return $text;
+	}
+	function _doDefLists_callback($matches) {
+		# Re-usable patterns to match list item bullets and number markers:
+		$list = $matches[1];
+		
+		# Turn double returns into triple returns, so that we can make a
+		# paragraph for the last item in a list, if necessary:
+		$result = trim($this->processDefListItems($list));
+		$result = "<dl>\n" . $result . "\n</dl>";
+		return $this->hashBlock($result) . "\n\n";
+	}
+
+
+	function processDefListItems($list_str) {
+	#
+	#	Process the contents of a single definition list, splitting it
+	#	into individual term and definition list items.
+	#
+		$less_than_tab = $this->tab_width - 1;
+		
+		# trim trailing blank lines:
+		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+		# Process definition terms.
+		$list_str = preg_replace_callback('{
+			(?>\A\n?|\n\n+)					# leading line
+			(								# definition terms = $1
+				[ ]{0,'.$less_than_tab.'}	# leading whitespace
+				(?![:][ ]|[ ])				# negative lookahead for a definition 
+											#   mark (colon) or more whitespace.
+				(?> \S.* \n)+?				# actual term (not whitespace).	
+			)			
+			(?=\n?[ ]{0,3}:[ ])				# lookahead for following line feed 
+											#   with a definition mark.
+			}xm',
+			array(&$this, '_processDefListItems_callback_dt'), $list_str);
+
+		# Process actual definitions.
+		$list_str = preg_replace_callback('{
+			\n(\n+)?						# leading line = $1
+			(								# marker space = $2
+				[ ]{0,'.$less_than_tab.'}	# whitespace before colon
+				[:][ ]+						# definition mark (colon)
+			)
+			((?s:.+?))						# definition text = $3
+			(?= \n+ 						# stop at next definition mark,
+				(?:							# next term or end of text
+					[ ]{0,'.$less_than_tab.'} [:][ ]	|
+					<dt> | \z
+				)						
+			)					
+			}xm',
+			array(&$this, '_processDefListItems_callback_dd'), $list_str);
+
+		return $list_str;
+	}
+	function _processDefListItems_callback_dt($matches) {
+		$terms = explode("\n", trim($matches[1]));
+		$text = '';
+		foreach ($terms as $term) {
+			$term = $this->runSpanGamut(trim($term));
+			$text .= "\n<dt>" . $term . "</dt>";
+		}
+		return $text . "\n";
+	}
+	function _processDefListItems_callback_dd($matches) {
+		$leading_line	= $matches[1];
+		$marker_space	= $matches[2];
+		$def			= $matches[3];
+
+		if ($leading_line || preg_match('/\n{2,}/', $def)) {
+			# Replace marker with the appropriate whitespace indentation
+			$def = str_repeat(' ', strlen($marker_space)) . $def;
+			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+			$def = "\n". $def ."\n";
+		}
+		else {
+			$def = rtrim($def);
+			$def = $this->runSpanGamut($this->outdent($def));
+		}
+
+		return "\n<dd>" . $def . "</dd>\n";
+	}
+
+
+	function doFencedCodeBlocks($text) {
+	#
+	# Adding the fenced code block syntax to regular Markdown:
+	#
+	# ~~~
+	# Code block
+	# ~~~
+	#
+		$less_than_tab = $this->tab_width;
+		
+		$text = preg_replace_callback('{
+				(?:\n|\A)
+				# 1: Opening marker
+				(
+					~{3,} # Marker: three tilde or more.
+				)
+				[ ]* \n # Whitespace and newline following marker.
+				
+				# 2: Content
+				(
+					(?>
+						(?!\1 [ ]* \n)	# Not a closing marker.
+						.*\n+
+					)+
+				)
+				
+				# Closing marker.
+				\1 [ ]* \n
+			}xm',
+			array(&$this, '_doFencedCodeBlocks_callback'), $text);
+
+		return $text;
+	}
+	function _doFencedCodeBlocks_callback($matches) {
+		$codeblock = $matches[2];
+		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+		$codeblock = preg_replace_callback('/^\n+/',
+			array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
+		$codeblock = "<pre><code>$codeblock</code></pre>";
+		return "\n\n".$this->hashBlock($codeblock)."\n\n";
+	}
+	function _doFencedCodeBlocks_newlines($matches) {
+		return str_repeat("<br$this->empty_element_suffix", 
+			strlen($matches[0]));
+	}
+
+
+	#
+	# Redefining emphasis markers so that emphasis by underscore does not
+	# work in the middle of a word.
+	#
+	var $em_relist = array(
+		''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
+		'_' => '(?<=\S|^)(?<!_)_(?![a-zA-Z0-9_])',
+		);
+	var $strong_relist = array(
+		''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
+		'__' => '(?<=\S|^)(?<!_)__(?![a-zA-Z0-9_])',
+		);
+	var $em_strong_relist = array(
+		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
+		'___' => '(?<=\S|^)(?<!_)___(?![a-zA-Z0-9_])',
+		);
+
+
+	function formParagraphs($text) {
+	#
+	#	Params:
+	#		$text - string to process with html <p> tags
+	#
+		# Strip leading and trailing lines:
+		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
+		
+		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+		#
+		# Wrap <p> tags and unhashify HTML blocks
+		#
+		foreach ($grafs as $key => $value) {
+			$value = trim($this->runSpanGamut($value));
+			
+			# Check if this should be enclosed in a paragraph.
+			# Clean tag hashes & block tag hashes are left alone.
+			$is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+			
+			if ($is_p) {
+				$value = "<p>$value</p>";
+			}
+			$grafs[$key] = $value;
+		}
+		
+		# Join grafs in one text, then unhash HTML tags. 
+		$text = implode("\n\n", $grafs);
+		
+		# Finish by removing any tag hashes still present in $text.
+		$text = $this->unhash($text);
+		
+		return $text;
+	}
+	
+	
+	### Footnotes
+	
+	function stripFootnotes($text) {
+	#
+	# Strips link definitions from text, stores the URLs and titles in
+	# hash references.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Link defs are in the form: [^id]: url "optional title"
+		$text = preg_replace_callback('{
+			^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?:	# note_id = $1
+			  [ ]*
+			  \n?					# maybe *one* newline
+			(						# text = $2 (no blank lines allowed)
+				(?:					
+					.+				# actual text
+				|
+					\n				# newlines but 
+					(?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
+					(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed 
+									# by non-indented content
+				)*
+			)		
+			}xm',
+			array(&$this, '_stripFootnotes_callback'),
+			$text);
+		return $text;
+	}
+	function _stripFootnotes_callback($matches) {
+		$note_id = $this->fn_id_prefix . $matches[1];
+		$this->footnotes[$note_id] = $this->outdent($matches[2]);
+		return ''; # String that will replace the block
+	}
+
+
+	function doFootnotes($text) {
+	#
+	# Replace footnote references in $text [^id] with a special text-token 
+	# which will be replaced by the actual footnote marker in appendFootnotes.
+	#
+		if (!$this->in_anchor) {
+			$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+		}
+		return $text;
+	}
+
+	
+	function appendFootnotes($text) {
+	#
+	# Append footnote list to text.
+	#
+		$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
+			array(&$this, '_appendFootnotes_callback'), $text);
+	
+		if (!empty($this->footnotes_ordered)) {
+			$text .= "\n\n";
+			$text .= "<div class=\"footnotes\">\n";
+			$text .= "<hr". $this->empty_element_suffix ."\n";
+			$text .= "<ol>\n\n";
+			
+			$attr = " rev=\"footnote\"";
+			if ($this->fn_backlink_class != "") {
+				$class = $this->fn_backlink_class;
+				$class = $this->encodeAttribute($class);
+				$attr .= " class=\"$class\"";
+			}
+			if ($this->fn_backlink_title != "") {
+				$title = $this->fn_backlink_title;
+				$title = $this->encodeAttribute($title);
+				$attr .= " title=\"$title\"";
+			}
+			$num = 0;
+			
+			while (!empty($this->footnotes_ordered)) {
+				$footnote = reset($this->footnotes_ordered);
+				$note_id = key($this->footnotes_ordered);
+				unset($this->footnotes_ordered[$note_id]);
+				
+				$footnote .= "\n"; # Need to append newline before parsing.
+				$footnote = $this->runBlockGamut("$footnote\n");				
+				$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
+					array(&$this, '_appendFootnotes_callback'), $footnote);
+				
+				$attr = str_replace("%%", ++$num, $attr);
+				$note_id = $this->encodeAttribute($note_id);
+				
+				# Add backlink to last paragraph; create new paragraph if needed.
+				$backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
+				if (preg_match('{</p>$}', $footnote)) {
+					$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
+				} else {
+					$footnote .= "\n\n<p>$backlink</p>";
+				}
+				
+				$text .= "<li id=\"fn:$note_id\">\n";
+				$text .= $footnote . "\n";
+				$text .= "</li>\n\n";
+			}
+			
+			$text .= "</ol>\n";
+			$text .= "</div>";
+		}
+		return $text;
+	}
+	function _appendFootnotes_callback($matches) {
+		$node_id = $this->fn_id_prefix . $matches[1];
+		
+		# Create footnote marker only if it has a corresponding footnote *and*
+		# the footnote hasn't been used by another marker.
+		if (isset($this->footnotes[$node_id])) {
+			# Transfert footnote content to the ordered list.
+			$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+			unset($this->footnotes[$node_id]);
+			
+			$num = $this->footnote_counter++;
+			$attr = " rel=\"footnote\"";
+			if ($this->fn_link_class != "") {
+				$class = $this->fn_link_class;
+				$class = $this->encodeAttribute($class);
+				$attr .= " class=\"$class\"";
+			}
+			if ($this->fn_link_title != "") {
+				$title = $this->fn_link_title;
+				$title = $this->encodeAttribute($title);
+				$attr .= " title=\"$title\"";
+			}
+			
+			$attr = str_replace("%%", $num, $attr);
+			$node_id = $this->encodeAttribute($node_id);
+			
+			return
+				"<sup id=\"fnref:$node_id\">".
+				"<a href=\"#fn:$node_id\"$attr>$num</a>".
+				"</sup>";
+		}
+		
+		return "[^".$matches[1]."]";
+	}
+		
+	
+	### Abbreviations ###
+	
+	function stripAbbreviations($text) {
+	#
+	# Strips abbreviations from text, stores titles in hash references.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Link defs are in the form: [id]*: url "optional title"
+		$text = preg_replace_callback('{
+			^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?:	# abbr_id = $1
+			(.*)					# text = $2 (no blank lines allowed)	
+			}xm',
+			array(&$this, '_stripAbbreviations_callback'),
+			$text);
+		return $text;
+	}
+	function _stripAbbreviations_callback($matches) {
+		$abbr_word = $matches[1];
+		$abbr_desc = $matches[2];
+		if ($this->abbr_word_re)
+			$this->abbr_word_re .= '|';
+		$this->abbr_word_re .= preg_quote($abbr_word);
+		$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+		return ''; # String that will replace the block
+	}
+	
+	
+	function doAbbreviations($text) {
+	#
+	# Find defined abbreviations in text and wrap them in <abbr> elements.
+	#
+		if ($this->abbr_word_re) {
+			// cannot use the /x modifier because abbr_word_re may 
+			// contain significant spaces:
+			$text = preg_replace_callback('{'.
+				'(?<![\w\x1A])'.
+				'(?:'.$this->abbr_word_re.')'.
+				'(?![\w\x1A])'.
+				'}', 
+				array(&$this, '_doAbbreviations_callback'), $text);
+		}
+		return $text;
+	}
+	function _doAbbreviations_callback($matches) {
+		$abbr = $matches[0];
+		if (isset($this->abbr_desciptions[$abbr])) {
+			$desc = $this->abbr_desciptions[$abbr];
+			if (empty($desc)) {
+				return $this->hashPart("<abbr>$abbr</abbr>");
+			} else {
+				$desc = $this->encodeAttribute($desc);
+				return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
+			}
+		} else {
+			return $matches[0];
+		}
+	}
+
+}
+
+
+/*
+
+PHP Markdown Extra
+==================
+
+Description
+-----------
+
+This is a PHP port of the original Markdown formatter written in Perl 
+by John Gruber. This special "Extra" version of PHP Markdown features 
+further enhancements to the syntax for making additional constructs 
+such as tables and definition list.
+
+Markdown is a text-to-HTML filter; it translates an easy-to-read /
+easy-to-write structured text format into HTML. Markdown's text format
+is most similar to that of plain text email, and supports features such
+as headers, *emphasis*, code blocks, blockquotes, and links.
+
+Markdown's syntax is designed not as a generic markup language, but
+specifically to serve as a front-end to (X)HTML. You can use span-level
+HTML tags anywhere in a Markdown document, and you can use block level
+HTML tags (like <div> and <table> as well).
+
+For more information about Markdown's syntax, see:
+
+<http://daringfireball.net/projects/markdown/>
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+
+<[email protected]>
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output Markdown actually produced.
+
+
+Version History
+--------------- 
+
+See the readme file for detailed release notes for this version.
+
+
+Copyright and License
+---------------------
+
+PHP Markdown & Extra  
+Copyright (c) 2004-2009 Michel Fortin  
+<http://michelf.com/>  
+All rights reserved.
+
+Based on Markdown  
+Copyright (c) 2003-2006 John Gruber   
+<http://daringfireball.net/>   
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+*	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+*	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+*	Neither the name "Markdown" nor the names of its contributors may
+	be used to endorse or promote products derived from this software
+	without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as
+is" and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed. In no event shall the copyright owner
+or contributors be liable for any direct, indirect, incidental, special,
+exemplary, or consequential damages (including, but not limited to,
+procurement of substitute goods or services; loss of use, data, or
+profits; or business interruption) however caused and on any theory of
+liability, whether in contract, strict liability, or tort (including
+negligence or otherwise) arising in any way out of the use of this
+software, even if advised of the possibility of such damage.
+
+*/
+?>

+ 85 - 0
php-laravel/bundles/docs/routes.php

@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * Load the Markdown library.
+ */
+require_once __DIR__.'/libraries/markdown.php';
+
+/**
+ * Get the root path for the documentation Markdown.
+ *
+ * @return string
+ */
+function doc_root()
+{
+	return path('sys').'documentation/';
+}
+
+/**
+ * Get the parsed Markdown contents of a given page.
+ *
+ * @param  string  $page
+ * @return string
+ */
+function document($page)
+{
+	return Markdown(file_get_contents(doc_root().$page.'.md'));
+}
+
+/**
+ * Determine if a documentation page exists.
+ *
+ * @param  string  $page
+ * @return bool
+ */
+function document_exists($page)
+{
+	return file_exists(doc_root().$page.'.md');
+}
+
+/**
+ * Attach the sidebar to the documentation template.
+ */
+View::composer('docs::template', function($view)
+{
+	$view->with('sidebar', document('contents'));
+});
+
+/**
+ * Handle the documentation homepage.
+ *
+ * This page contains the "introduction" to Laravel.
+ */
+Route::get('(:bundle)', function()
+{
+	return View::make('docs::page')->with('content', document('home'));
+});
+
+/**
+ * Handle documentation routes for sections and pages.
+ *
+ * @param  string  $section
+ * @param  string  $page
+ * @return mixed
+ */
+Route::get('(:bundle)/(:any)/(:any?)', function($section, $page = null)
+{
+	$file = rtrim(implode('/', func_get_args()), '/');
+
+	// If no page was specified, but a "home" page exists for the section,
+	// we'll set the file to the home page so that the proper page is
+	// displayed back out to the client for the requested doc page.
+	if (is_null($page) and document_exists($file.'/home'))
+	{
+		$file .= '/home';
+	}
+
+	if (document_exists($file))
+	{
+		return View::make('docs::page')->with('content', document($file));
+	}
+	else
+	{
+		return Response::error('404');
+	}
+});

+ 5 - 0
php-laravel/bundles/docs/views/page.blade.php

@@ -0,0 +1,5 @@
+@layout('docs::template')
+
+@section('content')
+	{{ $content }}
+@endsection

+ 34 - 0
php-laravel/bundles/docs/views/template.blade.php

@@ -0,0 +1,34 @@
+<!doctype html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+	<title>Laravel: A Framework For Web Artisans</title>
+	<meta name="viewport" content="width=device-width">
+
+	{{ HTML::style(URL::$base.'/laravel/css/style.css') }}
+	{{ HTML::script(URL::$base.'/laravel/js/modernizr-2.5.3.min.js') }}
+</head>
+<body onload="prettyPrint()">
+	<div class="wrapper">
+		<header>
+			<h1>Laravel</h1>
+			<h2>A Framework For Web Artisans</h2>
+
+			<p class="intro-text">
+			</p>
+		</header>
+		<div role="main" class="main">
+			<aside class="sidebar">
+				{{ $sidebar }}
+			</aside>
+			<div class="content">
+				@yield('content')
+			</div>
+		</div>
+	</div>
+	{{ HTML::script('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js') }}
+	{{ HTML::script(URL::$base.'/laravel/js/prettify.js') }}
+	{{ HTML::script(URL::$base.'/laravel/js/scroll.js') }}
+</body>
+</html>

+ 125 - 0
php-laravel/deploy/nginx.conf

@@ -0,0 +1,125 @@
+#user  nobody;
+worker_processes  8;
+
+#error_log  logs/error.log;
+#error_log  logs/error.log  notice;
+#error_log  logs/error.log  info;
+
+#pid        logs/nginx.pid;
+
+
+events {
+    worker_connections  1024;
+}
+
+
+http {
+    include       /usr/local/nginx/conf/mime.types;
+    default_type  application/octet-stream;
+
+    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+    #                  '$status $body_bytes_sent "$http_referer" '
+    #                  '"$http_user_agent" "$http_x_forwarded_for"';
+
+    #access_log  logs/access.log  main;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    #keepalive_timeout  0;
+    keepalive_timeout  65;
+
+    #gzip  on;
+
+    server {
+        listen       8080;
+        server_name  localhost;
+
+        #charset koi8-r;
+
+        #access_log  logs/host.access.log  main;
+
+        #location / {
+        #    root   html;
+        #    index  index.html index.htm;
+        #}
+
+        #error_page  404              /404.html;
+
+        # redirect server error pages to the static page /50x.html
+        #
+        #error_page   500 502 503 504  /50x.html;
+        #location = /50x.html {
+        #    root   html;
+        #}
+
+        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
+        #
+        #location ~ \.php$ {
+        #    proxy_pass   http://127.0.0.1;
+        #}
+
+        root /home/ubuntu/FrameworkBenchmarks/php-laravel/public/;
+        index  index.php;
+
+        location / {
+            try_files $uri $uri/ /index.php?$uri&$args;
+        }
+
+        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+        #
+        location ~ \.php$ {
+            try_files $uri =404;
+            fastcgi_pass   127.0.0.1:9001;
+            fastcgi_index  index.php;
+#            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
+            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
+            include        /usr/local/nginx/conf/fastcgi_params;
+        }
+
+        # deny access to .htaccess files, if Apache's document root
+        # concurs with nginx's one
+        #
+        #location ~ /\.ht {
+        #    deny  all;
+        #}
+    }
+
+
+    # another virtual host using mix of IP-, name-, and port-based configuration
+    #
+    #server {
+    #    listen       8000;
+    #    listen       somename:8080;
+    #    server_name  somename  alias  another.alias;
+
+    #    location / {
+    #        root   html;
+    #        index  index.html index.htm;
+    #    }
+    #}
+
+
+    # HTTPS server
+    #
+    #server {
+    #    listen       443;
+    #    server_name  localhost;
+
+    #    ssl                  on;
+    #    ssl_certificate      cert.pem;
+    #    ssl_certificate_key  cert.key;
+
+    #    ssl_session_timeout  5m;
+
+    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
+    #    ssl_ciphers  HIGH:!aNULL:!MD5;
+    #    ssl_prefer_server_ciphers   on;
+
+    #    location / {
+    #        root   html;
+    #        index  index.html index.htm;
+    #    }
+    #}
+
+}

+ 9 - 0
php-laravel/deploy/php-laravel

@@ -0,0 +1,9 @@
+<VirtualHost *:8080>
+  Alias /php-laravel/ "/home/ubuntu/FrameworkBenchmarks/php-laravel/public/"
+  <Directory /home/ubuntu/FrameworkBenchmarks/php-laravel/public/>
+          Options Indexes FollowSymLinks MultiViews
+          #AllowOverride None
+          Order allow,deny
+          allow from all
+  </Directory>
+</VirtualHost>

+ 356 - 0
php-laravel/laravel/asset.php

@@ -0,0 +1,356 @@
+<?php namespace Laravel;
+
+class Asset {
+
+	/**
+	 * All of the instantiated asset containers.
+	 *
+	 * @var array
+	 */
+	public static $containers = array();
+
+	/**
+	 * Get an asset container instance.
+	 *
+	 * <code>
+	 *		// Get the default asset container
+	 *		$container = Asset::container();
+	 *
+	 *		// Get a named asset container
+	 *		$container = Asset::container('footer');
+	 * </code>
+	 *
+	 * @param  string            $container
+	 * @return Asset_Container
+	 */
+	public static function container($container = 'default')
+	{
+		if ( ! isset(static::$containers[$container]))
+		{
+			static::$containers[$container] = new Asset_Container($container);
+		}
+
+		return static::$containers[$container];
+	}
+
+	/**
+	 * Magic Method for calling methods on the default container.
+	 *
+	 * <code>
+	 *		// Call the "styles" method on the default container
+	 *		echo Asset::styles();
+	 *
+	 *		// Call the "add" method on the default container
+	 *		Asset::add('jquery', 'js/jquery.js');
+	 * </code>
+	 */
+	public static function __callStatic($method, $parameters)
+	{
+		return call_user_func_array(array(static::container(), $method), $parameters);
+	}
+
+}
+
+class Asset_Container {
+
+	/**
+	 * The asset container name.
+	 *
+	 * @var string
+	 */
+	public $name;
+
+	/**
+	 * The bundle that the assets belong to.
+	 *
+	 * @var string
+	 */
+	public $bundle = DEFAULT_BUNDLE;
+
+	/**
+	 * All of the registered assets.
+	 *
+	 * @var array
+	 */
+	public $assets = array();
+
+	/**
+	 * Create a new asset container instance.
+	 *
+	 * @param  string  $name
+	 * @return void
+	 */
+	public function __construct($name)
+	{
+		$this->name = $name;
+	}
+
+	/**
+	 * Add an asset to the container.
+	 *
+	 * The extension of the asset source will be used to determine the type of
+	 * asset being registered (CSS or JavaScript). When using a non-standard
+	 * extension, the style/script methods may be used to register assets.
+	 *
+	 * <code>
+	 *		// Add an asset to the container
+	 *		Asset::container()->add('jquery', 'js/jquery.js');
+	 *
+	 *		// Add an asset that has dependencies on other assets
+	 *		Asset::add('jquery', 'js/jquery.js', 'jquery-ui');
+	 *
+	 *		// Add an asset that should have attributes applied to its tags
+	 *		Asset::add('jquery', 'js/jquery.js', null, array('defer'));
+	 * </code>
+	 *
+	 * @param  string  $name
+	 * @param  string  $source
+	 * @param  array   $dependencies
+	 * @param  array   $attributes
+	 * @return Asset_Container
+	 */
+	public function add($name, $source, $dependencies = array(), $attributes = array())
+	{
+		$type = (pathinfo($source, PATHINFO_EXTENSION) == 'css') ? 'style' : 'script';
+
+		return $this->$type($name, $source, $dependencies, $attributes);
+	}
+
+	/**
+	 * Add a CSS file to the registered assets.
+	 *
+	 * @param  string           $name
+	 * @param  string           $source
+	 * @param  array            $dependencies
+	 * @param  array            $attributes
+	 * @return Asset_Container
+	 */
+	public function style($name, $source, $dependencies = array(), $attributes = array())
+	{
+		if ( ! array_key_exists('media', $attributes))
+		{
+			$attributes['media'] = 'all';
+		}
+
+		$this->register('style', $name, $source, $dependencies, $attributes);
+
+		return $this;
+	}
+
+	/**
+	 * Add a JavaScript file to the registered assets.
+	 *
+	 * @param  string           $name
+	 * @param  string           $source
+	 * @param  array            $dependencies
+	 * @param  array            $attributes
+	 * @return Asset_Container
+	 */
+	public function script($name, $source, $dependencies = array(), $attributes = array())
+	{
+		$this->register('script', $name, $source, $dependencies, $attributes);
+
+		return $this;
+	}
+
+	/**
+	 * Returns the full-path for an asset.
+	 *
+	 * @param  string  $source
+	 * @return string
+	 */
+	public function path($source)
+	{
+		return Bundle::assets($this->bundle).$source;
+	}
+
+	/**
+	 * Set the bundle that the container's assets belong to.
+	 *
+	 * @param  string           $bundle
+	 * @return Asset_Container
+	 */
+	public function bundle($bundle)
+	{
+		$this->bundle = $bundle;
+		return $this;
+	}
+
+	/**
+	 * Add an asset to the array of registered assets.
+	 *
+	 * @param  string  $type
+	 * @param  string  $name
+	 * @param  string  $source
+	 * @param  array   $dependencies
+	 * @param  array   $attributes
+	 * @return void
+	 */
+	protected function register($type, $name, $source, $dependencies, $attributes)
+	{
+		$dependencies = (array) $dependencies;
+
+		$attributes = (array) $attributes;
+
+		$this->assets[$type][$name] = compact('source', 'dependencies', 'attributes');
+	}
+
+	/**
+	 * Get the links to all of the registered CSS assets.
+	 *
+	 * @return  string
+	 */
+	public function styles()
+	{
+		return $this->group('style');
+	}
+
+	/**
+	 * Get the links to all of the registered JavaScript assets.
+	 *
+	 * @return  string
+	 */
+	public function scripts()
+	{
+		return $this->group('script');
+	}
+
+	/**
+	 * Get all of the registered assets for a given type / group.
+	 *
+	 * @param  string  $group
+	 * @return string
+	 */
+	protected function group($group)
+	{
+		if ( ! isset($this->assets[$group]) or count($this->assets[$group]) == 0) return '';
+
+		$assets = '';
+
+		foreach ($this->arrange($this->assets[$group]) as $name => $data)
+		{
+			$assets .= $this->asset($group, $name);
+		}
+		
+		return $assets;
+	}
+
+	/**
+	 * Get the HTML link to a registered asset.
+	 *
+	 * @param  string  $group
+	 * @param  string  $name
+	 * @return string
+	 */
+	protected function asset($group, $name)
+	{
+		if ( ! isset($this->assets[$group][$name])) return '';
+
+		$asset = $this->assets[$group][$name];
+
+		// If the bundle source is not a complete URL, we will go ahead and prepend
+		// the bundle's asset path to the source provided with the asset. This will
+		// ensure that we attach the correct path to the asset.
+		if (filter_var($asset['source'], FILTER_VALIDATE_URL) === false)
+		{
+			$asset['source'] = $this->path($asset['source']);
+		}
+
+		return HTML::$group($asset['source'], $asset['attributes']);
+	}
+
+	/**
+	 * Sort and retrieve assets based on their dependencies
+	 *
+	 * @param   array  $assets
+	 * @return  array
+	 */
+	protected function arrange($assets)
+	{
+		list($original, $sorted) = array($assets, array());
+
+		while (count($assets) > 0)
+		{
+			foreach ($assets as $asset => $value)
+			{
+				$this->evaluate_asset($asset, $value, $original, $sorted, $assets);
+			}
+		}
+		
+		return $sorted;
+	}
+
+	/**
+	 * Evaluate an asset and its dependencies.
+	 *
+	 * @param  string  $asset
+	 * @param  string  $value
+	 * @param  array   $original
+	 * @param  array   $sorted
+	 * @param  array   $assets
+	 * @return void
+	 */
+	protected function evaluate_asset($asset, $value, $original, &$sorted, &$assets)
+	{
+		// If the asset has no more dependencies, we can add it to the sorted list
+		// and remove it from the array of assets. Otherwise, we will not verify
+		// the asset's dependencies and determine if they've been sorted.
+		if (count($assets[$asset]['dependencies']) == 0)
+		{
+			$sorted[$asset] = $value;
+
+			unset($assets[$asset]);
+		}
+		else
+		{
+			foreach ($assets[$asset]['dependencies'] as $key => $dependency)
+			{
+				if ( ! $this->dependency_is_valid($asset, $dependency, $original, $assets))
+				{
+					unset($assets[$asset]['dependencies'][$key]);
+
+					continue;
+				}
+
+				// If the dependency has not yet been added to the sorted list, we can not
+				// remove it from this asset's array of dependencies. We'll try again on
+				// the next trip through the loop.
+				if ( ! isset($sorted[$dependency])) continue;
+
+				unset($assets[$asset]['dependencies'][$key]);
+			}
+		}		
+	}
+
+	/**
+	 * Verify that an asset's dependency is valid.
+	 *
+	 * A dependency is considered valid if it exists, is not a circular reference, and is
+	 * not a reference to the owning asset itself. If the dependency doesn't exist, no
+	 * error or warning will be given. For the other cases, an exception is thrown.
+	 *
+	 * @param  string  $asset
+	 * @param  string  $dependency
+	 * @param  array   $original
+	 * @param  array   $assets
+	 * @return bool
+	 */
+	protected function dependency_is_valid($asset, $dependency, $original, $assets)
+	{
+		if ( ! isset($original[$dependency]))
+		{
+			return false;
+		}
+		elseif ($dependency === $asset)
+		{
+			throw new \Exception("Asset [$asset] is dependent on itself.");
+		}
+		elseif (isset($assets[$dependency]) and in_array($asset, $assets[$dependency]['dependencies']))
+		{
+			throw new \Exception("Assets [$asset] and [$dependency] have a circular dependency.");
+		}
+
+		return true;
+	}
+
+}

+ 93 - 0
php-laravel/laravel/auth.php

@@ -0,0 +1,93 @@
+<?php namespace Laravel; use Closure;
+
+class Auth {
+
+	/**
+	 * The currently active authentication drivers.
+	 *
+	 * @var array
+	 */
+	public static $drivers = array();
+
+	/**
+	 * The third-party driver registrar.
+	 *
+	 * @var array
+	 */
+	public static $registrar = array();
+
+	/**
+	 * Get an authentication driver instance.
+	 *
+	 * @param  string  $driver
+	 * @return Driver
+	 */
+	public static function driver($driver = null)
+	{
+		if (is_null($driver)) $driver = Config::get('auth.driver');
+
+		if ( ! isset(static::$drivers[$driver]))
+		{
+			static::$drivers[$driver] = static::factory($driver);
+		}
+
+		return static::$drivers[$driver];
+	}
+
+	/**
+	 * Create a new authentication driver instance.
+	 *
+	 * @param  string  $driver
+	 * @return Driver
+	 */
+	protected static function factory($driver)
+	{
+		if (isset(static::$registrar[$driver]))
+		{
+			$resolver = static::$registrar[$driver];
+
+			return $resolver();
+		}
+
+		switch ($driver)
+		{
+			case 'fluent':
+				return new Auth\Drivers\Fluent(Config::get('auth.table'));
+
+			case 'eloquent':
+				return new Auth\Drivers\Eloquent(Config::get('auth.model'));
+
+			default:
+				throw new \Exception("Auth driver {$driver} is not supported.");
+		}
+	}
+
+	/**
+	 * Register a third-party authentication driver.
+	 *
+	 * @param  string   $driver
+	 * @param  Closure  $resolver
+	 * @return void
+	 */
+	public static function extend($driver, Closure $resolver)
+	{
+		static::$registrar[$driver] = $resolver;
+	}
+
+	/**
+	 * Magic Method for calling the methods on the default cache driver.
+	 *
+	 * <code>
+	 *		// Call the "user" method on the default auth driver
+	 *		$user = Auth::user();
+	 *
+	 *		// Call the "check" method on the default auth driver
+	 *		Auth::check();
+	 * </code>
+	 */
+	public static function __callStatic($method, $parameters)
+	{
+		return call_user_func_array(array(static::driver(), $method), $parameters);
+	}
+
+}

+ 231 - 0
php-laravel/laravel/auth/drivers/driver.php

@@ -0,0 +1,231 @@
+<?php namespace Laravel\Auth\Drivers;
+
+use Laravel\Str;
+use Laravel\Cookie;
+use Laravel\Config;
+use Laravel\Event;
+use Laravel\Session;
+use Laravel\Crypter;
+
+abstract class Driver {
+
+	/**
+	 * The user currently being managed by the driver.
+	 *
+	 * @var mixed
+	 */
+	public $user;
+
+	/**
+	 * The current value of the user's token.
+	 *
+	 * @var string|null
+	 */
+	public $token;
+
+	/**
+	 * Create a new login auth driver instance.
+	 *
+	 * @return void
+	 */
+	public function __construct()
+	{
+		if (Session::started())
+		{
+			$this->token = Session::get($this->token());
+		}
+
+		// If a token did not exist in the session for the user, we will attempt
+		// to load the value of a "remember me" cookie for the driver, which
+		// serves as a long-lived client side authenticator for the user.
+		if (is_null($this->token))
+		{
+			$this->token = $this->recall();
+		}
+	}
+
+	/**
+	 * Determine if the user of the application is not logged in.
+	 *
+	 * This method is the inverse of the "check" method.
+	 *
+	 * @return bool
+	 */
+	public function guest()
+	{
+		return ! $this->check();
+	}
+
+	/**
+	 * Determine if the user is logged in.
+	 *
+	 * @return bool
+	 */
+	public function check()
+	{
+		return ! is_null($this->user());
+	}
+
+	/**
+	 * Get the current user of the application.
+	 *
+	 * If the user is a guest, null should be returned.
+	 *
+	 * @return mixed|null
+	 */
+	public function user()
+	{
+		if ( ! is_null($this->user)) return $this->user;
+
+		return $this->user = $this->retrieve($this->token);
+	}
+
+	/**
+	 * Get the given application user by ID.
+	 *
+	 * @param  int    $id
+	 * @return mixed
+	 */
+	abstract public function retrieve($id);
+
+	/**
+	 * Attempt to log a user into the application.
+	 *
+	 * @param  array  $arguments
+	 * @return void
+	 */
+	abstract public function attempt($arguments = array());
+
+	/**
+	 * Login the user assigned to the given token.
+	 *
+	 * The token is typically a numeric ID for the user.
+	 *
+	 * @param  string  $token
+	 * @param  bool    $remember
+	 * @return bool
+	 */
+	public function login($token, $remember = false)
+	{
+		$this->token = $token;
+
+		$this->store($token);
+
+		if ($remember) $this->remember($token);
+
+		Event::fire('laravel.auth: login');
+
+		return true;
+	}
+
+	/**
+	 * Log the user out of the driver's auth context.
+	 *
+	 * @return void
+	 */
+	public function logout()
+	{
+		$this->user = null;
+
+		$this->cookie($this->recaller(), null, -2000);
+
+		Session::forget($this->token());
+
+		Event::fire('laravel.auth: logout');
+
+		$this->token = null;
+	}
+
+	/**
+	 * Store a user's token in the session.
+	 *
+	 * @param  string  $token
+	 * @return void
+	 */
+	protected function store($token)
+	{
+		Session::put($this->token(), $token);
+	}
+
+	/**
+	 * Store a user's token in a long-lived cookie.
+	 *
+	 * @param  string  $token
+	 * @return void
+	 */
+	protected function remember($token)
+	{
+		$token = Crypter::encrypt($token.'|'.Str::random(40));
+
+		$this->cookie($this->recaller(), $token, Cookie::forever);
+	}
+
+	/**
+	 * Attempt to find a "remember me" cookie for the user.
+	 *
+	 * @return string|null
+	 */
+	protected function recall()
+	{
+		$cookie = Cookie::get($this->recaller());
+
+		// By default, "remember me" cookies are encrypted and contain the user
+		// token as well as a random string. If it exists, we'll decrypt it
+		// and return the first segment, which is the user's ID token.
+		if ( ! is_null($cookie))
+		{
+			return head(explode('|', Crypter::decrypt($cookie)));
+		}
+	}
+
+	/**
+	 * Store an authentication cookie.
+	 *
+	 * @param  string  $name
+	 * @param  string  $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	protected function cookie($name, $value, $minutes)
+	{
+		// When setting the default implementation of an authentication
+		// cookie we'll use the same settings as the session cookie.
+		// This typically makes sense as they both are sensitive.
+		$config = Config::get('session');
+
+		extract($config);
+
+		Cookie::put($name, $value, $minutes, $path, $domain, $secure);
+	}
+
+	/**
+	 * Get the session key name used to store the token.
+	 *
+	 * @return string
+	 */
+	protected function token()
+	{
+		return $this->name().'_login';
+	}
+
+	/**
+	 * Get the name used for the "remember me" cookie.
+	 *
+	 * @return string
+	 */
+	protected function recaller()
+	{
+		return Config::get('auth.cookie', $this->name().'_remember');
+	}
+
+	/**
+	 * Get the name of the driver in a storage friendly format.
+	 *
+	 * @return string
+	 */
+	protected function name()
+	{
+		return strtolower(str_replace('\\', '_', get_class($this)));
+	}
+
+}

+ 73 - 0
php-laravel/laravel/auth/drivers/eloquent.php

@@ -0,0 +1,73 @@
+<?php namespace Laravel\Auth\Drivers; use Laravel\Hash, Laravel\Config;
+
+class Eloquent extends Driver {
+
+	/**
+	 * Get the current user of the application.
+	 *
+	 * If the user is a guest, null should be returned.
+	 *
+	 * @param  int|object  $token
+	 * @return mixed|null
+	 */
+	public function retrieve($token)
+	{
+		// We return an object here either if the passed token is an integer (ID)
+		// or if we are passed a model object of the correct type
+		if (filter_var($token, FILTER_VALIDATE_INT) !== false)
+		{
+			return $this->model()->find($token);
+		}
+		else if (is_object($token) and get_class($token) == Config::get('auth.model'))
+		{
+			return $token;
+		}
+	}
+
+	/**
+	 * Attempt to log a user into the application.
+	 *
+	 * @param  array $arguments
+	 * @return void
+	 */
+	public function attempt($arguments = array())
+	{
+		$user = $this->model()->where(function($query) use($arguments)
+		{
+			$username = Config::get('auth.username');
+			
+			$query->where($username, '=', $arguments['username']);
+
+			foreach(array_except($arguments, array('username', 'password', 'remember')) as $column => $val)
+			{
+			    $query->where($column, '=', $val);
+			}
+		})->first();
+
+		// If the credentials match what is in the database we will just
+		// log the user into the application and remember them if asked.
+		$password = $arguments['password'];
+
+		$password_field = Config::get('auth.password', 'password');
+
+		if ( ! is_null($user) and Hash::check($password, $user->{$password_field}))
+		{
+			return $this->login($user->get_key(), array_get($arguments, 'remember'));
+		}
+
+		return false;
+	}
+
+	/**
+	 * Get a fresh model instance.
+	 *
+	 * @return Eloquent
+	 */
+	protected function model()
+	{
+		$model = Config::get('auth.model');
+
+		return new $model;
+	}
+
+}

+ 72 - 0
php-laravel/laravel/auth/drivers/fluent.php

@@ -0,0 +1,72 @@
+<?php namespace Laravel\Auth\Drivers;
+
+use Laravel\Hash;
+use Laravel\Config;
+use Laravel\Database as DB;
+
+class Fluent extends Driver {
+
+	/**
+	 * Get the current user of the application.
+	 *
+	 * If the user is a guest, null should be returned.
+	 *
+	 * @param  int  $id
+	 * @return mixed|null
+	 */
+	public function retrieve($id)
+	{
+		if (filter_var($id, FILTER_VALIDATE_INT) !== false)
+		{
+			return DB::table(Config::get('auth.table'))->find($id);
+		}
+	}
+
+	/**
+	 * Attempt to log a user into the application.
+	 *
+	 * @param  array $arguments
+	 * @return void
+	 */
+	public function attempt($arguments = array())
+	{
+		$user = $this->get_user($arguments);
+
+		// If the credentials match what is in the database we will just
+		// log the user into the application and remember them if asked.
+		$password = $arguments['password'];
+
+		$password_field = Config::get('auth.password', 'password');
+
+		if ( ! is_null($user) and Hash::check($password, $user->{$password_field}))
+		{
+			return $this->login($user->id, array_get($arguments, 'remember'));
+		}
+
+		return false;
+	}
+
+	/**
+	 * Get the user from the database table.
+	 *
+	 * @param  array  $arguments
+	 * @return mixed
+	 */
+	protected function get_user($arguments)
+	{
+		$table = Config::get('auth.table');
+
+		return DB::table($table)->where(function($query) use($arguments)
+		{
+			$username = Config::get('auth.username');
+			
+			$query->where($username, '=', $arguments['username']);
+
+			foreach(array_except($arguments, array('username', 'password', 'remember')) as $column => $val)
+			{
+			    $query->where($column, '=', $val);
+			}
+		})->first();
+	}
+
+}

+ 229 - 0
php-laravel/laravel/autoloader.php

@@ -0,0 +1,229 @@
+<?php namespace Laravel;
+
+class Autoloader {
+
+	/**
+	 * The mappings from class names to file paths.
+	 *
+	 * @var array
+	 */
+	public static $mappings = array();
+
+	/**
+	 * The directories that use the PSR-0 naming convention.
+	 *
+	 * @var array
+	 */
+	public static $directories = array();
+
+	/**
+	 * The mappings for namespaces to directories.
+	 *
+	 * @var array
+	 */
+	public static $namespaces = array();
+
+	/**
+	 * The mappings for underscored libraries to directories.
+	 *
+	 * @var array
+	 */
+	public static $underscored = array();
+
+	/**
+	 * All of the class aliases registered with the auto-loader.
+	 *
+	 * @var array
+	 */
+	public static $aliases = array();
+
+	/**
+	 * Load the file corresponding to a given class.
+	 *
+	 * This method is registered in the bootstrap file as an SPL auto-loader.
+	 *
+	 * @param  string  $class
+	 * @return void
+	 */
+	public static function load($class)
+	{
+		// First, we will check to see if the class has been aliased. If it has,
+		// we will register the alias, which may cause the auto-loader to be
+		// called again for the "real" class name to load its file.
+		if (isset(static::$aliases[$class]))
+		{
+			return class_alias(static::$aliases[$class], $class);
+		}
+
+		// All classes in Laravel are statically mapped. There is no crazy search
+		// routine that digs through directories. It's just a simple array of
+		// class to file path maps for ultra-fast file loading.
+		elseif (isset(static::$mappings[$class]))
+		{
+			require static::$mappings[$class];
+
+			return;
+		}
+
+		// If the class namespace is mapped to a directory, we will load the
+		// class using the PSR-0 standards from that directory accounting
+		// for the root of the namespace by trimming it off.
+		foreach (static::$namespaces as $namespace => $directory)
+		{
+			if (starts_with($class, $namespace))
+			{
+				return static::load_namespaced($class, $namespace, $directory);
+			}
+		}
+
+		static::load_psr($class);
+	}
+
+	/**
+	 * Load a namespaced class from a given directory.
+	 *
+	 * @param  string  $class
+	 * @param  string  $namespace
+	 * @param  string  $directory
+	 * @return void
+	 */
+	protected static function load_namespaced($class, $namespace, $directory)
+	{
+		return static::load_psr(substr($class, strlen($namespace)), $directory);
+	}
+
+	/**
+	 * Attempt to resolve a class using the PSR-0 standard.
+	 *
+	 * @param  string  $class
+	 * @param  string  $directory
+	 * @return void
+	 */
+	protected static function load_psr($class, $directory = null)
+	{
+		// The PSR-0 standard indicates that class namespaces and underscores
+		// should be used to indicate the directory tree in which the class
+		// resides, so we'll convert them to slashes.
+		$file = str_replace(array('\\', '_'), '/', $class);
+
+		$directories = $directory ?: static::$directories;
+
+		$lower = strtolower($file);
+
+		// Once we have formatted the class name, we'll simply spin through
+		// the registered PSR-0 directories and attempt to locate and load
+		// the class file into the script.
+		foreach ((array) $directories as $directory)
+		{
+			if (file_exists($path = $directory.$lower.EXT))
+			{
+				return require $path;
+			}
+			elseif (file_exists($path = $directory.$file.EXT))
+			{
+				return require $path;
+			}
+		}
+	}
+
+	/**
+	 * Register an array of class to path mappings.
+	 *
+	 * @param  array  $mappings
+	 * @return void
+	 */
+	public static function map($mappings)
+	{
+		static::$mappings = array_merge(static::$mappings, $mappings);
+	}
+
+	/**
+	 * Register a class alias with the auto-loader.
+	 *
+	 * @param  string  $class
+	 * @param  string  $alias
+	 * @return void
+	 */
+	public static function alias($class, $alias)
+	{
+		static::$aliases[$alias] = $class;
+	}
+
+	/**
+	 * Register directories to be searched as a PSR-0 library.
+	 *
+	 * @param  string|array  $directory
+	 * @return void
+	 */
+	public static function directories($directory)
+	{
+		$directories = static::format($directory);
+
+		static::$directories = array_unique(array_merge(static::$directories, $directories));
+	}
+
+	/**
+	 * Map namespaces to directories.
+	 *
+	 * @param  array   $mappings
+	 * @param  string  $append
+	 * @return void
+	 */
+	public static function namespaces($mappings, $append = '\\')
+	{
+		$mappings = static::format_mappings($mappings, $append);
+
+		static::$namespaces = array_merge($mappings, static::$namespaces);
+	}
+
+	/**
+	 * Register underscored "namespaces" to directory mappings.
+	 *
+	 * @param  array  $mappings
+	 * @return void
+	 */
+	public static function underscored($mappings)
+	{
+		static::namespaces($mappings, '_');
+	}
+
+	/**
+	 * Format an array of namespace to directory mappings.
+	 *
+	 * @param  array   $mappings
+	 * @param  string  $append
+	 * @return array
+	 */
+	protected static function format_mappings($mappings, $append)
+	{
+		foreach ($mappings as $namespace => $directory)
+		{
+			// When adding new namespaces to the mappings, we will unset the previously
+			// mapped value if it existed. This allows previously registered spaces to
+			// be mapped to new directories on the fly.
+			$namespace = trim($namespace, $append).$append;
+
+			unset(static::$namespaces[$namespace]);
+
+			$namespaces[$namespace] = head(static::format($directory));
+		}
+
+		return $namespaces;
+	}
+
+	/**
+	 * Format an array of directories with the proper trailing slashes.
+	 *
+	 * @param  array  $directories
+	 * @return array
+	 */
+	protected static function format($directories)
+	{
+		return array_map(function($directory)
+		{
+			return rtrim($directory, DS).DS;
+		
+		}, (array) $directories);
+	}
+
+}

+ 454 - 0
php-laravel/laravel/blade.php

@@ -0,0 +1,454 @@
+<?php namespace Laravel; use FilesystemIterator as fIterator; use Closure;
+
+class Blade {
+
+	/**
+	 * All of the compiler functions used by Blade.
+	 *
+	 * @var array
+	 */
+	protected static $compilers = array(
+		'extensions',
+		'layouts',
+		'comments',
+		'echos',
+		'forelse',
+		'empty',
+		'endforelse',
+		'structure_openings',
+		'structure_closings',
+		'else',
+		'unless',
+		'endunless',
+		'includes',
+		'render_each',
+		'render',
+		'yields',
+		'yield_sections',
+		'section_start',
+		'section_end',
+	);
+
+	/**
+	 * An array of user defined compilers.
+	 *
+	 * @var array
+	 */
+	protected static $extensions = array();
+
+	/**
+	 * Register the Blade view engine with Laravel.
+	 *
+	 * @return void
+	 */
+	public static function sharpen()
+	{
+		Event::listen(View::engine, function($view)
+		{
+			// The Blade view engine should only handle the rendering of views which
+			// end with the Blade extension. If the given view does not, we will
+			// return false so the View can be rendered as normal.
+			if ( ! str_contains($view->path, BLADE_EXT))
+			{
+				return;
+			}
+
+			$compiled = Blade::compiled($view->path);
+
+			// If the view doesn't exist or has been modified since the last time it
+			// was compiled, we will recompile the view into pure PHP from it's
+			// Blade representation, writing it to cached storage.
+			if ( ! file_exists($compiled) or Blade::expired($view->view, $view->path))
+			{
+				file_put_contents($compiled, Blade::compile($view));
+			}
+
+			$view->path = $compiled;
+
+			// Once the view has been compiled, we can simply set the path to the
+			// compiled view on the view instance and call the typical "get"
+			// method on the view to evaluate the compiled PHP view.
+			return ltrim($view->get());
+		});
+	}
+
+	/**
+	 * Register a custom Blade compiler.
+	 *
+	 * <code>
+	 * 		Blade::extend(function($view)
+	 *		{
+	 * 			return str_replace('foo', 'bar', $view);
+	 * 		});
+	 * </code>
+	 *
+	 * @param  Closure  $compiler
+	 * @return void
+	 */
+	public static function extend(Closure $compiler)
+	{
+		static::$extensions[] = $compiler;
+	}
+
+	/**
+	 * Determine if a view is "expired" and needs to be re-compiled.
+	 *
+	 * @param  string  $view
+	 * @param  string  $path
+	 * @return bool
+	 */
+	public static function expired($view, $path)
+	{
+		return filemtime($path) > filemtime(static::compiled($path));
+	}
+
+	/**
+	 * Compiles the specified file containing Blade pseudo-code into valid PHP.
+	 *
+	 * @param  string  $path
+	 * @return string
+	 */
+	public static function compile($view)
+	{
+		return static::compile_string(file_get_contents($view->path), $view);
+	}
+
+	/**
+	 * Compiles the given string containing Blade pseudo-code into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @param  View    $view
+	 * @return string
+	 */
+	public static function compile_string($value, $view = null)
+	{
+		foreach (static::$compilers as $compiler)
+		{
+			$method = "compile_{$compiler}";
+
+			$value = static::$method($value, $view);
+		}
+
+		return $value;
+	}
+
+	/**
+	 * Rewrites Blade "@layout" expressions into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_layouts($value)
+	{
+		// If the Blade template is not using "layouts", we'll just return it
+		// unchanged since there is nothing to do with layouts and we will
+		// just let the other Blade compilers handle the rest.
+		if ( ! starts_with($value, '@layout'))
+		{
+			return $value;
+		}
+
+		// First we'll split out the lines of the template so we can get the
+		// layout from the top of the template. By convention it must be
+		// located on the first line of the template contents.
+		$lines = preg_split("/(\r?\n)/", $value);
+
+		$pattern = static::matcher('layout');
+
+		$lines[] = preg_replace($pattern, '$1@include$2', $lines[0]);
+
+		// We will add a "render" statement to the end of the templates and
+		// then slice off the "@layout" shortcut from the start so the
+		// sections register before the parent template renders.
+		return implode(CRLF, array_slice($lines, 1));
+	}
+
+	/**
+	 * Extract a variable value out of a Blade expression.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function extract($value, $expression)
+	{
+		preg_match('/@layout(\s*\(.*\))(\s*)/', $value, $matches);
+
+		return str_replace(array("('", "')"), '', $matches[1]);
+	}
+
+	/**
+	 * Rewrites Blade comments into PHP comments.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_comments($value)
+	{
+		$value = preg_replace('/\{\{--(.+?)(--\}\})?\n/', "<?php // $1 ?>", $value);
+
+		return preg_replace('/\{\{--((.|\s)*?)--\}\}/', "<?php /* $1 */ ?>\n", $value);
+	}
+
+	/**
+	 * Rewrites Blade echo statements into PHP echo statements.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_echos($value)
+	{
+		$value = preg_replace('/\{\{\{(.+?)\}\}\}/', '<?php echo HTML::entities($1); ?>', $value);
+
+		return preg_replace('/\{\{(.+?)\}\}/', '<?php echo $1; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade "for else" statements into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_forelse($value)
+	{
+		preg_match_all('/(\s*)@forelse(\s*\(.*\))(\s*)/', $value, $matches);
+
+		foreach ($matches[0] as $forelse)
+		{
+			preg_match('/\s*\(\s*(\S*)\s/', $forelse, $variable);
+
+			// Once we have extracted the variable being looped against, we can add
+			// an if statement to the start of the loop that checks if the count
+			// of the variable being looped against is greater than zero.
+			$if = "<?php if (count({$variable[1]}) > 0): ?>";
+
+			$search = '/(\s*)@forelse(\s*\(.*\))/';
+
+			$replace = '$1'.$if.'<?php foreach$2: ?>';
+
+			$blade = preg_replace($search, $replace, $forelse);
+
+			// Finally, once we have the check prepended to the loop we'll replace
+			// all instances of this forelse syntax in the view content of the
+			// view being compiled to Blade syntax with real PHP syntax.
+			$value = str_replace($forelse, $blade, $value);
+		}
+
+		return $value;
+	}
+
+	/**
+	 * Rewrites Blade "empty" statements into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_empty($value)
+	{
+		return str_replace('@empty', '<?php endforeach; ?><?php else: ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade "forelse" endings into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_endforelse($value)
+	{
+		return str_replace('@endforelse', '<?php endif; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade structure openings into PHP structure openings.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_structure_openings($value)
+	{
+		$pattern = '/(\s*)@(if|elseif|foreach|for|while)(\s*\(.*\))/';
+
+		return preg_replace($pattern, '$1<?php $2$3: ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade structure closings into PHP structure closings.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_structure_closings($value)
+	{
+		$pattern = '/(\s*)@(endif|endforeach|endfor|endwhile)(\s*)/';
+
+		return preg_replace($pattern, '$1<?php $2; ?>$3', $value);
+	}
+
+	/**
+	 * Rewrites Blade else statements into PHP else statements.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_else($value)
+	{
+		return preg_replace('/(\s*)@(else)(\s*)/', '$1<?php $2: ?>$3', $value);
+	}
+
+	/**
+	 * Rewrites Blade "unless" statements into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_unless($value)
+	{
+		$pattern = '/(\s*)@unless(\s*\(.*\))/';
+
+		return preg_replace($pattern, '$1<?php if ( ! ($2)): ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade "unless" endings into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_endunless($value)
+	{
+		return str_replace('@endunless', '<?php endif; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade @include statements into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_includes($value)
+	{
+		$pattern = static::matcher('include');
+
+		return preg_replace($pattern, '$1<?php echo view$2->with(get_defined_vars())->render(); ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade @render statements into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_render($value)
+	{
+		$pattern = static::matcher('render');
+
+		return preg_replace($pattern, '$1<?php echo render$2; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade @render_each statements into valid PHP.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_render_each($value)
+	{
+		$pattern = static::matcher('render_each');
+
+		return preg_replace($pattern, '$1<?php echo render_each$2; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade @yield statements into Section statements.
+	 *
+	 * The Blade @yield statement is a shortcut to the Section::yield method.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_yields($value)
+	{
+		$pattern = static::matcher('yield');
+
+		return preg_replace($pattern, '$1<?php echo \\Laravel\\Section::yield$2; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade yield section statements into valid PHP.
+	 *
+	 * @return string
+	 */
+	protected static function compile_yield_sections($value)
+	{
+		$replace = '<?php echo \\Laravel\\Section::yield_section(); ?>';
+
+		return str_replace('@yield_section', $replace, $value);
+	}
+
+	/**
+	 * Rewrites Blade @section statements into Section statements.
+	 *
+	 * The Blade @section statement is a shortcut to the Section::start method.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_section_start($value)
+	{
+		$pattern = static::matcher('section');
+
+		return preg_replace($pattern, '$1<?php \\Laravel\\Section::start$2; ?>', $value);
+	}
+
+	/**
+	 * Rewrites Blade @endsection statements into Section statements.
+	 *
+	 * The Blade @endsection statement is a shortcut to the Section::stop method.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_section_end($value)
+	{
+		return preg_replace('/@endsection/', '<?php \\Laravel\\Section::stop(); ?>', $value);
+	}
+
+	/**
+	 * Execute user defined compilers.
+	 *
+	 * @param  string  $value
+	 * @return string
+	 */
+	protected static function compile_extensions($value)
+	{
+		foreach (static::$extensions as $compiler)
+		{
+			$value = $compiler($value);
+		}
+
+		return $value;
+	}	
+
+	/**
+	 * Get the regular expression for a generic Blade function.
+	 *
+	 * @param  string  $function
+	 * @return string
+	 */
+	public static function matcher($function)
+	{
+		return '/(\s*)@'.$function.'(\s*\(.*\))/';
+	}
+
+	/**
+	 * Get the fully qualified path for a compiled view.
+	 *
+	 * @param  string  $view
+	 * @return string
+	 */
+	public static function compiled($path)
+	{
+		return path('storage').'views/'.md5($path);
+	}
+
+}

+ 476 - 0
php-laravel/laravel/bundle.php

@@ -0,0 +1,476 @@
+<?php namespace Laravel; defined('DS') or die('No direct script access.');
+
+use Laravel\Routing\Router;
+use FilesystemIterator as fIterator;
+
+class Bundle {
+
+	/**
+	 * All of the application's bundles.
+	 *
+	 * @var array
+	 */
+	public static $bundles = array();
+
+	/**
+	 * A cache of the parsed bundle elements.
+	 *
+	 * @var array
+	 */
+	public static $elements = array();
+
+	/**
+	 * All of the bundles that have been started.
+	 *
+	 * @var array
+	 */
+	public static $started = array();
+
+	/**
+	 * All of the bundles that have their routes files loaded.
+	 *
+	 * @var array
+	 */
+	public static $routed = array();
+
+	/**
+	 * Register the bundle for the application.
+	 *
+	 * @param  string  $bundle
+	 * @param  array   $config
+	 * @return void
+	 */
+	public static function register($bundle, $config = array())
+	{
+		$defaults = array('handles' => null, 'auto' => false);
+
+		// If the given configuration is actually a string, we will assume it is a
+		// location and set the bundle name to match it. This is common for most
+		// bundles that simply live in the root bundle directory.
+		if (is_string($config))
+		{
+			$bundle = $config;
+
+			$config = array('location' => $bundle);
+		}
+
+		// If no location is set, we will set the location to match the name of
+		// the bundle. This is for bundles that are installed on the root of
+		// the bundle directory so a location was not set.
+		if ( ! isset($config['location']))
+		{
+			$config['location'] = $bundle;
+		}
+
+		static::$bundles[$bundle] = array_merge($defaults, $config);
+
+		// It is possible for the developer to specify auto-loader mappings
+		// directly on the bundle registration. This provides a convenient
+		// way to register mappings without a bootstrap.
+		if (isset($config['autoloads']))
+		{
+			static::autoloads($bundle, $config);
+		}
+	}
+
+	/**
+	 * Load a bundle by running its start-up script.
+	 *
+	 * If the bundle has already been started, no action will be taken.
+	 *
+	 * @param  string  $bundle
+	 * @return void
+	 */
+	public static function start($bundle)
+	{
+		if (static::started($bundle)) return;
+
+		if ( ! static::exists($bundle))
+		{
+			throw new \Exception("Bundle [$bundle] has not been installed.");
+		}
+
+		// Each bundle may have a start script which is responsible for preparing
+		// the bundle for use by the application. The start script may register
+		// any classes the bundle uses with the auto-loader class, etc.
+		if ( ! is_null($starter = static::option($bundle, 'starter')))
+		{
+			$starter();
+		}
+		elseif (file_exists($path = static::path($bundle).'start'.EXT))
+		{
+			require $path;
+		}
+
+		// Each bundle may also have a "routes" file which is responsible for
+		// registering the bundle's routes. This is kept separate from the
+		// start script for reverse routing efficiency purposes.
+		static::routes($bundle);
+
+		Event::fire("laravel.started: {$bundle}");
+
+		static::$started[] = strtolower($bundle);
+	}
+
+	/**
+	 * Load the "routes" file for a given bundle.
+	 *
+	 * @param  string  $bundle
+	 * @return void
+	 */
+	public static function routes($bundle)
+	{
+		if (static::routed($bundle)) return;
+
+		$path = static::path($bundle).'routes'.EXT;
+
+		// By setting the bundle property on the router, the router knows what
+		// value to replace the (:bundle) place-holder with when the bundle
+		// routes are added, keeping the routes flexible.
+		Router::$bundle = static::option($bundle, 'handles');
+
+		if ( ! static::routed($bundle) and file_exists($path))
+		{
+			static::$routed[] = $bundle;
+
+			require $path;
+		}
+	}
+
+	/**
+	 * Register the auto-loading configuration for a bundle.
+	 *
+	 * @param  string  $bundle
+	 * @param  array   $config
+	 * @return void
+	 */
+	protected static function autoloads($bundle, $config)
+	{
+		$path = rtrim(Bundle::path($bundle), DS);
+
+		foreach ($config['autoloads'] as $type => $mappings)
+		{
+			// When registering each type of mapping we'll replace the (:bundle)
+			// place-holder with the path to the bundle's root directory, so
+			// the developer may dryly register the mappings.
+			$mappings = array_map(function($mapping) use ($path)
+			{
+				return str_replace('(:bundle)', $path, $mapping);
+
+			}, $mappings);
+
+			// Once the mappings are formatted, we will call the Autoloader
+			// function matching the mapping type and pass in the array of
+			// mappings so they can be registered and used.
+			Autoloader::$type($mappings);
+		}
+	}
+
+	/**
+	 * Disable a bundle for the current request.
+	 *
+	 * @param  string  $bundle
+	 * @return void
+	 */
+	public static function disable($bundle)
+	{
+		unset(static::$bundles[$bundle]);
+	}
+
+	/**
+	 * Determine which bundle handles the given URI.
+	 *
+	 * The default bundle is returned if no other bundle is assigned.
+	 *
+	 * @param  string  $uri
+	 * @return string
+	 */
+	public static function handles($uri)
+	{
+		$uri = rtrim($uri, '/').'/';
+
+		foreach (static::$bundles as $key => $value)
+		{
+			if (isset($value['handles']) and starts_with($uri, $value['handles'].'/') or $value['handles'] == '/')
+			{
+				return $key;
+			}
+		}
+
+		return DEFAULT_BUNDLE;
+	}
+
+	/**
+	 * Determine if a bundle exists within the bundles directory.
+	 *
+	 * @param  string  $bundle
+	 * @return bool
+	 */
+	public static function exists($bundle)
+	{
+		return $bundle == DEFAULT_BUNDLE or in_array(strtolower($bundle), static::names());
+	}
+
+	/**
+	 * Determine if a given bundle has been started for the request.
+	 *
+	 * @param  string  $bundle
+	 * @return void
+	 */
+	public static function started($bundle)
+	{
+		return in_array(strtolower($bundle), static::$started);
+	}
+
+	/**
+	 * Determine if a given bundle has its routes file loaded.
+	 *
+	 * @param  string  $bundle
+	 * @return void
+	 */
+	public static function routed($bundle)
+	{
+		return in_array(strtolower($bundle), static::$routed);
+	}
+
+	/**
+	 * Get the identifier prefix for the bundle.
+	 *
+	 * @param  string  $bundle
+	 * @return string
+	 */
+	public static function prefix($bundle)
+	{
+		return ($bundle !== DEFAULT_BUNDLE) ? "{$bundle}::" : '';
+	}
+
+	/**
+	 * Get the class prefix for a given bundle.
+	 *
+	 * @param  string  $bundle
+	 * @return string
+	 */
+	public static function class_prefix($bundle)
+	{
+		return ($bundle !== DEFAULT_BUNDLE) ? Str::classify($bundle).'_' : '';
+	}
+
+	/**
+	 * Return the root bundle path for a given bundle.
+	 *
+	 * <code>
+	 *		// Returns the bundle path for the "admin" bundle
+	 *		$path = Bundle::path('admin');
+	 *
+	 *		// Returns the path('app') constant as the default bundle
+	 *		$path = Bundle::path('application');
+	 * </code>
+	 *
+	 * @param  string  $bundle
+	 * @return string
+	 */
+	public static function path($bundle)
+	{
+		if (is_null($bundle) or $bundle === DEFAULT_BUNDLE)
+		{
+			return path('app');
+		}
+		elseif ($location = array_get(static::$bundles, $bundle.'.location'))
+		{
+			// If the bundle location starts with "path: ", we will assume that a raw
+			// path has been specified and will simply return it. Otherwise, we'll
+			// prepend the bundle directory path onto the location and return.
+			if (starts_with($location, 'path: '))
+			{
+				return str_finish(substr($location, 6), DS);
+			}
+			else
+			{
+				return str_finish(path('bundle').$location, DS);
+			}
+		}
+	}
+
+	/**
+	 * Return the root asset path for the given bundle.
+	 *
+	 * @param  string  $bundle
+	 * @return string
+	 */
+	public static function assets($bundle)
+	{
+		if (is_null($bundle)) return static::assets(DEFAULT_BUNDLE);
+
+		return ($bundle != DEFAULT_BUNDLE) ? "/bundles/{$bundle}/" : '/';
+	}
+
+	/**
+	 * Get the bundle name from a given identifier.
+	 *
+	 * <code>
+	 *		// Returns "admin" as the bundle name for the identifier
+	 *		$bundle = Bundle::name('admin::home.index');
+	 * </code>
+	 *
+	 * @param  string  $identifier
+	 * @return string
+	 */
+	public static function name($identifier)
+	{
+		list($bundle, $element) = static::parse($identifier);
+
+		return $bundle;
+	}
+
+	/**
+	 * Get the element name from a given identifier.
+	 *
+	 * <code>
+	 *		// Returns "home.index" as the element name for the identifier
+	 *		$bundle = Bundle::bundle('admin::home.index');
+	 * </code>
+	 *
+	 * @param  string  $identifier
+	 * @return string
+	 */
+	public static function element($identifier)
+	{
+		list($bundle, $element) = static::parse($identifier);
+
+		return $element;
+	}
+
+	/**
+	 * Reconstruct an identifier from a given bundle and element.
+	 *
+	 * <code>
+	 *		// Returns "admin::home.index"
+	 *		$identifier = Bundle::identifier('admin', 'home.index');
+	 *
+	 *		// Returns "home.index"
+	 *		$identifier = Bundle::identifier('application', 'home.index');
+	 * </code>
+	 *
+	 * @param  string  $bundle
+	 * @param  string  $element
+	 * @return string
+	 */
+	public static function identifier($bundle, $element)
+	{
+		return (is_null($bundle) or $bundle == DEFAULT_BUNDLE) ? $element : $bundle.'::'.$element;
+	}
+
+	/**
+	 * Return the bundle name if it exists, else return the default bundle.
+	 *
+	 * @param  string  $bundle
+	 * @return string
+	 */
+	public static function resolve($bundle)
+	{
+		return (static::exists($bundle)) ? $bundle : DEFAULT_BUNDLE;
+	}
+
+	/**
+	 * Parse an element identifier and return the bundle name and element.
+	 *
+	 * <code>
+	 *		// Returns array(null, 'admin.user')
+	 *		$element = Bundle::parse('admin.user');
+	 *
+	 *		// Parses "admin::user" and returns array('admin', 'user')
+	 *		$element = Bundle::parse('admin::user');
+	 * </code>
+	 *
+	 * @param  string  $identifier
+	 * @return array
+	 */
+	public static function parse($identifier)
+	{
+		// The parsed elements are cached so we don't have to reparse them on each
+		// subsequent request for the parsed element. So if we've already parsed
+		// the given element, we'll just return the cached copy as the value.
+		if (isset(static::$elements[$identifier]))
+		{
+			return static::$elements[$identifier];
+		}
+
+		if (strpos($identifier, '::') !== false)
+		{
+			$element = explode('::', strtolower($identifier));
+		}
+		// If no bundle is in the identifier, we will insert the default bundle
+		// since classes like Config and Lang organize their items by bundle.
+		// The application folder essentially behaves as a default bundle.
+		else
+		{
+			$element = array(DEFAULT_BUNDLE, strtolower($identifier));
+		}
+
+		return static::$elements[$identifier] = $element;
+	}
+
+	/**
+	 * Get the information for a given bundle.
+	 *
+	 * @param  string  $bundle
+	 * @return object
+	 */
+	public static function get($bundle)
+	{
+		return array_get(static::$bundles, $bundle);
+	}
+
+	/**
+	 * Get an option for a given bundle.
+	 *
+	 * @param  string  $bundle
+	 * @param  string  $option
+	 * @param  mixed   $default
+	 * @return mixed
+	 */
+	public static function option($bundle, $option, $default = null)
+	{
+		$bundle = static::get($bundle);
+
+		if (is_null($bundle))
+		{
+			return value($default);
+		}
+
+		return array_get($bundle, $option, $default);
+	}
+
+	/**
+	 * Get all of the installed bundles for the application.
+	 *
+	 * @return array
+	 */
+	public static function all()
+	{
+		return static::$bundles;
+	}
+
+	/**
+	 * Get all of the installed bundle names.
+	 *
+	 * @return array
+	 */
+	public static function names()
+	{
+		return array_keys(static::$bundles);
+	}
+
+	/**
+	 * Expand given bundle path of form "[bundle::]path/...".
+	 *
+	 * @param  string  $path
+	 * @return string
+	 */
+	public static function expand($path)
+	{
+		list($bundle, $element) = static::parse($path);
+		return static::path($bundle).$element;
+	}
+
+}

+ 118 - 0
php-laravel/laravel/cache.php

@@ -0,0 +1,118 @@
+<?php namespace Laravel; use Closure;
+
+class Cache {
+
+	/**
+	 * All of the active cache drivers.
+	 *
+	 * @var array
+	 */
+	public static $drivers = array();
+
+	/**
+	 * The third-party driver registrar.
+	 *
+	 * @var array
+	 */
+	public static $registrar = array();
+
+	/**
+	 * Get a cache driver instance.
+	 *
+	 * If no driver name is specified, the default will be returned.
+	 *
+	 * <code>
+	 *		// Get the default cache driver instance
+	 *		$driver = Cache::driver();
+	 *
+	 *		// Get a specific cache driver instance by name
+	 *		$driver = Cache::driver('memcached');
+	 * </code>
+	 *
+	 * @param  string        $driver
+	 * @return Cache\Drivers\Driver
+	 */
+	public static function driver($driver = null)
+	{
+		if (is_null($driver)) $driver = Config::get('cache.driver');
+
+		if ( ! isset(static::$drivers[$driver]))
+		{
+			static::$drivers[$driver] = static::factory($driver);
+		}
+
+		return static::$drivers[$driver];
+	}
+
+	/**
+	 * Create a new cache driver instance.
+	 *
+	 * @param  string  $driver
+	 * @return Cache\Drivers\Driver
+	 */
+	protected static function factory($driver)
+	{
+		if (isset(static::$registrar[$driver]))
+		{
+			$resolver = static::$registrar[$driver];
+
+			return $resolver();
+		}
+
+		switch ($driver)
+		{
+			case 'apc':
+				return new Cache\Drivers\APC(Config::get('cache.key'));
+
+			case 'file':
+				return new Cache\Drivers\File(path('storage').'cache'.DS);
+
+			case 'memcached':
+				return new Cache\Drivers\Memcached(Memcached::connection(), Config::get('cache.key'));
+
+			case 'memory':
+				return new Cache\Drivers\Memory;
+
+			case 'redis':
+				return new Cache\Drivers\Redis(Redis::db());
+
+			case 'database':
+				return new Cache\Drivers\Database(Config::get('cache.key'));
+
+			case 'wincache':
+				return new Cache\Drivers\WinCache(Config::get('cache.key'));
+
+			default:
+				throw new \Exception("Cache driver {$driver} is not supported.");
+		}
+	}
+
+	/**
+	 * Register a third-party cache driver.
+	 *
+	 * @param  string   $driver
+	 * @param  Closure  $resolver
+	 * @return void
+	 */
+	public static function extend($driver, Closure $resolver)
+	{
+		static::$registrar[$driver] = $resolver;
+	}
+
+	/**
+	 * Magic Method for calling the methods on the default cache driver.
+	 *
+	 * <code>
+	 *		// Call the "get" method on the default cache driver
+	 *		$name = Cache::get('name');
+	 *
+	 *		// Call the "put" method on the default cache driver
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 */
+	public static function __callStatic($method, $parameters)
+	{
+		return call_user_func_array(array(static::driver(), $method), $parameters);
+	}
+
+}

+ 89 - 0
php-laravel/laravel/cache/drivers/apc.php

@@ -0,0 +1,89 @@
+<?php namespace Laravel\Cache\Drivers;
+
+class APC extends Driver {
+
+	/**
+	 * The cache key from the cache configuration file.
+	 *
+	 * @var string
+	 */
+	protected $key;
+
+	/**
+	 * Create a new APC cache driver instance.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function __construct($key)
+	{
+		$this->key = $key;
+	}
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		if (($cache = apc_fetch($this->key.$key)) !== false)
+		{
+			return $cache;
+		}
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		apc_store($this->key.$key, $value, $minutes * 60);
+	}
+
+	/**
+	 * Write an item to the cache that lasts forever.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		return $this->put($key, $value, 0);
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		apc_delete($this->key.$key);
+	}
+
+}

+ 125 - 0
php-laravel/laravel/cache/drivers/database.php

@@ -0,0 +1,125 @@
+<?php namespace Laravel\Cache\Drivers;
+
+use Laravel\Config;
+use Laravel\Database as DB;
+use Laravel\Database\Connection;
+
+class Database extends Driver {
+
+	/**
+	 * The cache key from the cache configuration file.
+	 *
+	 * @var string
+	 */
+	protected $key;
+
+	/**
+	 * Create a new database cache driver instance.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function __construct($key)
+	{
+		$this->key = $key;
+	}
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		$cache = $this->table()->where('key', '=', $this->key.$key)->first();
+
+		if ( ! is_null($cache))
+		{
+			if (time() >= $cache->expiration) return $this->forget($key);
+
+			return unserialize($cache->value);
+		}
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		$key = $this->key.$key;
+
+		$value = serialize($value);
+
+		$expiration = $this->expiration($minutes);
+
+		// To update the value, we'll first attempt an insert against the
+		// database and if we catch an exception we'll assume that the
+		// primary key already exists in the table and update.
+		try
+		{
+			$this->table()->insert(compact('key', 'value', 'expiration'));
+		}
+		catch (\Exception $e)
+		{
+			$this->table()->where('key', '=', $key)->update(compact('value', 'expiration'));
+		}
+	}
+
+	/**
+	 * Write an item to the cache for five years.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		return $this->put($key, $value, 2628000);
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		$this->table()->where('key', '=', $this->key.$key)->delete();
+	}
+
+	/**
+	 * Get a query builder for the database table.
+	 *
+	 * @return Laravel\Database\Query
+	 */
+	protected function table()
+	{
+		$connection = DB::connection(Config::get('cache.database.connection'));
+
+		return $connection->table(Config::get('cache.database.table'));
+	}
+
+}

+ 113 - 0
php-laravel/laravel/cache/drivers/driver.php

@@ -0,0 +1,113 @@
+<?php namespace Laravel\Cache\Drivers;
+
+abstract class Driver {
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	abstract public function has($key);
+
+	/**
+	 * Get an item from the cache.
+	 *
+	 * <code>
+	 *		// Get an item from the cache driver
+	 *		$name = Cache::driver('name');
+	 *
+	 *		// Return a default value if the requested item isn't cached
+	 *		$name = Cache::get('name', 'Taylor');
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $default
+	 * @return mixed
+	 */
+	public function get($key, $default = null)
+	{
+		return ( ! is_null($item = $this->retrieve($key))) ? $item : value($default);
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	abstract protected function retrieve($key);
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	abstract public function put($key, $value, $minutes);
+
+	/**
+	 * Get an item from the cache, or cache and return the default value.
+	 *
+	 * <code>
+	 *		// Get an item from the cache, or cache a value for 15 minutes
+	 *		$name = Cache::remember('name', 'Taylor', 15);
+	 *
+	 *		// Use a closure for deferred execution
+	 *		$count = Cache::remember('count', function() { return User::count(); }, 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $default
+	 * @param  int     $minutes
+	 * @param  string  $function
+	 * @return mixed
+	 */
+	public function remember($key, $default, $minutes, $function = 'put')
+	{
+		if ( ! is_null($item = $this->get($key, null))) return $item;
+
+		$this->$function($key, $default = value($default), $minutes);
+
+		return $default;
+	}
+
+	/**
+	 * Get an item from the cache, or cache the default value forever.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $default
+	 * @return mixed
+	 */
+	public function sear($key, $default)
+	{
+		return $this->remember($key, $default, null, 'forever');
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	abstract public function forget($key);
+
+	/**
+	 * Get the expiration time as a UNIX timestamp.
+	 *
+	 * @param  int  $minutes
+	 * @return int
+	 */
+	protected function expiration($minutes)
+	{
+		return time() + ($minutes * 60);
+	}
+
+}

+ 110 - 0
php-laravel/laravel/cache/drivers/file.php

@@ -0,0 +1,110 @@
+<?php namespace Laravel\Cache\Drivers;
+
+class File extends Driver {
+
+	/**
+	 * The path to which the cache files should be written.
+	 *
+	 * @var string
+	 */
+	protected $path;
+
+	/**
+	 * Create a new File cache driver instance.
+	 *
+	 * @param  string  $path
+	 * @return void
+	 */
+	public function __construct($path)
+	{
+		$this->path = $path;
+	}
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		if ( ! file_exists($this->path.$key)) return null;
+
+		// File based caches store have the expiration timestamp stored in
+		// UNIX format prepended to their contents. We'll compare the
+		// timestamp to the current time when we read the file.
+		if (time() >= substr($cache = file_get_contents($this->path.$key), 0, 10))
+		{
+			return $this->forget($key);
+		}
+
+		return unserialize(substr($cache, 10));
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		if ($minutes <= 0) return;
+
+		$value = $this->expiration($minutes).serialize($value);
+
+		file_put_contents($this->path.$key, $value, LOCK_EX);
+	}
+
+	/**
+	 * Write an item to the cache for five years.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		return $this->put($key, $value, 2628000);
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		if (file_exists($this->path.$key)) @unlink($this->path.$key);
+	}
+
+	/**
+	 * Flush the entire cache.
+	 *
+	 * @return void
+	 */
+	public function flush()
+	{
+		array_map('unlink', glob($this->path.'*'));
+	}
+
+}

+ 186 - 0
php-laravel/laravel/cache/drivers/memcached.php

@@ -0,0 +1,186 @@
+<?php namespace Laravel\Cache\Drivers;
+
+class Memcached extends Sectionable {
+
+	/**
+	 * The Memcache instance.
+	 *
+	 * @var Memcached
+	 */
+	public $memcache;
+
+	/**
+	 * The cache key from the cache configuration file.
+	 *
+	 * @var string
+	 */
+	protected $key;
+
+	/**
+	 * Create a new Memcached cache driver instance.
+	 *
+	 * @param  Memcached  $memcache
+	 * @param  string     $key
+	 * @return void
+	 */
+	public function __construct(\Memcached $memcache, $key)
+	{
+		$this->key = $key;
+		$this->memcache = $memcache;
+	}
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			return $this->get_from_section($section, $key);
+		}
+		elseif (($cache = $this->memcache->get($this->key.$key)) !== false)
+		{
+			return $cache;
+		}
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			return $this->put_in_section($section, $key, $value, $minutes);
+		}
+		else
+		{
+			$this->memcache->set($this->key.$key, $value, $minutes * 60);
+		}
+	}
+
+	/**
+	 * Write an item to the cache that lasts forever.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			return $this->forever_in_section($section, $key, $value);
+		}
+		else
+		{
+			return $this->put($key, $value, 0);
+		}
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			if ($key == '*')
+			{
+				$this->forget_section($section);
+			}
+			else
+			{
+				$this->forget_in_section($section, $key);
+			}
+		}
+		else
+		{
+			$this->memcache->delete($this->key.$key);
+		}
+	}
+
+	/**
+	 * Delete an entire section from the cache.
+	 *
+	 * @param  string    $section
+	 * @return int|bool
+	 */
+	public function forget_section($section)
+	{
+		return $this->memcache->increment($this->key.$this->section_key($section));
+	}
+
+	/**
+	 * Get the current section ID for a given section.
+	 *
+	 * @param  string  $section
+	 * @return int
+	 */
+	protected function section_id($section)
+	{
+		return $this->sear($this->section_key($section), function()
+		{
+			return rand(1, 10000);
+		});
+	}
+
+	/**
+	 * Get a section key name for a given section.
+	 *
+	 * @param  string  $section
+	 * @return string
+	 */
+	protected function section_key($section)
+	{
+		return $section.'_section_key';
+	}
+
+	/**
+	 * Get a section item key for a given section and key.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @return string
+	 */
+	protected function section_item_key($section, $key)
+	{
+		return $section.'#'.$this->section_id($section).'#'.$key;
+	}
+
+}

+ 151 - 0
php-laravel/laravel/cache/drivers/memory.php

@@ -0,0 +1,151 @@
+<?php namespace Laravel\Cache\Drivers;
+
+class Memory extends Sectionable {
+
+	/**
+	 * The in-memory array of cached items.
+	 *
+	 * @var string
+	 */
+	public $storage = array();
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			return $this->get_from_section($section, $key);
+		}
+		else
+		{
+			return array_get($this->storage, $key);
+		}
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			return $this->put_in_section($section, $key, $value, $minutes);
+		}
+		else
+		{
+			array_set($this->storage, $key, $value);
+		}
+	}
+
+	/**
+	 * Write an item to the cache that lasts forever.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			return $this->forever_in_section($section, $key, $value);
+		}
+		else
+		{
+			$this->put($key, $value, 0);
+		}
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		if ($this->sectionable($key))
+		{
+			list($section, $key) = $this->parse($key);
+
+			if ($key == '*')
+			{
+				$this->forget_section($section);
+			}
+			else
+			{
+				$this->forget_in_section($section, $key);
+			}
+		}
+		else
+		{
+			array_forget($this->storage, $key);
+		}
+	}
+
+	/**
+	 * Delete an entire section from the cache.
+	 *
+	 * @param  string    $section
+	 * @return int|bool
+	 */
+	public function forget_section($section)
+	{
+		array_forget($this->storage, 'section#'.$section);
+	}
+
+	/**
+	 * Flush the entire cache.
+	 *
+	 * @return void
+	 */
+	public function flush()
+	{
+		$this->storage = array();
+	}
+
+	/**
+	 * Get a section item key for a given section and key.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @return string
+	 */
+	protected function section_item_key($section, $key)
+	{
+		return "section#{$section}.{$key}";
+	}
+
+}

+ 101 - 0
php-laravel/laravel/cache/drivers/redis.php

@@ -0,0 +1,101 @@
+<?php namespace Laravel\Cache\Drivers;
+
+class Redis extends Driver {
+
+	/**
+	 * The Redis database instance.
+	 *
+	 * @var Laravel\Redis
+	 */
+	protected $redis;
+
+	/**
+	 * Create a new Redis cache driver instance.
+	 *
+	 * @param  Laravel\Redis  $redis
+	 * @return void
+	 */
+	public function __construct(\Laravel\Redis $redis)
+	{
+		$this->redis = $redis;
+	}
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->redis->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		if ( ! is_null($cache = $this->redis->get($key)))
+		{
+			return unserialize($cache);
+		}
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		$this->forever($key, $value);
+
+		$this->redis->expire($key, $minutes * 60);
+	}
+
+	/**
+	 * Write an item to the cache that lasts forever.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		$this->redis->set($key, serialize($value));
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		$this->redis->del($key);
+	}
+
+	/**
+	 * Flush the entire cache.
+	 *
+	 * @return void
+	 */
+	public function flush()
+	{
+		$this->redis->flushdb();
+	}
+
+}

+ 142 - 0
php-laravel/laravel/cache/drivers/sectionable.php

@@ -0,0 +1,142 @@
+<?php namespace Laravel\Cache\Drivers;
+
+abstract class Sectionable extends Driver {
+
+	/**
+	 * Indicates that section caching is implicit based on keys.
+	 *
+	 * @var bool
+	 */
+	public $implicit = true;
+
+	/**
+	 * The implicit section key delimiter.
+	 *
+	 * @var string
+	 */
+	public $delimiter = '::';
+
+	/**
+	 * Retrieve a sectioned item from the cache driver.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @param  mixed   $default
+	 * @return mixed
+	 */
+	public function get_from_section($section, $key, $default = null)
+	{
+		return $this->get($this->section_item_key($section, $key), $default);
+	}
+
+	/**
+	 * Write a sectioned item to the cache.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put_in_section($section, $key, $value, $minutes)
+	{
+		$this->put($this->section_item_key($section, $key), $value, $minutes);
+	}
+
+	/**
+	 * Write a sectioned item to the cache that lasts forever.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever_in_section($section, $key, $value)
+	{
+		return $this->forever($this->section_item_key($section, $key), $value);
+	}
+
+	/**
+	 * Get a sectioned item from the cache, or cache and return the default value.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @param  mixed   $default
+	 * @param  int     $minutes
+	 * @param  string  $function
+	 * @return mixed
+	 */
+	public function remember_in_section($section, $key, $default, $minutes, $function = 'put')
+	{
+		$key = $this->section_item_key($section, $key);
+
+		return $this->remember($key, $default, $minutes, $function);
+	}
+
+	/**
+	 * Get a sectioned item from the cache, or cache the default value forever.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @param  mixed   $default
+	 * @return mixed
+	 */
+	public function sear_in_section($section, $key, $default)
+	{
+		return $this->sear($this->section_item_key($section, $key), $default);
+	}
+
+	/**
+	 * Delete a sectioned item from the cache.
+	 *
+	 * @param  string  $section
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget_in_section($section, $key)
+	{
+		return $this->forget($this->section_item_key($section, $key));
+	}
+
+	/**
+	 * Delete an entire section from the cache.
+	 *
+	 * @param  string    $section
+	 * @return int|bool
+	 */
+	abstract public function forget_section($section);
+
+	/**
+	 * Indicates if a key is sectionable.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	protected function sectionable($key)
+	{
+		return $this->implicit and $this->sectioned($key);
+	}
+
+	/**
+	 * Determine if a key is sectioned.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	protected function sectioned($key)
+	{
+		return str_contains($key, '::');
+	}
+
+	/**
+	 * Get the section and key from a sectioned key.
+	 *
+	 * @param  string  $key
+	 * @return array
+	 */
+	protected function parse($key)
+	{
+		return explode('::', $key, 2);
+	}
+
+}

+ 89 - 0
php-laravel/laravel/cache/drivers/wincache.php

@@ -0,0 +1,89 @@
+<?php namespace Laravel\Cache\Drivers;
+
+class WinCache extends Driver {
+
+	/**
+	 * The cache key from the cache configuration file.
+	 *
+	 * @var string
+	 */
+	protected $key;
+
+	/**
+	 * Create a new WinCache cache driver instance.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function __construct($key)
+	{
+		$this->key = $key;
+	}
+
+	/**
+	 * Determine if an item exists in the cache.
+	 *
+	 * @param  string  $key
+	 * @return bool
+	 */
+	public function has($key)
+	{
+		return ( ! is_null($this->get($key)));
+	}
+
+	/**
+	 * Retrieve an item from the cache driver.
+	 *
+	 * @param  string  $key
+	 * @return mixed
+	 */
+	protected function retrieve($key)
+	{
+		if (($cache = wincache_ucache_get($this->key.$key)) !== false)
+		{
+			return $cache;
+		}
+	}
+
+	/**
+	 * Write an item to the cache for a given number of minutes.
+	 *
+	 * <code>
+	 *		// Put an item in the cache for 15 minutes
+	 *		Cache::put('name', 'Taylor', 15);
+	 * </code>
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @param  int     $minutes
+	 * @return void
+	 */
+	public function put($key, $value, $minutes)
+	{
+		wincache_ucache_add($this->key.$key, $value, $minutes * 60);
+	}
+
+	/**
+	 * Write an item to the cache that lasts forever.
+	 *
+	 * @param  string  $key
+	 * @param  mixed   $value
+	 * @return void
+	 */
+	public function forever($key, $value)
+	{
+		return $this->put($key, $value, 0);
+	}
+
+	/**
+	 * Delete an item from the cache.
+	 *
+	 * @param  string  $key
+	 * @return void
+	 */
+	public function forget($key)
+	{
+		wincache_ucache_delete($this->key.$key);
+	}
+
+}

+ 50 - 0
php-laravel/laravel/cli/artisan.php

@@ -0,0 +1,50 @@
+<?php namespace Laravel\CLI; defined('DS') or die('No direct script access.');
+
+use Laravel\Bundle;
+use Laravel\Config;
+use Laravel\Request;
+
+/**
+ * Fire up the default bundle. This will ensure any dependencies that
+ * need to be registered in the IoC container are registered and that
+ * the auto-loader mappings are registered.
+ */
+Bundle::start(DEFAULT_BUNDLE);
+
+/**
+ * The default database connection may be set by specifying a value
+ * for the "database" CLI option. This allows migrations to be run
+ * conveniently for a test or staging database.
+ */
+
+if ( ! is_null($database = get_cli_option('db')))
+{
+	Config::set('database.default', $database);
+}
+
+/**
+ * We will register all of the Laravel provided tasks inside the IoC
+ * container so they can be resolved by the task class. This allows
+ * us to seamlessly add tasks to the CLI so that the Task class
+ * doesn't have to worry about how to resolve core tasks.
+ */
+require path('sys').'cli/dependencies'.EXT;
+
+/**
+ * We will wrap the command execution in a try / catch block and
+ * simply write out any exception messages we receive to the CLI
+ * for the developer. Note that this only writes out messages
+ * for the CLI exceptions. All others will not be caught
+ * and will be totally dumped out to the CLI.
+ */
+try
+{
+	Command::run(array_slice($arguments, 1));
+}
+catch (\Exception $e)
+{
+	echo $e->getMessage().PHP_EOL;
+	exit(1);
+}
+
+echo PHP_EOL;

+ 198 - 0
php-laravel/laravel/cli/command.php

@@ -0,0 +1,198 @@
+<?php namespace Laravel\CLI;
+
+use Laravel\IoC;
+use Laravel\Str;
+use Laravel\Bundle;
+
+class Command {
+
+	/**
+	 * Run a CLI task with the given arguments.
+	 *
+	 * <code>
+	 *		// Call the migrate artisan task
+	 *		Command::run(array('migrate'));
+	 *
+	 *		// Call the migrate task with some arguments
+	 *		Command::run(array('migrate:rollback', 'bundle-name'))
+	 * </code>
+	 *
+	 * @param  array  $arguments
+	 * @return void
+	 */
+	public static function run($arguments = array())
+	{
+		static::validate($arguments);
+
+		list($bundle, $task, $method) = static::parse($arguments[0]);
+
+		// If the task exists within a bundle, we will start the bundle so that any
+		// dependencies can be registered in the application IoC container. If the
+		// task is registered in the container,  we'll resolve it.
+		if (Bundle::exists($bundle))
+		{
+			Bundle::start($bundle);
+		}
+
+		$task = static::resolve($bundle, $task);
+
+		// Once the bundle has been resolved, we'll make sure we could actually
+		// find that task, and then verify that the method exists on the task
+		// so we can successfully call it without a problem.
+		if (is_null($task))
+		{
+			throw new \Exception("Sorry, I can't find that task.");
+		}
+
+		if (is_callable(array($task, $method)))
+		{
+			$task->$method(array_slice($arguments, 1));
+		}
+		else
+		{
+			throw new \Exception("Sorry, I can't find that method!");
+		}
+	}
+
+	/**
+	 * Determine if the given command arguments are valid.
+	 *
+	 * @param  array  $arguments
+	 * @return void
+	 */
+	protected static function validate($arguments)
+	{
+		if ( ! isset($arguments[0]))
+		{
+			throw new \Exception("You forgot to provide the task name.");
+		}
+	}
+
+	/**
+	 * Parse the task name to extract the bundle, task, and method.
+	 *
+	 * @param  string  $task
+	 * @return array
+	 */
+	protected static function parse($task)
+	{
+		list($bundle, $task) = Bundle::parse($task);
+
+		// Extract the task method from the task string. Methods are called
+		// on tasks by separating the task and method with a single colon.
+		// If no task is specified, "run" is used as the default.
+		if (str_contains($task, ':'))
+		{
+			list($task, $method) = explode(':', $task);
+		}
+		else
+		{
+			$method = 'run';
+		}
+
+		return array($bundle, $task, $method);
+	}
+
+	/**
+	 * Resolve an instance of the given task name.
+	 *
+	 * <code>
+	 *		// Resolve an instance of a task
+	 *		$task = Command::resolve('application', 'migrate');
+	 *
+	 *		// Resolve an instance of a task within a bundle
+	 *		$task = Command::resolve('bundle', 'foo');
+	 * </code>
+	 *
+	 * @param  string  $bundle
+	 * @param  string  $task
+	 * @return object
+	 */
+	public static function resolve($bundle, $task)
+	{
+		$identifier = Bundle::identifier($bundle, $task);
+
+		// First we'll check to see if the task has been registered in the
+		// application IoC container. This allows all dependencies to be
+		// injected into tasks for more flexible testability.
+		if (IoC::registered("task: {$identifier}"))
+		{
+			return IoC::resolve("task: {$identifier}");
+		}
+
+		// If the task file exists, we'll format the bundle and task name
+		// into a task class name and resolve an instance of the class so that
+		// the requested method may be executed.
+		if (file_exists($path = Bundle::path($bundle).'tasks/'.$task.EXT))
+		{
+			require_once $path;
+
+			$task = static::format($bundle, $task);
+
+			return new $task;
+		}
+	}
+
+	/**
+	 * Parse the command line arguments and return the results.
+	 *
+	 * @param  array  $argv
+	 * @return array
+	 */
+	public static function options($argv)
+	{
+		$options = array();
+
+		$arguments = array();
+
+		for ($i = 0, $count = count($argv); $i < $count; $i++)
+		{
+			$argument = $argv[$i];
+
+			// If the CLI argument starts with a double hyphen, it is an option,
+			// so we will extract the value and add it to the array of options
+			// to be returned by the method.
+			if (starts_with($argument, '--'))
+			{
+				// By default, we will assume the value of the options is true,
+				// but if the option contains an equals sign, we will take the
+				// value to the right of the equals sign as the value and
+				// remove the value from the option key.
+				list($key, $value) = array(substr($argument, 2), true);
+
+				if (($equals = strpos($argument, '=')) !== false)
+				{
+					$key = substr($argument, 2, $equals - 2);
+
+					$value = substr($argument, $equals + 1);
+				}
+
+				$options[$key] = $value;
+			}
+			// If the CLI argument does not start with a double hyphen it's
+			// simply an argument to be passed to the console task so we'll
+			// add it to the array of "regular" arguments.
+			else
+			{
+				$arguments[] = $argument;
+			}
+		}
+
+		return array($arguments, $options);
+	}
+
+	/**
+	 * Format a bundle and task into a task class name.
+	 *
+	 * @param  string  $bundle
+	 * @param  string  $task
+	 * @return string
+	 */
+	protected static function format($bundle, $task)
+	{
+		$prefix = Bundle::class_prefix($bundle);
+
+		return '\\'.$prefix.Str::classify($task).'_Task';
+	}
+
+}

Some files were not shown because too many files changed in this diff