diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..1d589555 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: php + +php: + - 5.3 + +script: "php artisan test:core" \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..94e2b12a --- /dev/null +++ b/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. \ No newline at end of file diff --git a/application/config/application.php b/application/config/application.php index 9f597954..60735a60 100755 --- a/application/config/application.php +++ b/application/config/application.php @@ -8,7 +8,7 @@ |-------------------------------------------------------------------------- | | 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 + | does not have to be set. If it isn't, we'll try our best to guess the URL | of your application. | */ @@ -48,7 +48,7 @@ | | This key is used by the encryption and cookie classes to generate secure | encrypted strings and hashes. It is extremely important that this key - | remain secret and should not be shared with anyone. Make it about 32 + | remains secret and it should not be shared with anyone. Make it about 32 | characters of random gibberish. | */ @@ -63,7 +63,7 @@ | 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.. + | disable the toolbar for production applications. | */ @@ -84,7 +84,7 @@ /* |-------------------------------------------------------------------------- - | Application Language + | Default Application Language |-------------------------------------------------------------------------- | | The default language of your application. This language will be used by @@ -94,12 +94,25 @@ '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 + | 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. | diff --git a/application/config/cache.php b/application/config/cache.php index a507ff66..5dc267e6 100644 --- a/application/config/cache.php +++ b/application/config/cache.php @@ -29,7 +29,7 @@ | 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 identifier our items. + | be polite and use a prefix to uniquely identify our items. | */ diff --git a/application/config/database.php b/application/config/database.php index d5e6ac1b..4aa6b592 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -35,7 +35,7 @@ | Default Database Connection |-------------------------------------------------------------------------- | - | The name of your default database connection. This connection will used + | 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. @@ -54,7 +54,7 @@ | 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 particlar database of + | so make sure you have the PDO drivers for your particular database of | choice installed on your machine. | */ @@ -85,6 +85,7 @@ 'password' => '', 'charset' => 'utf8', 'prefix' => '', + 'schema' => 'public', ), 'sqlsrv' => array( diff --git a/application/config/error.php b/application/config/error.php index 1713afce..c4d27fe4 100644 --- a/application/config/error.php +++ b/application/config/error.php @@ -9,7 +9,7 @@ | | 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 about them will be displayed. + | information about them will be displayed. | */ @@ -56,7 +56,7 @@ | logging is enabled. | | You may log the error message however you like; however, a simple log - | solution has been setup for you which will log all error messages to + | solution has been set up for you which will log all error messages to | text files within the application storage directory. | */ diff --git a/application/config/session.php b/application/config/session.php index ea686f89..dbfe8b27 100644 --- a/application/config/session.php +++ b/application/config/session.php @@ -23,7 +23,7 @@ | Session Database |-------------------------------------------------------------------------- | - | The database table on which the session should be stored. It probably + | 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. | diff --git a/application/config/strings.php b/application/config/strings.php index 5d94f81c..bbbe230c 100644 --- a/application/config/strings.php +++ b/application/config/strings.php @@ -8,7 +8,7 @@ |-------------------------------------------------------------------------- | | This array contains the singular and plural forms of words. It's used by - | the "singular" and "plural" methods on the Str class to convert a given + | 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. @@ -96,6 +96,8 @@ 'sheep', 'species', 'moose', + 'chassis', + 'traffic', ), /* @@ -185,4 +187,4 @@ ), -); \ No newline at end of file +); diff --git a/application/language/ar/pagination.php b/application/language/ar/pagination.php new file mode 100644 index 00000000..37135719 --- /dev/null +++ b/application/language/ar/pagination.php @@ -0,0 +1,19 @@ + '→ السابق', + 'next' => 'التالي ←', + +); \ No newline at end of file diff --git a/application/language/ar/validation.php b/application/language/ar/validation.php new file mode 100644 index 00000000..fb88f6d8 --- /dev/null +++ b/application/language/ar/validation.php @@ -0,0 +1,104 @@ + "القيمة :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(), + +); \ No newline at end of file diff --git a/application/language/bg/pagination.php b/application/language/bg/pagination.php new file mode 100644 index 00000000..2f4b150c --- /dev/null +++ b/application/language/bg/pagination.php @@ -0,0 +1,19 @@ + '« Назад', + 'next' => 'Напред »', + +); \ No newline at end of file diff --git a/application/language/bg/validation.php b/application/language/bg/validation.php new file mode 100644 index 00000000..c95b1ed3 --- /dev/null +++ b/application/language/bg/validation.php @@ -0,0 +1,104 @@ + "Трябва да приемете :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(), + +); \ No newline at end of file diff --git a/application/language/da/pagination.php b/application/language/da/pagination.php new file mode 100644 index 00000000..089ec7e0 --- /dev/null +++ b/application/language/da/pagination.php @@ -0,0 +1,19 @@ + '« Forrige', + 'next' => 'Næste »', + +); \ No newline at end of file diff --git a/application/language/da/validation.php b/application/language/da/validation.php new file mode 100644 index 00000000..b49b75ec --- /dev/null +++ b/application/language/da/validation.php @@ -0,0 +1,104 @@ + ":attribute skal accepteres.", + "active_url" => ":attribute er ikke en gyldig URL.", + "after" => ":attribute skal være en dato efter :date.", + "alpha" => ":attribute må kun indeholde bogstaver.", + "alpha_dash" => ":attribute må kun indeholde bogstaver, numre, og skråstreg.", + "alpha_num" => ":attribute må kun indeholde bogstaver og numre.", + "array" => ":attribute skal have valgte elementer.", + "before" => ":attribute skal have en dato før :date.", + "between" => array( + "numeric" => ":attribute skal være mellem :min - :max.", + "file" => ":attribute skal være mellem :min - :max kilobytes.", + "string" => ":attribute skal være mellem :min - :max karakterer.", + ), + "confirmed" => ":attribute bekræftelse stemmer ikke overens.", + "count" => ":attribute skal være præcis :count valgte elementer.", + "countbetween" => ":attribute skal væ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ære forskellige.", + "email" => "Formatet for :attribute er ugyldigt.", + "exists" => "Den valgte :attribute er ugyldig.", + "image" => ":attribute skal være et billede.", + "in" => "Den valgte :attribute er ugyldig.", + "integer" => ":attribute må kun indeholde tal.", + "ip" => ":attribute skal være en gyldig IP adresse.", + "match" => "Formatet for :attribute er ugyldigt.", + "max" => array( + "numeric" => ":attribute skal være mindre end :max.", + "file" => ":attribute skal være mindre end :max kilobytes.", + "string" => ":attribute skal være mindre end :max karakterer.", + ), + "mimes" => ":attribute skal have filtypen type: :values.", + "min" => array( + "numeric" => ":attribute ska minimum være :min.", + "file" => ":attribute skal være mindst :min kilobytes.", + "string" => ":attribute skal være mindst :min karakterer.", + ), + "not_in" => "Den valgte :attribute er ugyldig.", + "numeric" => ":attribute skal være et nummer.", + "required" => ":attribute er krævet.", + "same" => ":attribute og :other stemmer ikke overens.", + "size" => array( + "numeric" => ":attribute skal være :size.", + "file" => ":attribute skal være :size kilobyte.", + "string" => ":attribute skal væ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(), + +); \ No newline at end of file diff --git a/application/language/de/pagination.php b/application/language/de/pagination.php new file mode 100644 index 00000000..9fd96322 --- /dev/null +++ b/application/language/de/pagination.php @@ -0,0 +1,19 @@ + '« Zurück', + 'next' => 'Weiter »', + +); \ No newline at end of file diff --git a/application/language/de/validation.php b/application/language/de/validation.php new file mode 100644 index 00000000..cb41d00c --- /dev/null +++ b/application/language/de/validation.php @@ -0,0 +1,104 @@ + ":attribute muss akzeptiert werden.", + "active_url" => ":attribute ist keine gü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ä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ß sein.", + "string" => ":attribute muss zwischen :min und :max Zeichen lang sein.", + ), + "confirmed" => ":attribute stimmt nicht mit der Bestätigung überein.", + "count" => ":attribute muss genau :count ausgewählte Elemente haben.", + "countbetween" => ":attribute muss zwischen :min und :max ausgewählte Elemente haben.", + "countmax" => ":attribute muss weniger als :max ausgewählte Elemente haben.", + "countmin" => ":attribute muss mindestens :min ausgewählte Elemente haben.", + "different" => ":attribute und :other müssen verschieden sein.", + "email" => ":attribute ist keine gültige Email-Adresse.", + "exists" => "Der gewählte Wert für :attribute ist ungültig.", + "image" => ":attribute muss ein Bild sein.", + "in" => "Der gewählte Wert für :attribute ist ungültig.", + "integer" => ":attribute muss eine ganze Zahl sein.", + "ip" => ":attribute muss eine gültige IP-Adresse sein.", + "match" => ":attribute hat ein ungültiges Format.", + "max" => array( + "numeric" => ":attribute muss kleiner als :max sein.", + "file" => ":attribute muss kleiner als :max Kilobytes groß sein.", + "string" => ":attribute muss kürzer als :max Zeichen sein.", + ), + "mimes" => ":attribute muss den Dateityp :values haben.", + "min" => array( + "numeric" => ":attribute muss größer als :min sein.", + "file" => ":attribute muss größer als :min Kilobytes groß sein.", + "string" => ":attribute muss länger als :min Zeichen sein.", + ), + "not_in" => "Der gewählte Wert für :attribute ist ungültig.", + "numeric" => ":attribute muss eine Zahl sein.", + "required" => ":attribute muss ausgefüllt sein.", + "same" => ":attribute und :other müssen übereinstimmen.", + "size" => array( + "numeric" => ":attribute muss gleich :size sein.", + "file" => ":attribute muss :size Kilobyte groß sein.", + "string" => ":attribute muss :size Zeichen lang sein.", + ), + "unique" => ":attribute ist schon vergeben.", + "url" => "Das Format von :attribute ist ungü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(), + +); \ No newline at end of file diff --git a/application/language/el/pagination.php b/application/language/el/pagination.php new file mode 100644 index 00000000..1b0a53ae --- /dev/null +++ b/application/language/el/pagination.php @@ -0,0 +1,19 @@ + '« Προηγούμενο', + 'next' => 'Επόμενο »', + +); \ No newline at end of file diff --git a/application/language/el/validation.php b/application/language/el/validation.php new file mode 100644 index 00000000..f461ac0e --- /dev/null +++ b/application/language/el/validation.php @@ -0,0 +1,104 @@ + "Το πεδίο :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(), + +); \ No newline at end of file diff --git a/application/language/en/validation.php b/application/language/en/validation.php index aade5eda..e5116996 100644 --- a/application/language/en/validation.php +++ b/application/language/en/validation.php @@ -24,6 +24,7 @@ "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.", @@ -31,6 +32,10 @@ "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.", "different" => "The :attribute and :other must be different.", "email" => "The :attribute format is invalid.", "exists" => "The selected :attribute is invalid.", diff --git a/application/language/fr/pagination.php b/application/language/fr/pagination.php new file mode 100644 index 00000000..30b85534 --- /dev/null +++ b/application/language/fr/pagination.php @@ -0,0 +1,19 @@ + '« Précédent', + 'next' => 'Suivant »', + +); diff --git a/application/language/fr/validation.php b/application/language/fr/validation.php new file mode 100644 index 00000000..bbc0408f --- /dev/null +++ b/application/language/fr/validation.php @@ -0,0 +1,104 @@ + "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" => "The :attribute must have selected elements.", + "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" => "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" => "Les champ :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 :attribute doit être plus petit que :max.", + "file" => "Le :attribute doit être plus petit que :max kilo-octets.", + "string" => "Le :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 :min kilo-octets.", + "string" => "Le champ :attribute doit être 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" => "Le champ :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 à 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(), + +); diff --git a/application/language/gr/pagination.php b/application/language/gr/pagination.php new file mode 100644 index 00000000..1b0a53ae --- /dev/null +++ b/application/language/gr/pagination.php @@ -0,0 +1,19 @@ + '« Προηγούμενο', + 'next' => 'Επόμενο »', + +); \ No newline at end of file diff --git a/application/language/gr/validation.php b/application/language/gr/validation.php new file mode 100644 index 00000000..f461ac0e --- /dev/null +++ b/application/language/gr/validation.php @@ -0,0 +1,104 @@ + "Το πεδίο :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(), + +); \ No newline at end of file diff --git a/application/language/he/pagination.php b/application/language/he/pagination.php new file mode 100644 index 00000000..6d2684cd --- /dev/null +++ b/application/language/he/pagination.php @@ -0,0 +1,19 @@ + '→ אחורה', + 'next' => 'קדימה ←', + +); \ No newline at end of file diff --git a/application/language/he/validation.php b/application/language/he/validation.php new file mode 100644 index 00000000..f714dd8d --- /dev/null +++ b/application/language/he/validation.php @@ -0,0 +1,107 @@ + "חובה להסכים ל-: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 חייב להיות כתובת 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(), + +); \ No newline at end of file diff --git a/application/language/hu/pagination.php b/application/language/hu/pagination.php new file mode 100644 index 00000000..00104344 --- /dev/null +++ b/application/language/hu/pagination.php @@ -0,0 +1,19 @@ + '« Előző', + 'next' => 'Következő »', + +); \ No newline at end of file diff --git a/application/language/hu/validation.php b/application/language/hu/validation.php new file mode 100644 index 00000000..ee0e7145 --- /dev/null +++ b/application/language/hu/validation.php @@ -0,0 +1,104 @@ + "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(), + +); \ No newline at end of file diff --git a/application/language/id/pagination.php b/application/language/id/pagination.php new file mode 100644 index 00000000..7cdad20b --- /dev/null +++ b/application/language/id/pagination.php @@ -0,0 +1,19 @@ + '« Sebelumnya', + 'next' => 'Selanjutnya »', + +); \ No newline at end of file diff --git a/application/language/id/validation.php b/application/language/id/validation.php new file mode 100644 index 00000000..51d0178e --- /dev/null +++ b/application/language/id/validation.php @@ -0,0 +1,104 @@ + "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" => "The :attribute must have selected elements.", + "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" => "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" => "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(), + +); \ No newline at end of file diff --git a/application/language/ja/pagination.php b/application/language/ja/pagination.php new file mode 100644 index 00000000..47e9d3f2 --- /dev/null +++ b/application/language/ja/pagination.php @@ -0,0 +1,31 @@ + '« 前', + 'next' => '次 »', + +); diff --git a/application/language/ja/validation.php b/application/language/ja/validation.php new file mode 100644 index 00000000..19d5a1b3 --- /dev/null +++ b/application/language/ja/validation.php @@ -0,0 +1,147 @@ + ":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" => "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 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(), + +); diff --git a/application/language/nl/pagination.php b/application/language/nl/pagination.php new file mode 100644 index 00000000..0240af61 --- /dev/null +++ b/application/language/nl/pagination.php @@ -0,0 +1,19 @@ + '« Vorige', + 'next' => 'Volgende »', + +); diff --git a/application/language/nl/validation.php b/application/language/nl/validation.php new file mode 100644 index 00000000..92ebf53e --- /dev/null +++ b/application/language/nl/validation.php @@ -0,0 +1,95 @@ + "Het :attribute moet geaccepteerd zijn.", + "active_url" => "Het :attribute is geen geldige URL.", + "after" => "Het :attribute moet een datum na :date zijn.", + "alpha" => "Het :attribute mag alleen letters bevatten.", + "alpha_dash" => "Het :attribute mag alleen letters, nummers, onderstreep(_) en strepen(-) bevatten.", + "alpha_num" => "Het :attribute mag alleen letters en nummers bevatten.", + "array" => "Het :attribute moet geselecteerde elementen bevatten.", + "before" => "Het :attribute moet een datum voor :date zijn.", + "between" => array( + "numeric" => "Het :attribute moet tussen :min en :max zijn.", + "file" => "Het :attribute moet tussen :min en :max kilobytes zijn.", + "string" => "Het :attribute moet tussen :min en :max karakters zijn.", + ), + "confirmed" => "Het :attribute bevestiging komt niet overeen.", + "count" => "Het :attribute moet precies :count geselecteerde elementen bevatten.", + "countbetween" => "Het :attribute moet tussen :min en :max geselecteerde elementen bevatten.", + "countmax" => "Het :attribute moet minder dan :max geselecteerde elementen bevatten.", + "countmin" => "Het :attribute moet minimaal :min geselecteerde elementen bevatten.", + "different" => "Het :attribute en :other moeten verschillend zijn.", + "email" => "Het :attribute formaat is ongeldig.", + "exists" => "Het gekozen :attribute is al ingebruik.", + "image" => "Het :attribute moet een afbeelding zijn.", + "in" => "Het gekozen :attribute is ongeldig.", + "integer" => "Het :attribute moet een getal zijn.", + "ip" => "Het :attribute moet een geldig IP-adres zijn.", + "match" => "Het :attribute formaat is ongeldig.", + "max" => array( + "numeric" => "Het :attribute moet minder dan :max zijn.", + "file" => "Het :attribute moet minder dan :max kilobytes zijn.", + "string" => "Het :attribute moet minder dan :max karakters zijn.", + ), + "mimes" => "Het :attribute moet een bestand zijn van het bestandstype :values.", + "min" => array( + "numeric" => "Het :attribute moet minimaal :min zijn.", + "file" => "Het :attribute moet minimaal :min kilobytes zijn.", + "string" => "Het :attribute moet minimaal :min karakters zijn.", + ), + "not_in" => "Het :attribute formaat is ongeldig.", + "numeric" => "Het :attribute moet een nummer zijn.", + "required" => "Het :attribute veld is verplicht.", + "same" => "Het :attribute en :other moeten overeenkomen.", + "size" => array( + "numeric" => "Het :attribute moet :size zijn.", + "file" => "Het :attribute moet :size kilobyte zijn.", + "string" => "Het :attribute moet :size characters zijn.", + ), + "unique" => "Het :attribute is al in gebruik.", + "url" => "Het :attribute formaat is ongeldig.", + + /* + |-------------------------------------------------------------------------- + | 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(), + +); diff --git a/application/language/pl/pagination.php b/application/language/pl/pagination.php new file mode 100644 index 00000000..90536b95 --- /dev/null +++ b/application/language/pl/pagination.php @@ -0,0 +1,19 @@ + '« Poprzednia', + 'next' => 'Następna »', + +); \ No newline at end of file diff --git a/application/language/pl/validation.php b/application/language/pl/validation.php new file mode 100644 index 00000000..0ec36d57 --- /dev/null +++ b/application/language/pl/validation.php @@ -0,0 +1,104 @@ + ":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(), + +); \ No newline at end of file diff --git a/application/language/pt/pagination.php b/application/language/pt/pagination.php new file mode 100644 index 00000000..e6303530 --- /dev/null +++ b/application/language/pt/pagination.php @@ -0,0 +1,19 @@ + '« Anterior', + 'next' => 'Próxima »', + +); \ No newline at end of file diff --git a/application/language/pt/validation.php b/application/language/pt/validation.php new file mode 100644 index 00000000..6e98fb59 --- /dev/null +++ b/application/language/pt/validation.php @@ -0,0 +1,99 @@ + "O :attribute deve ser aceito.", + "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" => "O :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(), + +); \ No newline at end of file diff --git a/application/language/ru/validation.php b/application/language/ru/validation.php index e8ee3a13..8fd15f5c 100644 --- a/application/language/ru/validation.php +++ b/application/language/ru/validation.php @@ -24,6 +24,7 @@ "alpha" => "Поле :attribute может содержать только буквы.", "alpha_dash" => "Поле :attribute может содержать только буквы, цифры и тире.", "alpha_num" => "Поле :attribute может содержать только буквы и цифры.", + "array" => "The :attribute must have selected elements.", "before" => "Поле :attribute должно быть датой перед :date.", "between" => array( "numeric" => "Поле :attribute должно быть между :min и :max.", @@ -31,6 +32,10 @@ "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 уже существует.", diff --git a/application/language/tr/pagination.php b/application/language/tr/pagination.php new file mode 100644 index 00000000..fce594d6 --- /dev/null +++ b/application/language/tr/pagination.php @@ -0,0 +1,28 @@ + + * @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' => '« Önceki', + 'next' => 'Sonraki »', + +); \ No newline at end of file diff --git a/application/language/tr/validation.php b/application/language/tr/validation.php new file mode 100644 index 00000000..18cb0458 --- /dev/null +++ b/application/language/tr/validation.php @@ -0,0 +1,108 @@ + + * @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(), + +); \ No newline at end of file diff --git a/application/views/home/index.blade.php b/application/views/home/index.blade.php index ec7973d7..d3c9bf17 100644 --- a/application/views/home/index.blade.php +++ b/application/views/home/index.blade.php @@ -29,7 +29,7 @@

And the view sitting before you can be found at:

-
{{ path('app') }}views/home/index.php
+
{{ path('app') }}views/home/index.blade.php

Grow in knowledge.

diff --git a/artisan b/artisan index e5dfd7ef..2f3dbeb6 100644 --- a/artisan +++ b/artisan @@ -4,7 +4,7 @@ * Laravel - A PHP Framework For Web Artisans * * @package Laravel - * @version 3.2.3 + * @version 3.2.8 * @author Taylor Otwell * @link http://laravel.com */ diff --git a/bundles/docs/routes.php b/bundles/docs/routes.php index 334c652d..2a8561ff 100644 --- a/bundles/docs/routes.php +++ b/bundles/docs/routes.php @@ -38,7 +38,7 @@ function document_exists($page) } /** - * Attach the sidebar to the documentatoin template. + * Attach the sidebar to the documentation template. */ View::composer('docs::template', function($view) { @@ -68,7 +68,7 @@ function document_exists($page) // 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 - // display back out to the client for the requested doc page. + // displayed back out to the client for the requested doc page. if (is_null($page) and document_exists($file.'/home')) { $file .= '/home'; diff --git a/bundles/docs/views/template.blade.php b/bundles/docs/views/template.blade.php old mode 100644 new mode 100755 index 20bf601f..658895e4 --- a/bundles/docs/views/template.blade.php +++ b/bundles/docs/views/template.blade.php @@ -6,8 +6,8 @@ Laravel: A Framework For Web Artisans - {{ HTML::style('laravel/css/style.css') }} - {{ HTML::style('laravel/js/modernizr-2.5.3.min.js') }} + {{ HTML::style(URL::$base.'/laravel/css/style.css') }} + {{ HTML::script(URL::$base.'/laravel/js/modernizr-2.5.3.min.js') }}
@@ -28,7 +28,7 @@
{{ HTML::script('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js') }} - {{ HTML::script('laravel/js/prettify.js') }} - {{ HTML::script('laravel/js/scroll.js') }} + {{ HTML::script(URL::$base.'/laravel/js/prettify.js') }} + {{ HTML::script(URL::$base.'/laravel/js/scroll.js') }} - \ No newline at end of file + diff --git a/laravel/auth/drivers/driver.php b/laravel/auth/drivers/driver.php index 4a272ba4..db649d24 100644 --- a/laravel/auth/drivers/driver.php +++ b/laravel/auth/drivers/driver.php @@ -80,7 +80,7 @@ public function user() } /** - * Get the a given application user by ID. + * Get the given application user by ID. * * @param int $id * @return mixed @@ -192,7 +192,7 @@ protected function cookie($name, $value, $minutes) } /** - * Get session key name used to store the token. + * Get the session key name used to store the token. * * @return string */ diff --git a/laravel/auth/drivers/eloquent.php b/laravel/auth/drivers/eloquent.php index 8c1c6a80..35fe07d2 100644 --- a/laravel/auth/drivers/eloquent.php +++ b/laravel/auth/drivers/eloquent.php @@ -7,37 +7,50 @@ class Eloquent extends Driver { * * If the user is a guest, null should be returned. * - * @param int $id + * @param int|object $token * @return mixed|null */ - public function retrieve($id) + public function retrieve($token) { - if (filter_var($id, FILTER_VALIDATE_INT) !== false) + // 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($id); + return $this->model()->find($token); + } + else if (get_class($token) == Config::get('auth.model')) + { + return $token; } } /** * Attempt to log a user into the application. * - * @param array $arguments + * @param array $arguments * @return void */ public function attempt($arguments = array()) { - $username = Config::get('auth.username'); + $user = $this->model()->where(function($query) use($arguments) + { + $username = Config::get('auth.username'); + + $query->where($username, '=', $arguments['username']); - $user = $this->model()->where($username, '=', $arguments['username'])->first(); + foreach(array_except($arguments, array('username', 'password', 'remember')) as $column => $val) + { + $query->where($column, '=', $val); + } + })->first(); - // This driver uses a basic username and password authentication scheme - // so if the credentials match what is in the database we will just + // 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->get_attribute($password_field))) + if ( ! is_null($user) and Hash::check($password, $user->{$password_field})) { return $this->login($user->id, array_get($arguments, 'remember')); } @@ -57,4 +70,4 @@ protected function model() return new $model; } -} \ No newline at end of file +} diff --git a/laravel/auth/drivers/fluent.php b/laravel/auth/drivers/fluent.php index 4c23468b..b91b93ea 100644 --- a/laravel/auth/drivers/fluent.php +++ b/laravel/auth/drivers/fluent.php @@ -11,7 +11,7 @@ class Fluent extends Driver { * * If the user is a guest, null should be returned. * - * @param int $id + * @param int $id * @return mixed|null */ public function retrieve($id) @@ -25,15 +25,14 @@ public function retrieve($id) /** * Attempt to log a user into the application. * - * @param array $arguments + * @param array $arguments * @return void */ public function attempt($arguments = array()) { - $user = $this->get_user($arguments['username']); + $user = $this->get_user($arguments); - // This driver uses a basic username and password authentication scheme - // so if the credentials match what is in the database we will just + // 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']; @@ -48,18 +47,26 @@ public function attempt($arguments = array()) } /** - * Get the user from the database table by username. + * Get the user from the database table. * - * @param mixed $value + * @param array $arguments * @return mixed */ - protected function get_user($value) + protected function get_user($arguments) { $table = Config::get('auth.table'); - $username = Config::get('auth.username'); + return DB::table($table)->where(function($query) use($arguments) + { + $username = Config::get('auth.username'); + + $query->where($username, '=', $arguments['username']); - return DB::table($table)->where($username, '=', $value)->first(); + foreach(array_except($arguments, array('username', 'password', 'remember')) as $column => $val) + { + $query->where($column, '=', $val); + } + })->first(); } } diff --git a/laravel/autoloader.php b/laravel/autoloader.php index 68e423d2..4168e305 100644 --- a/laravel/autoloader.php +++ b/laravel/autoloader.php @@ -40,7 +40,7 @@ class Autoloader { /** * Load the file corresponding to a given class. * - * This method is registerd in the bootstrap file as an SPL auto-loader. + * This method is registered in the bootstrap file as an SPL auto-loader. * * @param string $class * @return void @@ -55,7 +55,7 @@ public static function load($class) return class_alias(static::$aliases[$class], $class); } - // All classes in Laravel are staticly mapped. There is no crazy search + // 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])) @@ -102,7 +102,7 @@ protected static function load_namespaced($class, $namespace, $directory) protected static function load_psr($class, $directory = null) { // The PSR-0 standard indicates that class namespaces and underscores - // should be used to indcate the directory tree in which the class + // 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); diff --git a/laravel/blade.php b/laravel/blade.php index 0deed20e..f0a520ab 100644 --- a/laravel/blade.php +++ b/laravel/blade.php @@ -68,7 +68,7 @@ public static function sharpen() // 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 $view->get(); + return ltrim($view->get()); }); } @@ -95,7 +95,6 @@ public static function extend(Closure $compiler) * * @param string $view * @param string $path - * @param string $compiled * @return bool */ public static function expired($view, $path) @@ -278,7 +277,7 @@ protected static function compile_structure_openings($value) */ protected static function compile_structure_closings($value) { - $pattern = '/(\s*)@(endif|endforeach|endfor|endwhile|break)(\s*)/'; + $pattern = '/(\s*)@(endif|endforeach|endfor|endwhile)(\s*)/'; return preg_replace($pattern, '$1$3', $value); } diff --git a/laravel/bundle.php b/laravel/bundle.php index 2259228e..382051ea 100644 --- a/laravel/bundle.php +++ b/laravel/bundle.php @@ -46,7 +46,7 @@ public static function register($bundle, $config = array()) // 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 who simply live in the root bundle directory. + // bundles that simply live in the root bundle directory. if (is_string($config)) { $bundle = $config; @@ -55,7 +55,7 @@ public static function register($bundle, $config = array()) } // If no location is set, we will set the location to match the name of - // the bundle. This is for bundles who are installed to the root 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'])) { @@ -66,7 +66,7 @@ public static function register($bundle, $config = array()) // It is possible for the developer to specify auto-loader mappings // directly on the bundle registration. This provides a convenient - // way to register mappings withuot a bootstrap. + // way to register mappings without a bootstrap. if (isset($config['autoloads'])) { static::autoloads($bundle, $config); @@ -74,7 +74,7 @@ public static function register($bundle, $config = array()) } /** - * Load a bundle by running it's start-up script. + * Load a bundle by running its start-up script. * * If the bundle has already been started, no action will be taken. * @@ -124,7 +124,7 @@ public static function routes($bundle) $path = static::path($bundle).'routes'.EXT; - // By setting the bundle property on the router the router knows what + // 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'); @@ -191,7 +191,7 @@ public static function handles($uri) foreach (static::$bundles as $key => $value) { - if (isset($value['handles']) and starts_with($uri, $value['handles'].'/')) + if (isset($value['handles']) and starts_with($uri, $value['handles'].'/') or $value['handles'] == '/') { return $key; } @@ -201,7 +201,7 @@ public static function handles($uri) } /** - * Deteremine if a bundle exists within the bundles directory. + * Determine if a bundle exists within the bundles directory. * * @param string $bundle * @return bool @@ -372,7 +372,7 @@ public static function resolve($bundle) } /** - * Parse a element identifier and return the bundle name and element. + * Parse an element identifier and return the bundle name and element. * * * // Returns array(null, 'admin.user') @@ -461,4 +461,16 @@ 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; + } + } \ No newline at end of file diff --git a/laravel/cache/drivers/driver.php b/laravel/cache/drivers/driver.php index c6abcb2e..5df317be 100644 --- a/laravel/cache/drivers/driver.php +++ b/laravel/cache/drivers/driver.php @@ -67,6 +67,7 @@ abstract public function put($key, $value, $minutes); * @param string $key * @param mixed $default * @param int $minutes + * @param string $function * @return mixed */ public function remember($key, $default, $minutes, $function = 'put') diff --git a/laravel/cache/drivers/memcached.php b/laravel/cache/drivers/memcached.php index 3e6a454d..5a324bf5 100644 --- a/laravel/cache/drivers/memcached.php +++ b/laravel/cache/drivers/memcached.php @@ -20,6 +20,7 @@ class Memcached extends Sectionable { * Create a new Memcached cache driver instance. * * @param Memcached $memcache + * @param string $key * @return void */ public function __construct(\Memcached $memcache, $key) diff --git a/laravel/cache/drivers/sectionable.php b/laravel/cache/drivers/sectionable.php index 4ec78246..93566989 100644 --- a/laravel/cache/drivers/sectionable.php +++ b/laravel/cache/drivers/sectionable.php @@ -63,6 +63,7 @@ public function forever_in_section($section, $key, $value) * @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') diff --git a/laravel/cli/artisan.php b/laravel/cli/artisan.php index 46886dc8..e7bd130e 100644 --- a/laravel/cli/artisan.php +++ b/laravel/cli/artisan.php @@ -34,7 +34,7 @@ * 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 be not be caught + * for the CLI exceptions. All others will not be caught * and will be totally dumped out to the CLI. */ try diff --git a/laravel/cli/command.php b/laravel/cli/command.php index 7b4ae3af..c6a25ee4 100644 --- a/laravel/cli/command.php +++ b/laravel/cli/command.php @@ -100,7 +100,7 @@ protected static function parse($task) * // Resolve an instance of a task * $task = Command::resolve('application', 'migrate'); * - * // Resolve an instance of a task wtihin a bundle + * // Resolve an instance of a task within a bundle * $task = Command::resolve('bundle', 'foo'); * * @@ -121,11 +121,11 @@ public static function resolve($bundle, $task) } // If the task file exists, we'll format the bundle and task name - // into a task class name and resolve an instance of the so that + // 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 $path; + require_once $path; $task = static::format($bundle, $task); diff --git a/laravel/cli/dependencies.php b/laravel/cli/dependencies.php index f0c59e81..2e7f23b6 100644 --- a/laravel/cli/dependencies.php +++ b/laravel/cli/dependencies.php @@ -125,4 +125,16 @@ { return new Tasks\Bundle\Providers\Github; }); +} + +/** + * The "help" task provides information about + * artisan usage. + */ +if(! IoC::registered('task: help')) +{ + IoC::singleton('task: help', function() + { + return new Tasks\Help; + }); } \ No newline at end of file diff --git a/laravel/cli/tasks/bundle/bundler.php b/laravel/cli/tasks/bundle/bundler.php index 9d369c21..7af60e07 100644 --- a/laravel/cli/tasks/bundle/bundler.php +++ b/laravel/cli/tasks/bundle/bundler.php @@ -49,7 +49,7 @@ public function install($bundles) // all of its registered dependencies as well. // // Each bundle provider implements the Provider interface and - // is repsonsible for retrieving the bundle source from its + // is responsible for retrieving the bundle source from its // hosting party and installing it into the application. $path = path('bundle').$this->path($bundle); @@ -135,7 +135,7 @@ protected function get($bundles) $responses[] = $bundle; - // We'll also get the bundle's declared dependenceis so they + // We'll also get the bundle's declared dependencies so they // can be installed along with the bundle, making it easy // to install a group of bundles. $dependencies = $this->get($bundle['dependencies']); diff --git a/laravel/cli/tasks/bundle/providers/provider.php b/laravel/cli/tasks/bundle/providers/provider.php index bf6401f7..8ac853ff 100644 --- a/laravel/cli/tasks/bundle/providers/provider.php +++ b/laravel/cli/tasks/bundle/providers/provider.php @@ -27,7 +27,7 @@ protected function zipball($url, $bundle, $path) // When installing a bundle from a Zip archive, we'll first clone // down the bundle zip into the bundles "working" directory so - // we have a spot to do all of our bundle extration work. + // we have a spot to do all of our bundle extraction work. $target = $work.'laravel-bundle.zip'; File::put($target, $this->download($url)); @@ -49,7 +49,7 @@ protected function zipball($url, $bundle, $path) // Once we have the latest modified directory, we should be // able to move its contents over into the bundles folder - // so the bundle will be usable by the develoepr. + // so the bundle will be usable by the developer. File::mvdir($latest, $path); File::rmdir($work.'zip'); @@ -73,7 +73,7 @@ protected function download($url) // zip that was put in the storage directory. if ($remote === false) { - throw new \Exception("Error downloading bundle [{$bundle}]."); + throw new \Exception("Error downloading the requested bundle."); } return $remote; diff --git a/laravel/cli/tasks/help.json b/laravel/cli/tasks/help.json new file mode 100644 index 00000000..3f614ad1 --- /dev/null +++ b/laravel/cli/tasks/help.json @@ -0,0 +1,78 @@ +{ + "Application Configuration": { + "key:generate": { + "description": "Generate a secure application key.", + "command": "php artisan key:generate" + } + }, + "Database Tables": { + "session:table": { + "description": "Generate a migration for the sessions database table.", + "command": "php artisan session:table" + } + }, + "Migrations": { + "migrate:install": { + "description": "Create the Laravel migration table.", + "command": "php artisan migrate:install" + }, + "migrate:make": { + "description": "Create a migration.", + "command": "php artisan migrate:make create_users_table" + }, + "migrate": { + "description": "Run outstanding migrations.", + "command": "php artisan migrate" + }, + "migrate:rollback": { + "description": "Roll back the most recent migration.", + "command": "php artisan migrate:rollback" + }, + "migrate:reset": { + "description": "Roll back all migrations.", + "command": "php artisan migrate:reset" + } + }, + "Bundles": { + "bundle:install": { + "description": "Install a bundle.", + "command": "php artisan bundle:install swiftmailer" + }, + "bundle:upgrade": { + "description": "Upgrade a bundle.", + "command": "php artisan bundle:upgrade swiftmailer" + }, + "bundle:publish": { + "description": "Publish all bundles' assets.", + "command": "php artisan bundle:publish" + } + }, + "Unit Testing": { + "test": { + "description": "Run the application's tests.", + "command": "php artisan test" + } + }, + "Routing": { + "route:call": { + "description": "Call a route.", + "command": "php artisan route:call get api/user/1" + } + }, + "Application Keys": { + "key:generate": { + "description": "Generate an application key.", + "command": "php artisan key:generade" + } + }, + "CLI Options": { + "--env=": { + "description": "Set the Laravel environment.", + "command": "php artisan task --env=local" + }, + "--database=": { + "description": "Set the default database connection.", + "command": "php artisan task --database=mysql" + } + } +} \ No newline at end of file diff --git a/laravel/cli/tasks/help.php b/laravel/cli/tasks/help.php new file mode 100644 index 00000000..929c4ff8 --- /dev/null +++ b/laravel/cli/tasks/help.php @@ -0,0 +1,34 @@ + $commands) + { + if($i++ != 0) echo PHP_EOL; + + echo PHP_EOL . "# $category" . PHP_EOL; + + foreach($commands as $command => $details) + { + echo PHP_EOL . str_pad($command, 20) . str_pad($details->description, 30); + } + } + } +} \ No newline at end of file diff --git a/laravel/cli/tasks/migrate/database.php b/laravel/cli/tasks/migrate/database.php index a6aae9d5..31fcf110 100644 --- a/laravel/cli/tasks/migrate/database.php +++ b/laravel/cli/tasks/migrate/database.php @@ -40,7 +40,7 @@ public function last() $table = $this->table(); // First we need to grab the last batch ID from the migration table, - // as this will allow us to grab the lastest batch of migrations + // as this will allow us to grab the latest batch of migrations // that need to be run for a rollback command. $id = $this->batch(); diff --git a/laravel/cli/tasks/migrate/migrator.php b/laravel/cli/tasks/migrate/migrator.php index 5bf7617b..4ab2ef05 100644 --- a/laravel/cli/tasks/migrate/migrator.php +++ b/laravel/cli/tasks/migrate/migrator.php @@ -151,7 +151,7 @@ public function install() $table->create(); // Migrations can be run for a specific bundle, so we'll use - // the bundle name and string migration name as an unique ID + // the bundle name and string migration name as a unique ID // for the migrations, allowing us to easily identify which // migrations have been run for each bundle. $table->string('bundle', 50); @@ -206,7 +206,7 @@ public function make($arguments = array()) // Once the migration has been created, we'll return the // migration file name so it can be used by the task - // consumer if necessary for futher work. + // consumer if necessary for further work. return $file; } @@ -223,7 +223,7 @@ protected function stub($bundle, $migration) $prefix = Bundle::class_prefix($bundle); - // The class name is formatted simialrly to tasks and controllers, + // The class name is formatted similarly to tasks and controllers, // where the bundle name is prefixed to the class if it is not in // the default "application" bundle. $class = $prefix.Str::classify($migration); diff --git a/laravel/cli/tasks/route.php b/laravel/cli/tasks/route.php index 494d5ba0..b30d467c 100644 --- a/laravel/cli/tasks/route.php +++ b/laravel/cli/tasks/route.php @@ -14,7 +14,7 @@ class Route extends Task { */ public function call($arguments = array()) { - if ( ! count($arguments) == 2) + if ( count($arguments) != 2) { throw new \Exception("Please specify a request method and URI."); } @@ -41,7 +41,7 @@ protected function route() // We'll call the router using the method and URI specified by // the developer on the CLI. If a route is found, we will not // run the filters, but simply dump the result. - $route = Router::route(Request::method(), URI::current()); + $route = Router::route(Request::method(), $_SERVER['REQUEST_URI']); if ( ! is_null($route)) { @@ -53,4 +53,4 @@ protected function route() } } -} \ No newline at end of file +} diff --git a/laravel/cli/tasks/test/phpunit.php b/laravel/cli/tasks/test/phpunit.php index 67644838..32eadd58 100644 --- a/laravel/cli/tasks/test/phpunit.php +++ b/laravel/cli/tasks/test/phpunit.php @@ -1,12 +1,4 @@ - * @link http://laravel.com - */ // -------------------------------------------------------------- // Define the directory separator for the environment. @@ -18,22 +10,6 @@ // -------------------------------------------------------------- require 'paths.php'; -// -------------------------------------------------------------- -// Override the application paths when testing the core. -// -------------------------------------------------------------- -$config = file_get_contents('phpunit.xml'); - -if (strpos($config, 'laravel-tests') !== false) -{ - $path = path('bundle').'laravel-tests'.DS; - - set_path('app', $path.'application'.DS); - - set_path('bundle', $path.'bundles'.DS); - - set_path('storage', $path.'storage'.DS); -} - // -------------------------------------------------------------- // Bootstrap the Laravel core. // -------------------------------------------------------------- diff --git a/laravel/cli/tasks/test/runner.php b/laravel/cli/tasks/test/runner.php index 85787896..0d9fb4e6 100644 --- a/laravel/cli/tasks/test/runner.php +++ b/laravel/cli/tasks/test/runner.php @@ -7,9 +7,19 @@ class Runner extends Task { + /** + * The base directory where the tests will be executed. + * + * A phpunit.xml should also be stored in that directory. + * + * @var string + */ + protected $base_path; + /** * Run all of the unit tests for the application. * + * @param array $bundles * @return void */ public function run($bundles = array()) @@ -26,17 +36,8 @@ public function run($bundles = array()) */ public function core() { - if ( ! is_dir(path('bundle').'laravel-tests')) - { - throw new \Exception("The bundle [laravel-tests] has not been installed!"); - } - - // When testing the Laravel core, we will just stub the path directly - // so the test bundle is not required to be registered in the bundle - // configuration, as it is kind of a unique bundle. - $this->stub(path('bundle').'laravel-tests/cases'); - - $path = path('bundle').'laravel-tests/'; + $this->base_path = path('sys').'tests'.DS; + $this->stub(path('sys').'tests'.DS.'cases'); $this->test(); } @@ -54,6 +55,8 @@ public function bundle($bundles = array()) $bundles = Bundle::names(); } + $this->base_path = path('sys').'cli'.DS.'tasks'.DS.'test'.DS; + foreach ($bundles as $bundle) { // To run PHPUnit for the application, bundles, and the framework @@ -77,13 +80,20 @@ public function bundle($bundles = array()) protected function test() { // We'll simply fire off PHPUnit with the configuration switch - // pointing to our temporary configuration file. This allows + // pointing to our requested configuration file. This allows // us to flexibly run tests for any setup. - $path = path('base').'phpunit.xml'; + $path = 'phpunit.xml'; + + // fix the spaced directories problem when using the command line + // strings with spaces inside should be wrapped in quotes. + $esc_path = escapeshellarg($path); - passthru('phpunit --configuration '.$path); + passthru('phpunit --configuration '.$esc_path, $status); @unlink($path); + + // Pass through the exit status + exit($status); } /** @@ -103,7 +113,7 @@ protected function stub($directory) // locations depending on what the developer wants to test. foreach (array('bootstrap', 'directory') as $item) { - $stub = $this->{"swap_{$item}"}($stub, $path, $directory); + $stub = $this->{"swap_{$item}"}($stub, $directory); } File::put(path('base').'phpunit.xml', $stub); @@ -113,24 +123,22 @@ protected function stub($directory) * Swap the bootstrap file in the stub. * * @param string $stub - * @param string $path * @param string $directory * @return string */ - protected function swap_bootstrap($stub, $path, $directory) + protected function swap_bootstrap($stub, $directory) { - return str_replace('{{bootstrap}}', $path.'phpunit.php', $stub); + return str_replace('{{bootstrap}}', $this->base_path.'phpunit.php', $stub); } /** * Swap the directory in the stub. * * @param string $stub - * @param string $path * @param string $directory * @return string */ - protected function swap_directory($stub, $path, $directory) + protected function swap_directory($stub, $directory) { return str_replace('{{directory}}', $directory, $stub); } diff --git a/laravel/config.php b/laravel/config.php index 50bd7dc8..ac46693b 100644 --- a/laravel/config.php +++ b/laravel/config.php @@ -73,7 +73,7 @@ public static function get($key, $default = null) $items = static::$items[$bundle][$file]; // If a specific configuration item was not requested, the key will be null, - // meaning we'll to return the entire array of configuration item from the + // meaning we'll return the entire array of configuration items from the // requested configuration file. Otherwise we can return the item. if (is_null($item)) { @@ -175,7 +175,7 @@ public static function load($bundle, $file) // requested. This allows many types of config "drivers". $config = Event::first(static::loader, func_get_args()); - // If configuration items were actually found for the bundle and file we + // If configuration items were actually found for the bundle and file, we // will add them to the configuration array and return true, otherwise // we will return false indicating the file was not found. if (count($config) > 0) diff --git a/laravel/cookie.php b/laravel/cookie.php index 1f79a69b..1c3b5873 100644 --- a/laravel/cookie.php +++ b/laravel/cookie.php @@ -3,7 +3,7 @@ class Cookie { /** - * How long is forever (in minutes). + * How long is forever (in minutes)? * * @var int */ @@ -77,7 +77,7 @@ public static function put($name, $value, $expiration = 0, $path = '/', $domain // If the secure option is set to true, yet the request is not over HTTPS // we'll throw an exception to let the developer know that they are - // attempting to send a secure cookie over the unsecure HTTP. + // attempting to send a secure cookie over the insecure HTTP. if ($secure and ! Request::secure()) { throw new \Exception("Attempting to set secure cookie over HTTP."); @@ -120,4 +120,4 @@ public static function forget($name, $path = '/', $domain = null, $secure = fals return static::put($name, null, -2000, $path, $domain, $secure); } -} \ No newline at end of file +} diff --git a/laravel/core.php b/laravel/core.php index a38bf9dd..0f33ccfd 100644 --- a/laravel/core.php +++ b/laravel/core.php @@ -17,6 +17,20 @@ define('DEFAULT_BUNDLE', 'application'); define('MB_STRING', (int) function_exists('mb_get_info')); +/* +|-------------------------------------------------------------------------- +| Start Output Buffering +|-------------------------------------------------------------------------- +| +| Output buffering allows us to capture all output at any time, so that we +| can discard it or treat it accordingly. An example of this is if you have +| echoed a string, but want to return a Redirect object. Because Symfony +| only checks if headers have been sent, your redirect just silently fails. +| +*/ + +ob_start('mb_output_handler'); + /* |-------------------------------------------------------------------------- | Require Core Classes @@ -147,7 +161,7 @@ | Determine The Application Environment |-------------------------------------------------------------------------- | -| Next we're ready to determine the application environment. This may be +| Next, we're ready to determine the application environment. This may be | set either via the command line options or via the mapping of URIs to | environments that lives in the "paths.php" file for the application | and is parsed. When determining the CLI environment, the "--env" @@ -178,7 +192,7 @@ | | Once we have determined the application environment, we will set it on | the global server array of the HttpFoundation request. This makes it -| available throughout the application, thought it is mainly only +| available throughout the application, though it is mainly only | used to determine which configuration files to merge in. | */ @@ -216,7 +230,7 @@ |-------------------------------------------------------------------------- | | Finally we will register all of the bundles that have been defined for -| the application. None of them will be started yet, but will be setup +| the application. None of them will be started yet, but will be set up | so that they may be started by the developer at any time. | */ diff --git a/laravel/database.php b/laravel/database.php index 57f8d2c1..c5e28ac2 100644 --- a/laravel/database.php +++ b/laravel/database.php @@ -1,5 +1,6 @@ fetch($statement, Config::get('database.fetch')); } @@ -194,7 +194,7 @@ public function query($sql, $bindings = array()) return $statement->rowCount(); } // For insert statements that use the "returning" clause, which is allowed - // by databsae systems such as Postgres, we need to actually return the + // by database systems such as Postgres, we need to actually return the // real query result so the consumer can get the ID. elseif (stripos($sql, 'insert') === 0 and stripos($sql, 'returning') !== false) { @@ -209,7 +209,7 @@ public function query($sql, $bindings = array()) /** * Execute a SQL query against the connection. * - * The PDO statement and boolean result will be return in an array. + * The PDO statement and boolean result will be returned in an array. * * @param string $sql * @param array $bindings @@ -265,7 +265,7 @@ protected function execute($sql, $bindings = array()) throw $exception; } - // Once we have execute the query, we log the SQL, bindings, and + // Once we have executed the query, we log the SQL, bindings, and // execution time in a static array that is accessed by all of // the connections actively being used by the application. if (Config::get('database.profile')) @@ -287,7 +287,7 @@ protected function fetch($statement, $style) { // If the fetch style is "class", we'll hydrate an array of PHP // stdClass objects as generic containers for the query rows, - // otherwise we'll just use the fetch styel value. + // otherwise we'll just use the fetch style value. if ($style === PDO::FETCH_CLASS) { return $statement->fetchAll(PDO::FETCH_CLASS, 'stdClass'); diff --git a/laravel/database/connectors/postgres.php b/laravel/database/connectors/postgres.php index 3721f368..d4a54344 100644 --- a/laravel/database/connectors/postgres.php +++ b/laravel/database/connectors/postgres.php @@ -44,6 +44,13 @@ public function connect($config) $connection->prepare("SET NAMES '{$config['charset']}'")->execute(); } + // If a schema has been specified, we'll execute a query against + // the database to set the search path. + if (isset($config['schema'])) + { + $connection->prepare("SET search_path TO '{$config['schema']}'")->execute(); + } + return $connection; } diff --git a/laravel/database/connectors/sqlserver.php b/laravel/database/connectors/sqlserver.php index 29c6929b..04d9d770 100644 --- a/laravel/database/connectors/sqlserver.php +++ b/laravel/database/connectors/sqlserver.php @@ -28,8 +28,16 @@ public function connect($config) // also be used to connect to Azure SQL Server databases. The port is defined // directly after the server name, so we'll create that first. $port = (isset($port)) ? ','.$port : ''; - - $dsn = "sqlsrv:Server={$host}{$port};Database={$database}"; + + //check for dblib for mac users connecting to mssql (utilizes freetds) + if (!empty($dsn_type) and $dsn_type == 'dblib') + { + $dsn = "dblib:host={$host}{$port};dbname={$database}"; + } + else + { + $dsn = "sqlsrv:Server={$host}{$port};Database={$database}"; + } return new PDO($dsn, $username, $password, $this->options($config)); } diff --git a/laravel/database/eloquent/model.php b/laravel/database/eloquent/model.php index 2ad1c72b..c2566496 100644 --- a/laravel/database/eloquent/model.php +++ b/laravel/database/eloquent/model.php @@ -218,9 +218,11 @@ public static function update($id, $attributes) { $model = new static(array(), true); - if (static::$timestamps) $attributes['updated_at'] = new \DateTime; + $model->fill($attributes); - return $model->query()->where($model->key(), '=', $id)->update($attributes); + if (static::$timestamps) $model->timestamp(); + + return $model->query()->where($model->key(), '=', $id)->update($model->attributes); } /** @@ -253,27 +255,7 @@ public static function all() */ public function _with($includes) { - $includes = (array) $includes; - - $all_includes = array(); - - foreach($includes as $include) - { - $nested = explode('.', $include); - - $inc = array(); - - foreach($nested as $relation) - { - $inc[] = $relation; - - $all_includes[] = implode('.', $inc); - } - - } - - //remove duplicates and reset the array keys. - $this->includes = array_values(array_unique($all_includes)); + $this->includes = (array) $includes; return $this; } @@ -463,13 +445,23 @@ public function delete() * * @return void */ - protected function timestamp() + public function timestamp() { $this->updated_at = new \DateTime; if ( ! $this->exists) $this->created_at = $this->updated_at; } + /** + *Updates the timestamp on the model and immediately saves it. + * + * @return void + */ + public function touch(){ + $this->timestamp(); + $this->save(); + } + /** * Get a new fluent query builder instance for the model. * @@ -500,7 +492,7 @@ final public function sync() */ public function changed($attribute) { - return array_get($this->attributes, $attribute) !== array_get($this->original, $attribute); + return array_get($this->attributes, $attribute) != array_get($this->original, $attribute); } /** @@ -635,6 +627,8 @@ public function to_array() // to_array method, keying them both by name and ID. elseif (is_array($models)) { + $attributes[$name] = array(); + foreach ($models as $id => $model) { $attributes[$name][$id] = $model->to_array(); diff --git a/laravel/database/eloquent/pivot.php b/laravel/database/eloquent/pivot.php index d2878bb5..a90d7e7d 100644 --- a/laravel/database/eloquent/pivot.php +++ b/laravel/database/eloquent/pivot.php @@ -26,7 +26,7 @@ class Pivot extends Model { public function __construct($table, $connection = null) { $this->pivot_table = $table; - $this->connection = $connection; + static::$connection = $connection; parent::__construct(array(), true); } @@ -41,14 +41,4 @@ public function table() return $this->pivot_table; } - /** - * Get the connection used by the pivot table. - * - * @return string - */ - public function connection() - { - return $this->connection; - } - } \ No newline at end of file diff --git a/laravel/database/eloquent/relationships/has_many_and_belongs_to.php b/laravel/database/eloquent/relationships/has_many_and_belongs_to.php index 52276a5f..e46d5f96 100644 --- a/laravel/database/eloquent/relationships/has_many_and_belongs_to.php +++ b/laravel/database/eloquent/relationships/has_many_and_belongs_to.php @@ -85,12 +85,14 @@ public function results() /** * Insert a new record into the joining table of the association. * - * @param int $id - * @param array $joining + * @param Model|int $id + * @param array $attributes * @return bool */ public function attach($id, $attributes = array()) { + if ($id instanceof Model) $id = $id->get_key(); + $joining = array_merge($this->join_record($id), $attributes); return $this->insert_joining($joining); @@ -99,12 +101,13 @@ public function attach($id, $attributes = array()) /** * Detach a record from the joining table of the association. * - * @param int $ids + * @param array|Model|int $ids * @return bool */ public function detach($ids) { - if ( ! is_array($ids)) $ids = array($ids); + if ($ids instanceof Model) $ids = array($ids->get_key()); + elseif ( ! is_array($ids)) $ids = array($ids); return $this->pivot()->where_in($this->other_key(), $ids)->delete(); } diff --git a/laravel/database/eloquent/relationships/has_one_or_many.php b/laravel/database/eloquent/relationships/has_one_or_many.php index a8268de6..e7bfc0b0 100644 --- a/laravel/database/eloquent/relationships/has_one_or_many.php +++ b/laravel/database/eloquent/relationships/has_one_or_many.php @@ -7,16 +7,25 @@ class Has_One_Or_Many extends Relationship { /** * Insert a new record for the association. * + * If save is successful, the model will be returned, otherwise false. + * * @param Model|array $attributes - * @return bool + * @return Model|false */ public function insert($attributes) { - $attributes = ($attributes instanceof Model) ? $attributes->attributes : $attributes; + if ($attributes instanceof Model) + { + $attributes->set_attribute($this->foreign_key(), $this->base->get_key()); + + return $attributes->save() ? $attributes : false; + } + else + { + $attributes[$this->foreign_key()] = $this->base->get_key(); - $attributes[$this->foreign_key()] = $this->base->get_key(); - - return $this->model->create($attributes); + return $this->model->create($attributes); + } } /** diff --git a/laravel/database/grammar.php b/laravel/database/grammar.php index 13d92d8e..0ff5bd14 100644 --- a/laravel/database/grammar.php +++ b/laravel/database/grammar.php @@ -35,7 +35,7 @@ public function __construct(Connection $connection) */ public function wrap_table($table) { - // Expressions should be injected into the query as raw strings so + // Expressions should be injected into the query as raw strings // so we do not want to wrap them in any way. We will just return // the string value from the expression to be included. if ($table instanceof Expression) @@ -64,7 +64,7 @@ public function wrap_table($table) */ public function wrap($value) { - // Expressions should be injected into the query as raw strings so + // Expressions should be injected into the query as raw strings // so we do not want to wrap them in any way. We will just return // the string value from the expression to be included. if ($value instanceof Expression) diff --git a/laravel/database/query.php b/laravel/database/query.php index 83c92b83..fa6a4c8c 100644 --- a/laravel/database/query.php +++ b/laravel/database/query.php @@ -621,7 +621,7 @@ public function lists($column, $key = null) // set the keys on the array of values using the array_combine // function provided by PHP, which should give us the proper // array form to return from the method. - if ( ! is_null($key)) + if ( ! is_null($key) && count($results)) { return array_combine(array_map(function($row) use ($key) { diff --git a/laravel/database/query/grammars/grammar.php b/laravel/database/query/grammars/grammar.php index 65c62cf3..3e828cff 100644 --- a/laravel/database/query/grammars/grammar.php +++ b/laravel/database/query/grammars/grammar.php @@ -13,7 +13,7 @@ class Grammar extends \Laravel\Database\Grammar { public $datetime = 'Y-m-d H:i:s'; /** - * All of the query componenets in the order they should be built. + * All of the query components in the order they should be built. * * @var array */ @@ -125,7 +125,7 @@ protected function from(Query $query) protected function joins(Query $query) { // We need to iterate through each JOIN clause that is attached to the - // query an translate it into SQL. The table and the columns will be + // query and translate it into SQL. The table and the columns will be // wrapped in identifiers to avoid naming collisions. foreach ($query->joins as $join) { @@ -135,7 +135,7 @@ protected function joins(Query $query) // Each JOIN statement may have multiple clauses, so we will iterate // through each clause creating the conditions then we'll join all - // of the together at the end to build the clause. + // of them together at the end to build the clause. foreach ($join->clauses as $clause) { extract($clause); @@ -149,7 +149,7 @@ protected function joins(Query $query) // The first clause will have a connector on the front, but it is // not needed on the first condition, so we will strip it off of - // the condition before adding it to the arrya of joins. + // the condition before adding it to the array of joins. $search = array('AND ', 'OR '); $clauses[0] = str_replace($search, '', $clauses[0]); @@ -343,7 +343,7 @@ protected function offset(Query $query) } /** - * Compile a SQL INSERT statment from a Query instance. + * Compile a SQL INSERT statement from a Query instance. * * This method handles the compilation of single row inserts and batch inserts. * @@ -366,7 +366,7 @@ public function insert(Query $query, $values) $columns = $this->columnize(array_keys(reset($values))); // Build the list of parameter place-holders of values bound to the query. - // Each insert should have the same number of bound paramters, so we can + // Each insert should have the same number of bound parameters, so we can // just use the first array of values. $parameters = $this->parameterize(reset($values)); @@ -376,7 +376,7 @@ public function insert(Query $query, $values) } /** - * Compile a SQL INSERT and get ID statment from a Query instance. + * Compile a SQL INSERT and get ID statement from a Query instance. * * @param Query $query * @param array $values @@ -389,7 +389,7 @@ public function insert_get_id(Query $query, $values, $column) } /** - * Compile a SQL UPDATE statment from a Query instance. + * Compile a SQL UPDATE statement from a Query instance. * * @param Query $query * @param array $values @@ -410,13 +410,13 @@ public function update(Query $query, $values) $columns = implode(', ', $columns); // UPDATE statements may be constrained by a WHERE clause, so we'll run - // the entire where compilation process for those contraints. This is + // the entire where compilation process for those constraints. This is // easily achieved by passing it to the "wheres" method. return trim("UPDATE {$table} SET {$columns} ".$this->wheres($query)); } /** - * Compile a SQL DELETE statment from a Query instance. + * Compile a SQL DELETE statement from a Query instance. * * @param Query $query * @return string diff --git a/laravel/database/query/grammars/postgres.php b/laravel/database/query/grammars/postgres.php index 002b4cc7..6041ae82 100644 --- a/laravel/database/query/grammars/postgres.php +++ b/laravel/database/query/grammars/postgres.php @@ -5,7 +5,7 @@ class Postgres extends Grammar { /** - * Compile a SQL INSERT and get ID statment from a Query instance. + * Compile a SQL INSERT and get ID statement from a Query instance. * * @param Query $query * @param array $values diff --git a/laravel/database/query/grammars/sqlserver.php b/laravel/database/query/grammars/sqlserver.php index def519a5..f912f562 100644 --- a/laravel/database/query/grammars/sqlserver.php +++ b/laravel/database/query/grammars/sqlserver.php @@ -95,7 +95,7 @@ protected function ansi_offset(Query $query, $components) // Next we need to calculate the constraint that should be placed on // the row number to get the correct offset and limit on the query. - // If there is not limit, we'll just handle the offset. + // If there is not a limit, we'll just handle the offset. if ($query->limit > 0) { $finish = $query->offset + $query->limit; diff --git a/laravel/database/schema.php b/laravel/database/schema.php index c7e56309..e09b8b16 100644 --- a/laravel/database/schema.php +++ b/laravel/database/schema.php @@ -40,6 +40,25 @@ public static function create($table, $callback) return static::execute($table); } + /** + * Rename a database table in the schema. + * + * @param string $table + * @param string $new_name + * @return void + */ + public static function rename($table, $new_name) + { + $table = new Schema\Table($table); + + // To indicate that the table needs to be renamed, we will run the + // "rename" command on the table instance and pass the instance to + // the execute method as calling a Closure isn't needed. + $table->rename($new_name); + + return static::execute($table); + } + /** * Drop a database table from the schema. * @@ -71,7 +90,7 @@ public static function execute($table) { // The implications method is responsible for finding any fluently // defined indexes on the schema table and adding the explicit - // commands that are needed to tbe schema instance. + // commands that are needed for the schema instance. static::implications($table); foreach ($table->commands as $command) @@ -171,4 +190,4 @@ public static function grammar(Connection $connection) throw new \Exception("Schema operations not supported for [$driver]."); } -} \ No newline at end of file +} diff --git a/laravel/database/schema/grammars/grammar.php b/laravel/database/schema/grammars/grammar.php index da93aa64..c33d8dd7 100644 --- a/laravel/database/schema/grammars/grammar.php +++ b/laravel/database/schema/grammars/grammar.php @@ -9,7 +9,7 @@ abstract class Grammar extends \Laravel\Database\Grammar { * Generate the SQL statement for creating a foreign key. * * @param Table $table - * @param Command $command + * @param Fluent $command * @return string */ public function foreign(Table $table, Fluent $command) @@ -50,11 +50,23 @@ public function foreign(Table $table, Fluent $command) return $sql; } + /** + * Generate the SQL statement for a drop table command. + * + * @param Table $table + * @param Fluent $command + * @return string + */ + public function drop(Table $table, Fluent $command) + { + return 'DROP TABLE '.$this->wrap($table); + } + /** * Drop a constraint from the table. * * @param Table $table - * @param Fluent $fluent + * @param Fluent $command * @return string */ protected function drop_constraint(Table $table, Fluent $command) @@ -96,4 +108,19 @@ protected function type(Fluent $column) return $this->{'type_'.$column->type}($column); } + /** + * Format a value so that it can be used in SQL DEFAULT clauses. + * @param mixed $value + * @return string + */ + protected function default_value($value) + { + if (is_bool($value)) + { + return intval($value); + } + + return strval($value); + } + } \ No newline at end of file diff --git a/laravel/database/schema/grammars/mysql.php b/laravel/database/schema/grammars/mysql.php index d0ba45ad..93b22a4e 100644 --- a/laravel/database/schema/grammars/mysql.php +++ b/laravel/database/schema/grammars/mysql.php @@ -37,7 +37,7 @@ public function create(Table $table, Fluent $command) } /** - * Geenrate the SQL statements for a table modification command. + * Generate the SQL statements for a table modification command. * * @param Table $table * @param Fluent $command @@ -47,7 +47,7 @@ public function add(Table $table, Fluent $command) { $columns = $this->columns($table); - // Once we the array of column definitions, we need to add "add" to the + // Once we have the array of column definitions, we need to add "add" to the // front of each definition, then we'll concatenate the definitions // using commas like normal and generate the SQL. $columns = implode(', ', array_map(function($column) @@ -99,7 +99,7 @@ protected function columns(Table $table) */ protected function unsigned(Table $table, Fluent $column) { - if ($column->type == 'integer' && $column->unsigned) + if ($column->type == 'integer' && ($column->unsigned || $column->increment)) { return ' UNSIGNED'; } @@ -128,7 +128,7 @@ protected function defaults(Table $table, Fluent $column) { if ( ! is_null($column->default)) { - return " DEFAULT '".$column->default."'"; + return " DEFAULT '".$this->default_value($column->default)."'"; } } @@ -143,7 +143,7 @@ protected function incrementer(Table $table, Fluent $column) { if ($column->type == 'integer' and $column->increment) { - return ' UNSIGNED AUTO_INCREMENT PRIMARY KEY'; + return ' AUTO_INCREMENT PRIMARY KEY'; } } @@ -213,15 +213,15 @@ protected function key(Table $table, Fluent $command, $type) } /** - * Generate the SQL statement for a drop table command. + * Generate the SQL statement for a rename table command. * * @param Table $table * @param Fluent $command * @return string */ - public function drop(Table $table, Fluent $command) + public function rename(Table $table, Fluent $command) { - return 'DROP TABLE '.$this->wrap($table); + return 'RENAME TABLE '.$this->wrap($table).' TO '.$this->wrap($command->name); } /** @@ -260,7 +260,7 @@ public function drop_primary(Table $table, Fluent $command) } /** - * Generate the SQL statement for a drop unqique key command. + * Generate the SQL statement for a drop unique key command. * * @param Table $table * @param Fluent $command @@ -284,7 +284,7 @@ public function drop_fulltext(Table $table, Fluent $command) } /** - * Generate the SQL statement for a drop unqique key command. + * Generate the SQL statement for a drop unique key command. * * @param Table $table * @param Fluent $command @@ -311,7 +311,7 @@ protected function drop_key(Table $table, Fluent $command) * Drop a foreign key constraint from the table. * * @param Table $table - * @param Fluent $fluent + * @param Fluent $command * @return string */ public function drop_foreign(Table $table, Fluent $command) @@ -353,7 +353,7 @@ protected function type_float(Fluent $column) } /** - * Generate the data-type definintion for a decimal. + * Generate the data-type definition for a decimal. * * @param Fluent $column * @return string @@ -371,7 +371,7 @@ protected function type_decimal(Fluent $column) */ protected function type_boolean(Fluent $column) { - return 'TINYINT'; + return 'TINYINT(1)'; } /** @@ -418,4 +418,4 @@ protected function type_blob(Fluent $column) return 'BLOB'; } -} \ No newline at end of file +} diff --git a/laravel/database/schema/grammars/postgres.php b/laravel/database/schema/grammars/postgres.php index 930c5160..1382acc5 100644 --- a/laravel/database/schema/grammars/postgres.php +++ b/laravel/database/schema/grammars/postgres.php @@ -25,7 +25,7 @@ public function create(Table $table, Fluent $command) } /** - * Geenrate the SQL statements for a table modification command. + * Generate the SQL statements for a table modification command. * * @param Table $table * @param Fluent $command @@ -35,7 +35,7 @@ public function add(Table $table, Fluent $command) { $columns = $this->columns($table); - // Once we the array of column definitions, we need to add "add" to the + // Once we have the array of column definitions, we need to add "add" to the // front of each definition, then we'll concatenate the definitions // using commas like normal and generate the SQL. $columns = implode(', ', array_map(function($column) @@ -101,7 +101,7 @@ protected function defaults(Table $table, Fluent $column) { if ( ! is_null($column->default)) { - return " DEFAULT '".$column->default."'"; + return " DEFAULT '".$this->default_value($column->default)."'"; } } @@ -199,15 +199,15 @@ protected function key(Table $table, Fluent $command, $unique = false) } /** - * Generate the SQL statement for a drop table command. + * Generate the SQL statement for a rename table command. * * @param Table $table * @param Fluent $command * @return string */ - public function drop(Table $table, Fluent $command) + public function rename(Table $table, Fluent $command) { - return 'DROP TABLE '.$this->wrap($table); + return 'ALTER TABLE '.$this->wrap($table).' RENAME TO '.$this->wrap($command->name); } /** @@ -246,7 +246,7 @@ public function drop_primary(Table $table, Fluent $command) } /** - * Generate the SQL statement for a drop unqique key command. + * Generate the SQL statement for a drop unique key command. * * @param Table $table * @param Fluent $command @@ -297,12 +297,12 @@ protected function drop_key(Table $table, Fluent $command) * Drop a foreign key constraint from the table. * * @param Table $table - * @param Fluent $fluent + * @param Fluent $command * @return string */ public function drop_foreign(Table $table, Fluent $command) { - return $this->drop_constraint($table, $command); + return $this->drop_constraint($table, $command); } /** @@ -339,7 +339,7 @@ protected function type_float(Fluent $column) } /** - * Generate the data-type definintion for a decimal. + * Generate the data-type definition for a decimal. * * @param Fluent $column * @return string diff --git a/laravel/database/schema/grammars/sqlite.php b/laravel/database/schema/grammars/sqlite.php index 09102f52..975c4137 100644 --- a/laravel/database/schema/grammars/sqlite.php +++ b/laravel/database/schema/grammars/sqlite.php @@ -29,7 +29,7 @@ public function create(Table $table, Fluent $command) return $value->type == 'primary'; }); - // If we found primary key in the array of commands, we'll create the SQL for + // If we found primary keys in the array of commands, we'll create the SQL for // the key addition and append it to the SQL table creation statement for // the schema table so the index is properly generated. if ( ! is_null($primary)) @@ -43,7 +43,7 @@ public function create(Table $table, Fluent $command) } /** - * Geenrate the SQL statements for a table modification command. + * Generate the SQL statements for a table modification command. * * @param Table $table * @param Fluent $command @@ -53,7 +53,7 @@ public function add(Table $table, Fluent $command) { $columns = $this->columns($table); - // Once we the array of column definitions, we need to add "add" to the + // Once we have the array of column definitions, we need to add "add" to the // front of each definition, then we'll concatenate the definitions // using commas like normal and generate the SQL. $columns = array_map(function($column) @@ -87,7 +87,7 @@ protected function columns(Table $table) { // Each of the data type's have their own definition creation method // which is responsible for creating the SQL for the type. This lets - // us to keep the syntax easy and fluent, while translating the + // us keep the syntax easy and fluent, while translating the // types to the types used by the database. $sql = $this->wrap($column).' '.$this->type($column); @@ -127,7 +127,7 @@ protected function defaults(Table $table, Fluent $column) { if ( ! is_null($column->default)) { - return ' DEFAULT '.$this->wrap($column->default); + return ' DEFAULT '.$this->wrap($this->default_value($column->default)); } } @@ -202,19 +202,19 @@ protected function key(Table $table, Fluent $command, $unique = false) } /** - * Generate the SQL statement for a drop table command. + * Generate the SQL statement for a rename table command. * - * @param Table $table - * @param Fluent $command + * @param Table $table + * @param Fluent $command * @return string */ - public function drop(Table $table, Fluent $command) + public function rename(Table $table, Fluent $command) { - return 'DROP TABLE '.$this->wrap($table); + return 'ALTER TABLE '.$this->wrap($table).' RENAME TO '.$this->wrap($command->name); } /** - * Generate the SQL statement for a drop unqique key command. + * Generate the SQL statement for a drop unique key command. * * @param Table $table * @param Fluent $command @@ -226,7 +226,7 @@ public function drop_unique(Table $table, Fluent $command) } /** - * Generate the SQL statement for a drop unqique key command. + * Generate the SQL statement for a drop unique key command. * * @param Table $table * @param Fluent $command @@ -283,7 +283,7 @@ protected function type_float(Fluent $column) } /** - * Generate the data-type definintion for a decimal. + * Generate the data-type definition for a decimal. * * @param Fluent $column * @return string diff --git a/laravel/database/schema/grammars/sqlserver.php b/laravel/database/schema/grammars/sqlserver.php index 5f756c2e..a9164fd6 100644 --- a/laravel/database/schema/grammars/sqlserver.php +++ b/laravel/database/schema/grammars/sqlserver.php @@ -32,7 +32,7 @@ public function create(Table $table, Fluent $command) } /** - * Geenrate the SQL statements for a table modification command. + * Generate the SQL statements for a table modification command. * * @param Table $table * @param Fluent $command @@ -42,7 +42,7 @@ public function add(Table $table, Fluent $command) { $columns = $this->columns($table); - // Once we the array of column definitions, we need to add "add" to the + // Once we have the array of column definitions, we need to add "add" to the // front of each definition, then we'll concatenate the definitions // using commas like normal and generate the SQL. $columns = implode(', ', array_map(function($column) @@ -108,7 +108,7 @@ protected function defaults(Table $table, Fluent $column) { if ( ! is_null($column->default)) { - return " DEFAULT '".$column->default."'"; + return " DEFAULT '".$this->default_value($column->default)."'"; } } @@ -213,15 +213,15 @@ protected function key(Table $table, Fluent $command, $unique = false) } /** - * Generate the SQL statement for a drop table command. + * Generate the SQL statement for a rename table command. * - * @param Table $table - * @param Fluent $command + * @param Table $table + * @param Fluent $command * @return string */ - public function drop(Table $table, Fluent $command) + public function rename(Table $table, Fluent $command) { - return 'DROP TABLE '.$this->wrap($table); + return 'ALTER TABLE '.$this->wrap($table).' RENAME TO '.$this->wrap($command->name); } /** @@ -235,7 +235,7 @@ public function drop_column(Table $table, Fluent $command) { $columns = array_map(array($this, 'wrap'), $command->columns); - // Once we the array of column names, we need to add "drop" to the front + // Once we have the array of column names, we need to add "drop" to the front // of each column, then we'll concatenate the columns using commas and // generate the alter statement SQL. $columns = implode(', ', array_map(function($column) @@ -260,7 +260,7 @@ public function drop_primary(Table $table, Fluent $command) } /** - * Generate the SQL statement for a drop unqiue key command. + * Generate the SQL statement for a drop unique key command. * * @param Table $table * @param Fluent $command @@ -315,12 +315,12 @@ protected function drop_key(Table $table, Fluent $command) * Drop a foreign key constraint from the table. * * @param Table $table - * @param Fluent $fluent + * @param Fluent $command * @return string */ public function drop_foreign(Table $table, Fluent $command) { - return $this->drop_constraint($table, $command); + return $this->drop_constraint($table, $command); } /** @@ -357,7 +357,7 @@ protected function type_float(Fluent $column) } /** - * Generate the data-type definintion for a decimal. + * Generate the data-type definition for a decimal. * * @param Fluent $column * @return string diff --git a/laravel/database/schema/table.php b/laravel/database/schema/table.php index ba187df5..c728260c 100644 --- a/laravel/database/schema/table.php +++ b/laravel/database/schema/table.php @@ -113,6 +113,7 @@ public function index($columns, $name = null) * * @param string|array $columns * @param string $name + * @return Fluent */ public function foreign($columns, $name = null) { @@ -144,6 +145,17 @@ public function key($type, $columns, $name) return $this->command($type, compact('name', 'columns')); } + /** + * Rename the database table. + * + * @param string $name + * @return Fluent + */ + public function rename($name) + { + return $this->command(__FUNCTION__, compact('name')); + } + /** * Drop the database table. * diff --git a/laravel/documentation/artisan/commands.md b/laravel/documentation/artisan/commands.md index 997e86ce..0a2dd5ff 100644 --- a/laravel/documentation/artisan/commands.md +++ b/laravel/documentation/artisan/commands.md @@ -2,6 +2,7 @@ # Artisan Commands ## Contents +- [Help](#help) - [Application Configuration](#application-configuration) - [Sessions](#sessions) - [Migrations](#migrations) @@ -12,6 +13,13 @@ ## Contents - [Application Keys](#keys) - [CLI Options](#cli-options) + +## Help + +Description | Command +------------- | ------------- +View a list of available artisan commands. | `php artisan help:commands` + ## Application Configuration [(More Information)](/docs/install#basic-configuration) diff --git a/laravel/documentation/artisan/tasks.md b/laravel/documentation/artisan/tasks.md index 08e6606c..a5ab78b6 100644 --- a/laravel/documentation/artisan/tasks.md +++ b/laravel/documentation/artisan/tasks.md @@ -38,6 +38,14 @@ #### Calling a task and passing arguments: php artisan notify taylor +#### Calling a task from your application: + + Command::run(array('notify')); + +#### Calling a task from your application with arguements: + + Command::run(array('notify', 'taylor')); + Remember, you can call specific methods on your task, so, let's add an "urgent" method to the notify task: #### Adding a method to the task: @@ -97,4 +105,4 @@ #### Setting the Laravel environment: #### Setting the default database connection: - php artisan foo --database=sqlite \ No newline at end of file + php artisan foo --database=sqlite diff --git a/laravel/documentation/auth/usage.md b/laravel/documentation/auth/usage.md index e02747a0..8a9a0650 100644 --- a/laravel/documentation/auth/usage.md +++ b/laravel/documentation/auth/usage.md @@ -63,7 +63,7 @@ ## Protecting Routes To protect a route, simply attach the **auth** filter: - Route::get('admin', array('before' => 'auth', function() {}); + Route::get('admin', array('before' => 'auth', function() {})); > **Note:** You are free to edit the **auth** filter however you like. A default implementation is located in **application/routes.php**. diff --git a/laravel/documentation/bundles.md b/laravel/documentation/bundles.md index 2f72dbb5..674deb25 100644 --- a/laravel/documentation/bundles.md +++ b/laravel/documentation/bundles.md @@ -21,7 +21,7 @@ ## The Basics ## Creating Bundles -The first step in creating a bundle is to create a folder for the bundle within your **bundles** directory. For this example, let's create an "admin" bundle, which could house the administrator back-end to our application. The **application/start.php** file provides some basic configuration that helps to define how our application will run. Likewise we'll create a **start.php** file within our new bundle folder for the same purpose. It is run everytime the bundle is loaded. Let's create it: +The first step in creating a bundle is to create a folder for the bundle within your **bundles** directory. For this example, let's create an "admin" bundle, which could house the administrator back-end to our application. The **application/start.php** file provides some basic configuration that helps to define how our application will run. Likewise we'll create a **start.php** file within our new bundle folder for the same purpose. It is run every time the bundle is loaded. Let's create it: #### Creating a bundle start.php file: diff --git a/laravel/documentation/changes.md b/laravel/documentation/changes.md index d4e12daa..d9b0ff41 100644 --- a/laravel/documentation/changes.md +++ b/laravel/documentation/changes.md @@ -2,6 +2,16 @@ # Laravel Change Log ## Contents +- [Laravel 3.2.8](#3.2.8) +- [Upgrading From 3.2.7](#upgrade-3.2.8) +- [Laravel 3.2.7](#3.2.7) +- [Upgrading From 3.2.6](#upgrade-3.2.7) +- [Laravel 3.2.6](#3.2.6) +- [Upgrading From 3.2.5](#upgrade-3.2.6) +- [Laravel 3.2.5](#3.2.5) +- [Upgrading From 3.2.4](#upgrade-3.2.5) +- [Laravel 3.2.4](#3.2.4) +- [Upgrading From 3.2.3](#upgrade-3.2.4) - [Laravel 3.2.3](#3.2.3) - [Upgrading From 3.2.2](#upgrade-3.2.3) - [Laravel 3.2.2](#3.2.2) @@ -31,6 +41,59 @@ ## Contents - [Laravel 3.1](#3.1) - [Upgrading From 3.0](#upgrade-3.1) + +## Laravel 3.2.8 + +- Fix double slash bug in URLs when using languages and no "index.php". + + +### Upgrading From 3.2.7 + +- Replace the **laravel** folder. + + +## Laravel 3.2.7 + +- Fix bug in Eloquent `to_array` method. +- Fix bug in displaying of generic error page. + + +### Upgrading From 3.2.6 + +- Replace the **laravel** folder. + + +## Laravel 3.2.6 + +- Revert Blade code back to 3.2.3 tag. + + +### Upgrading From 3.2.5 + +- Replace the **laravel** folder. + + +## Laravel 3.2.5 + +- Revert nested where code back to 3.2.3 tag. + + +### Upgrading From 3.2.4 + +- Replace the **laravel** folder. + + +## Laravel 3.2.4 + +- Speed up many to many eager loading mapping. +- Tweak the Eloquent::changed() method. +- Various bug fixes and improvements. + + +### Upgrading From 3.2.3 + +- Replace the **laravel** folder. + ## Laravel 3.2.3 @@ -38,7 +101,7 @@ ## Laravel 3.2.3 - Added `laravel.resolving` event for all IoC resolutions. -## Upgrading From 3.2.2 +### Upgrading From 3.2.2 - Replace the **laravel** folder. @@ -54,7 +117,7 @@ ## Laravel 3.2.2 - Added `password` option to Auth configuration. -## Upgrading From 3.2.1 +### Upgrading From 3.2.1 - Replace the **laravel** folder. @@ -69,7 +132,7 @@ ## Laravel 3.2.1 - Added `format` method to message container. -## Upgrading From 3.2 +### Upgrading From 3.2 - Replace the **laravel** folder. @@ -126,7 +189,7 @@ ## Laravel 3.2 - Added `array_except` and `array_only` helpers, similar to `Input::except` and `Input::only` but for arbitrary arrays. -## Upgrading From 3.1 +### Upgrading From 3.1 - Add new `asset_url` and `profiler` options to application configuration. - Replace **auth** configuration file. @@ -151,7 +214,7 @@ ## Laravel 3.1.9 - Fixes cookie session driver bug that caused infinite loop on some occasions. -## Upgrading From 3.1.8 +### Upgrading From 3.1.8 - Replace the **laravel** folder. @@ -161,7 +224,7 @@ ## Laravel 3.1.8 - Fixes possible WSOD when using Blade's @include expression. -## Upgrading From 3.1.7 +### Upgrading From 3.1.7 - Replace the **laravel** folder. @@ -173,7 +236,7 @@ ## Laravel 3.1.7 - Classify migration names. -## Upgrading From 3.1.6 +### Upgrading From 3.1.6 - Replace the **laravel** folder. @@ -183,7 +246,7 @@ ## Laravel 3.1.6 - Fixes many-to-many eager loading in Eloquent. -## Upgrading From 3.1.5 +### Upgrading From 3.1.5 - Replace the **laravel** folder. @@ -193,7 +256,7 @@ ## Laravel 3.1.5 - Fixes bug that could allow secure cookies to be sent over HTTP. -## Upgrading From 3.1.4 +### Upgrading From 3.1.4 - Replace the **laravel** folder. @@ -204,7 +267,7 @@ ## Laravel 3.1.4 - Fixes SQL "where in" (...) short-cut bug. -## Upgrading From 3.1.3 +### Upgrading From 3.1.3 - Replace the **laravel** folder. @@ -214,7 +277,7 @@ ## Laravel 3.1.3 - Fixes **delete** method in Eloquent models. -## Upgrade From 3.1.2 +### Upgrade From 3.1.2 - Replace the **laravel** folder. @@ -224,7 +287,7 @@ ## Laravel 3.1.2 - Fixes Eloquent query method constructor conflict. -## Upgrade From 3.1.1 +### Upgrade From 3.1.1 - Replace the **laravel** folder. @@ -234,7 +297,7 @@ ## Laravel 3.1.1 - Fixes Eloquent model hydration bug involving custom setters. -## Upgrading From 3.1 +### Upgrading From 3.1 - Replace the **laravel** folder. @@ -272,48 +335,48 @@ ## Laravel 3.1 - Added "before" and "after" validation checks for dates. -## Upgrading From 3.0 +### Upgrading From 3.0 -### Replace your **application/start.php** file. +#### Replace your **application/start.php** file. The default **start.php** file has been expanded in order to give you more flexibility over the loading of your language, configuration, and view files. To upgrade your file, copy your current file and paste it at the bottom of a copy of the new Laravel 3.1 start file. Next, scroll up in the **start** file until you see the default Autoloader registrations (line 61 and line 76). Delete both of these sections since you just pasted your previous auto-loader registrations at the bottom of the file. -### Remove the **display** option from your **errors** configuration file. +#### Remove the **display** option from your **errors** configuration file. This option is now set at the beginning of your **application/start** file. -### Call the parent controller's constructor from your controller. +#### Call the parent controller's constructor from your controller. Simply add a **parent::__construct();** to to any of your controllers that have a constructor. -### Prefix Laravel migration created indexes with their table name. +#### Prefix Laravel migration created indexes with their table name. If you have created indexes on tables using the Laravel migration system and you used to the default index naming scheme provided by Laravel, prefix the index names with their table name on your database. So, if the current index name is "id_unique" on the "users" table, make the index name "users_id_unique". -### Add alias for Eloquent in your application configuration. +#### Add alias for Eloquent in your application configuration. Add the following to the **aliases** array in your **application/config/application.php** file: 'Eloquent' => 'Laravel\\Database\\Eloquent\\Model', 'Blade' => 'Laravel\\Blade', -### Update Eloquent many-to-many tables. +#### Update Eloquent many-to-many tables. Eloquent now maintains **created_at** and **updated_at** column on many-to-many intermediate tables by default. Simply add these columns to your tables. Also, many-to-many tables are now the singular model names concatenated with an underscore. For example, if the relationship is between User and Role, the intermediate table name should be **role_user**. -### Remove Eloquent bundle. +#### Remove Eloquent bundle. If you are using the Eloquent bundle with your installation, you can remove it from your bundles directory and your **application/bundles.php** file. Eloquent version 2 is included in the core in Laravel 3.1. Your models can also now extend simply **Eloquent** instead of **Eloquent\Model**. -### Update your **config/strings.php** file. +#### Update your **config/strings.php** file. English pluralization and singularization is now automatic. Just completely replace your **application/config/strings.php** file. -### Add the **fetch** option to your database configuration file. +#### Add the **fetch** option to your database configuration file. A new **fetch** option allows you to specify in which format you receive your database results. Just copy and paste the option from the new **application/config/database.php** file. -### Add **database** option to your Redis configuration. +#### Add **database** option to your Redis configuration. If you are using Redis, add the "database" option to your Redis connection configurations. The "database" value can be zero by default. diff --git a/laravel/documentation/contents.md b/laravel/documentation/contents.md index 1d5ce11e..d29b3908 100644 --- a/laravel/documentation/contents.md +++ b/laravel/documentation/contents.md @@ -4,6 +4,7 @@ ### General - [Installation & Setup](/docs/install) - [Requirements](/docs/install#requirements) - [Installation](/docs/install#installation) + - [Server Configuration](/docs/install#server-configuration) - [Basic Configuration](/docs/install#basic-configuration) - [Environments](/docs/install#environments) - [Cleaner URLs](/docs/install#cleaner-urls) @@ -17,7 +18,8 @@ ### General - [Route Groups](/docs/routing#groups) - [Named Routes](/docs/routing#named-routes) - [HTTPS Routes](/docs/routing#https-routes) - - [Bundle Routing](/docs/routing#bundle-routing) + - [Bundle Routes](/docs/routing#bundle-routes) + - [Controller Routing](/docs/routing#controller-routing) - [CLI Route Testing](/docs/routing#cli-route-testing) - [Controllers](/docs/controllers) - [The Basics](/docs/controllers#the-basics) @@ -107,4 +109,10 @@ ### Artisan CLI - [Creating & Running Tasks](/docs/artisan/tasks#creating-tasks) - [Bundle Tasks](/docs/artisan/tasks#bundle-tasks) - [CLI Options](/docs/artisan/tasks#cli-options) -- [Commands](/docs/artisan/commands) \ No newline at end of file +- [Commands](/docs/artisan/commands) + +### Contributing + +- [Laravel on GitHub](/docs/contrib/github) +- [Command Line](/docs/contrib/command-line) +- [TortoiseGit](/docs/contrib/tortoisegit) diff --git a/laravel/documentation/contrib/command-line.md b/laravel/documentation/contrib/command-line.md new file mode 100644 index 00000000..5dea4cb6 --- /dev/null +++ b/laravel/documentation/contrib/command-line.md @@ -0,0 +1,128 @@ +# Contributing to Laravel via Command-Line + +## Contents + +- [Getting Started](#getting-started) +- [Forking Laravel](#forking-laravel) +- [Cloning Laravel](#cloning-laravel) +- [Adding your Fork](#adding-your-fork) +- [Creating Branches](#creating-branches) +- [Committing](#committing) +- [Submitting a Pull Request](#submitting-a-pull-request) +- [What's Next?](#whats-next) + + +## Getting Started + +This tutorial explains the basics of contributing to a project on [GitHub](https://github.com/) via the command-line. The workflow can apply to most projects on GitHub, but in this case, we will be focused on the [Laravel](https://github.com/laravel/laravel) project. This tutorial is applicable to OSX, Linux and Windows. + +This tutorial assumes you have installed [Git](http://git-scm.com/) and you have created a [GitHub account](https://github.com/signup/free). If you haven't already, look at the [Laravel on GitHub](/docs/contrib/github) documentation in order to familiarize yourself with Laravel's repositories and branches. + + +## Forking Laravel + +Login to GitHub and visit the [Laravel Repository](https://github.com/laravel/laravel). Click on the **Fork** button. This will create your own fork of Laravel in your own GitHub account. Your Laravel fork will be located at **https://github.com/username/laravel** (your GitHub username will be used in place of *username*). + + +## Cloning Laravel + +Open up the command-line or terminal and make a new directory where you can make development changes to Laravel: + + # mkdir laravel-develop + # cd laravel-develop + +Next, clone the Laravel repository (not your fork you made): + + # git clone https://github.com/laravel/laravel.git . + +> **Note**: The reason you are cloning the original Laravel repository (and not the fork you made) is so you can always pull down the most recent changes from the Laravel repository to your local repository. + + +## Adding your Fork + +Next, it's time to add the fork you made as a **remote repository**: + + # git remote add fork git@github.com:username/laravel.git + +Remember to replace *username** with your GitHub username. *This is case-sensitive*. You can verify that your fork was added by typing: + + # git remote + +Now you have a pristine clone of the Laravel repository along with your fork as a remote repository. You are ready to begin branching for new features or fixing bugs. + + +## Creating Branches + +First, make sure you are working in the **develop** branch. If you submit changes to the **master** branch, it is unlikely they will be pulled in anytime in the near future. For more information on this, read the documentation for [Laravel on GitHub](/docs/contrib/github). To switch to the develop branch: + + # git checkout develop + +Next, you want to make sure you are up-to-date with the latest Laravel repository. If any new features or bug fixes have been added to the Laravel project since you cloned it, this will ensure that your local repository has all of those changes. This important step is the reason we originally cloned the Laravel repository instead of your own fork. + + # git pull origin develop + +Now you are ready to create a new branch for your new feature or bug-fix. When you create a new branch, use a self-descriptive naming convention. For example, if you are going to fix a bug in Eloquent, name your branch *bug/eloquent*: + + # git branch bug/eloquent + # git checkout bug/eloquent + Switched to branch 'bug/eloquent' + +Or if there is a new feature to add or change to the documentation that you want to make, for example, the localization documentation: + + # git branch feature/localization-docs + # git checkout feature/localization-docs + Switched to branch 'feature/localization-docs' + +> **Note:** Create one new branch for every new feature or bug-fix. This will encourage organization, limit interdependency between new features/fixes and will make it easy for the Laravel team to merge your changes into the Laravel core. + +Now that you have created your own branch and have switched to it, it's time to make your changes to the code. Add your new feature or fix that bug. + + +## Committing + +Now that you have finished coding and testing your changes, it's time to commit them to your local repository. First, add the files that you changed/added: + + # git add laravel/documentation/localization.md + +Next, commit the changes to the repository: + + # git commit -s -m "I added some more stuff to the Localization documentation." + +"- **-s** means that you are signing-off on your commit with your name. This tells the Laravel team know that you personally agree to your code being added to the Laravel core. +"- **-m** is the message that goes with your commit. Provide a brief explanation of what you added or changed. + + +## Pushing to your Fork + +Now that your local repository has your committed changes, it's time to push (or sync) your new branch to your fork that is hosted in GitHub: + + # git push fork feature/localization-docs + +Your branch has been successfully pushed to your fork on GitHub. + + +## Submitting a Pull Request + +The final step is to submit a pull request to the Laravel repository. This means that you are requesting that the Laravel team pull and merge your changes to the Laravel core. In your browser, visit your Laravel fork at [https://github.com/username/laravel](https://github.com/username/laravel). Click on **Pull Request**. Next, make sure you choose the proper base and head repositories and branches: + +- **base repo:** laravel/laravel +- **base branch:** develop +- **head repo:** username/laravel +- **head branch:** feature/localization-docs + +Use the form to write a more detailed description of the changes you made and why you made them. Finally, click **Send pull request**. That's it! The changes you made have been submitted to the Laravel team. + + +## What's Next? + +Do you have another feature you want to add or another bug you need to fix? First, make sure you always base your new branch off of the develop branch: + + # git checkout develop + +Then, pull down the latest changes from Laravel's repository: + + # git pull origin develop + +Now you are ready to create a new branch and start coding again! + +> [Jason Lewis](http://jasonlewis.me/)'s blog post [Contributing to a GitHub Project](http://jasonlewis.me/blog/2012/06/how-to-contributing-to-a-github-project) was the primary inspiration for this tutorial. diff --git a/laravel/documentation/contrib/github.md b/laravel/documentation/contrib/github.md new file mode 100644 index 00000000..ceeac76e --- /dev/null +++ b/laravel/documentation/contrib/github.md @@ -0,0 +1,46 @@ +# Laravel on GitHub + +## Contents + +- [The Basics](#the-basics) +- [Repositories](#repositories) +- [Branches](#branches) +- [Pull Requests](#pull-requests) + + +## The Basics + +Because Laravel's development and source control is done through GitHub, anyone is able to make contributions to it. Anyone can fix bugs, add features or improve the documentation. + +After submitting proposed changes to the project, the Laravel team will review the changes and make the decision to commit them to Laravel's core. + + +## Repositories + +Laravel's home on GitHub is at [github.com/laravel](https://github.com/laravel). Laravel has several repositories. For basic contributions, the only repository you need to pay attention to is the **laravel** repository, located at [github.com/laravel/laravel](https://github.com/laravel/laravel). + + +## Branches + +The **laravel** repository has multiple branches, each serving a specific purpose: + +- **master** - This is the Laravel release branch. Active development does not happen on this branch. This branch is only for the most recent, stable Laravel core code. When you download Laravel from [laravel.com](http://laravel.com/), you are downloading directly from this master branch. *Do not make pull requests to this branch.* +- **develop** - This is the working development branch. All proposed code changes and contributions by the community are pulled into this branch. *When you make a pull request to the Laravel project, this is the branch you want to pull-request into.* + +Once certain milestones have been reached and/or Taylor Otwell and the Laravel team is happy with the stability and additional features of the current development branch, the changes in the **develop** branch are pulled into the **master** branch, thus creating and releasing the newest stable version of Laravel for the world to use. + + +## Pull Requests + +[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. + +*Further Reading* + + - [Contributing to Laravel via Command-Line](docs/contrib/command-line) + - [Contributing to Laravel using TortoiseGit](docs/contrib/tortoisegit) diff --git a/laravel/documentation/contrib/tortoisegit.md b/laravel/documentation/contrib/tortoisegit.md new file mode 100644 index 00000000..74049ead --- /dev/null +++ b/laravel/documentation/contrib/tortoisegit.md @@ -0,0 +1,114 @@ +# Contributing to Laravel using TortoiseGit + +## Contents + +- [Getting Started](#getting-started) +- [Forking Laravel](#forking-laravel) +- [Cloning Laravel](#cloning-laravel) +- [Adding your Fork](#adding-your-fork) +- [Creating Branches](#creating-branches) +- [Committing](#committing) +- [Submitting a Pull Request](#submitting-a-pull-request) +- [What's Next?](#whats-next) + + +## Getting Started + +This tutorial explains the basics of contributing to a project on [GitHub](https://github.com/) using [TortoiseGit](http://code.google.com/p/tortoisegit/) for Windows. The workflow can apply to most projects on GitHub, but in this case, we will be focused on the [Laravel](https://github.com/laravel/laravel) project. + +This tutorial assumes you have installed TortoiseGit for Windows and you have created a GitHub account. If you haven't already, look at the [Laravel on GitHub](/docs/contrib/github) documentation in order to familiarize yourself with Laravel's repositories and branches. + + +## Forking Laravel + +Login to GitHub and visit the [Laravel Repository](https://github.com/laravel/laravel). Click on the **Fork** button. This will create your own fork of Laravel in your own GitHub account. Your Laravel fork will be located at **https://github.com/username/laravel** (your GitHub username will be used in place of *username*). + + +## Cloning Laravel + +Open up Windows Explorer and create a new directory where you can make development changes to Laravel. + +- Right-click the Laravel directory to bring up the context menu. Click on **Git Clone...** +- Git clone + - **Url:** https://github.com/laravel/laravel.git + - **Directory:** the directory that you just created in the previous step + - Click **OK** + +> **Note**: The reason you are cloning the original Laravel repository (and not the fork you made) is so you can always pull down the most recent changes from the Laravel repository to your local repository. + + +## Adding your Fork + +After the cloning process is complete, it's time to add the fork you made as a **remote repository**. + +- Right-click the Laravel directory and goto **TortoiseGit > Settings** +- Goto the **Git/Remote** section. Add a new remote: + - **Remote**: fork + - **URL**: https://github.com/username/laravel.git + - Click **Add New/Save** + - Click **OK** + +Remember to replace *username* with your GitHub username. *This is case-sensitive*. + + +## Creating Branches + +Now you are ready to create a new branch for your new feature or bug-fix. When you create a new branch, use a self-descriptive naming convention. For example, if you are going to fix a bug in Eloquent, name your branch *bug/eloquent*. Or if you were going to make changes to the localization documentation, name your branch *feature/localization-docs*. A good naming convention will encourage organization and help others understand the purpose of your branch. + +- Right-click the Laravel directory and goto **TortoiseGit > Create Branch** + - **Branch:** feature/localization-docs + - **Base On Branch:** remotes/origin/develop + - **Check** *Track* + - **Check** *Switch to new branch* + - Click **OK** + +This will create your new *feature/localization-docs* branch and switch you to it. + +> **Note:** Create one new branch for every new feature or bug-fix. This will encourage organization, limit interdependency between new features/fixes and will make it easy for the Laravel team to merge your changes into the Laravel core. + +Now that you have created your own branch and have switched to it, it's time to make your changes to the code. Add your new feature or fix that bug. + + +##Committing + +Now that you have finished coding and testing your changes, it's time to commit them to your local repository: + +- Right-click the Laravel directory and goto **Git Commit -> "feature/localization-docs"...** +- Commit + - **Message:** Provide a brief explaination of what you added or changed + - Click **Sign** - This tells the Laravel team know that you personally agree to your code being added to the Laravel core + - **Changes made:** Check all changed/added files + - Click **OK** + + +## Pushing to your Fork + +Now that your local repository has your committed changes, it's time to push (or sync) your new branch to your fork that is hosted in GitHub: + +- Right-click the Laravel directory and goto **Git Sync...** +- Git Syncronization + - **Local Branch:** feature/localization-docs + - **Remote Branch:** leave this blank + - **Remote URL:** fork + - Click **Push** + - When asked for "username:" enter your GitHub *case-sensitive* username + - When asked for "password:" enter your GitHub *case-sensitive* account + +Your branch has been successfully pushed to your fork on GitHub. + + +## Submitting a Pull Request + +The final step is to submit a pull request to the Laravel repository. This means that you are requesting that the Laravel team pull and merge your changes to the Laravel core. In your browser, visit your Laravel fork at [https://github.com/username/laravel](https://github.com/username/laravel). Click on **Pull Request**. Next, make sure you choose the proper base and head repositories and branches: + +- **base repo:** laravel/laravel +- **base branch:** develop +- **head repo:** username/laravel +- **head branch:** feature/localization-docs + +Use the form to write a more detailed description of the changes you made and why you made them. Finally, click **Send pull request**. That's it! The changes you made have been submitted to the Laravel team. + + +## What's Next? + +Do you have another feature you want to add or another bug you need to fix? Just follow the same instructions as before in the [Creating Branches](#creating-branches) section. Just remember to always create a new branch for every new feature/fix and don't forget to always base your new branches off of the *remotes/origin/develop* branch. diff --git a/laravel/documentation/controllers.md b/laravel/documentation/controllers.md index 220c10af..0f8555f2 100644 --- a/laravel/documentation/controllers.md +++ b/laravel/documentation/controllers.md @@ -49,7 +49,7 @@ ## Controller Routing ## Bundle Controllers -Bundles are Laravel's modular package system. Bundles can easily configured to handle requests to your application. We'll be going over [bundles in more detail](/docs/bundles) in another document. +Bundles are Laravel's modular package system. Bundles can be easily configured to handle requests to your application. We'll be going over [bundles in more detail](/docs/bundles) in another document. Creating controllers that belong to bundles is almost identical to creating your application controllers. Just prefix the controller class name with the name of the bundle, so if your bundle is named "admin", your controller classes would look like this: diff --git a/laravel/documentation/database/config.md b/laravel/documentation/database/config.md index a4eddb62..b593dbc6 100644 --- a/laravel/documentation/database/config.md +++ b/laravel/documentation/database/config.md @@ -5,6 +5,7 @@ ## Contents - [Quick Start Using SQLite](#quick) - [Configuring Other Databases](#server) - [Setting The Default Connection Name](#default) +- [Overwriting The Default PDO Options](#options) Laravel supports the following databases out of the box: @@ -43,4 +44,27 @@ ## Setting The Default Connection Name 'default' => 'sqlite'; -The default connection will always be used by the [fluent query builder](/docs/database/fluent). If you need to change the default connection during a request, use the **Config::set** method. \ No newline at end of file +The default connection will always be used by the [fluent query builder](/docs/database/fluent). If you need to change the default connection during a request, use the **Config::set** method. + + +##Overwriting The Default PDO Options + +The PDO connector class (**laravel/database/connectors/connector.php**) has a set of default PDO attributes defined which can be overwritten in the options array for each system. For example, one of the default attributes is to force column names to lowercase (**PDO::CASE_LOWER**) even if they are defined in UPPERCASE or CamelCase in the table. Therefore, under the default attributes, query result object variables would only be accessible in lowercase. +An example of the MySQL system settings with added default PDO attributes: + + 'mysql' => array( + 'driver' => 'mysql', + 'host' => 'localhost', + 'database' => 'database', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', + 'prefix' => '', + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_EMULATE_PREPARES => false, + ), + +More about the PDO connection attributes can be found [in the PHP manual](http://php.net/manual/en/pdo.setattribute.php). \ No newline at end of file diff --git a/laravel/documentation/database/eloquent.md b/laravel/documentation/database/eloquent.md index 0706b7d9..09493db0 100644 --- a/laravel/documentation/database/eloquent.md +++ b/laravel/documentation/database/eloquent.md @@ -15,6 +15,7 @@ ## Contents - [Setter & Getter Methods](#getter-and-setter-methods) - [Mass-Assignment](#mass-assignment) - [Converting Models To Arrays](#to-array) +- [Deleting Models](#delete) ## The Basics @@ -65,7 +66,7 @@ ## Retrieving Models echo $user->email; } -Of course, retrieving an entire table isn't very helpful. Thankfully, **every method that is available through the fluent query builder is available in Eloquent**. Just begin querying your model with a static call to one of the [query builder](/docs/database/query) methods, and execute the query using the **get** or **first** method. The get method will return an array of models, while the first method will return a single model: +Of course, retrieving an entire table isn't very helpful. Thankfully, **every method that is available through the fluent query builder is available in Eloquent**. Just begin querying your model with a static call to one of the [query builder](/docs/database/fluent) methods, and execute the query using the **get** or **first** method. The get method will return an array of models, while the first method will return a single model: $user = User::where('email', '=', $email)->first(); @@ -131,6 +132,18 @@ ## Inserting & Updating Models Next, add **created_at** and **updated_at** date columns to your table. Now, whenever you save the model, the creation and update timestamps will be set automatically. You're welcome. +In some cases it may be useful to update the **updated_at** date column without actually modifying any data within the model. Simply use the **touch** method, which will also automatically save the changes immediately: + + $comment = Comment::find(1); + $comment->touch(); + +You can also use the **timestamp** function to update the **updated_at** date column without saving the model immediately. Note that if you are actually modifying the model's data this is handled behind the scenes: + + $comment = Comment::find(1); + $comment->timestamp(); + //do something else here, but not modifying the $comment model data + $comment->save(); + > **Note:** You can change the default timezone of your application in the **application/config/application.php** file. @@ -223,7 +236,7 @@ ### One-To-Many return $this->has_many('Comment', 'my_foreign_key'); -You may be wondering: _If the dynamic properties return the relationship and require less keystokes, why would I ever use the relationship methods?_ Actually, relationship methods are very powerful. They allow you to continue to chain query methods before retrieving the relationship. Check this out: +You may be wondering: _If the dynamic properties return the relationship and require less keystrokes, why would I ever use the relationship methods?_ Actually, relationship methods are very powerful. They allow you to continue to chain query methods before retrieving the relationship. Check this out: echo Post::find(1)->comments()->order_by('votes', 'desc')->take(10)->get(); @@ -242,8 +255,9 @@ ### Many-To-Many id - INTEGER name - VARCHAR -**Roles_Users:** +**Role_User:** + id - INTEGER user_id - INTEGER role_id - INTEGER @@ -277,6 +291,17 @@ ### Many-To-Many } +By default only certain fields from the pivot table will be returned (the two **id** fields, and the timestamps). If your pivot table contains additional columns, you can fetch them too by using the **with()** method : + + class User extends Eloquent { + + public function roles() + { + return $this->has_many_and_belongs_to('Role', 'user_roles')->with('column'); + } + + } + ## Inserting Related Models @@ -286,7 +311,7 @@ ## Inserting Related Models $post = Post::find(1); - $post->comments()->insert($comment); + $comment = $post->comments()->insert($comment); When inserting related models through their parent model, the foreign key will automatically be set. So, in this case, the "post_id" was automatically set to "1" on the newly inserted comment. @@ -310,7 +335,7 @@ ### Inserting Related Models (Many-To-Many) $user = User::find(1); - $user->roles()->insert($role); + $role = $user->roles()->insert($role); Now, when the Role is inserted, not only is the Role inserted into the "roles" table, but a record in the intermediate table is also inserted for you. It couldn't be easier! @@ -318,6 +343,10 @@ ### Inserting Related Models (Many-To-Many) $user->roles()->attach($role_id); +It's also possible to attach data for fields in the intermediate table (pivot table), to do this add a second array variable to the attach command containing the data you want to attach: + + $user->roles()->attach($role_id, array('expires' => $expires)); + Alternatively, you can use the `sync` method, which accepts an array of IDs to "sync" with the intermediate table. After this operation is complete, only the IDs in the array will be on the intermediate table. @@ -406,6 +435,28 @@ ## Eager Loading $books = Book::with(array('author', 'author.contacts'))->get(); +If you find yourself eager loading the same models often, you may want to use **$includes** in the model. + + class Book extends Eloquent { + + public $includes = array('author'); + + public function author() + { + return $this->belongs_to('Author'); + } + + } + +**$includes** takes the same arguments that **with** takes. The following is now eagerly loaded. + + foreach (Book::all() as $book) + { + echo $book->author->name; + } + +> **Note:** Using **with** will override a models **$includes**. + ## Constraining Eager Loads @@ -498,4 +549,13 @@ #### Excluding attributes from the array: public static $hidden = array('password'); - } \ No newline at end of file + } + + +## Deleting Models + +Because Eloquent inherits all the features and methods of Fluent queries, deleting models is a snap: + + $author->delete(); + +Note, however, than this won't delete any related models (e.g. all the author's Book models will still exist), unless you have set up [foreign keys](/docs/database/schema#foreign-keys) and cascading deletes. diff --git a/laravel/documentation/database/fluent.md b/laravel/documentation/database/fluent.md index 6ab34476..ceeb809b 100644 --- a/laravel/documentation/database/fluent.md +++ b/laravel/documentation/database/fluent.md @@ -124,7 +124,7 @@ ## Nested Where Clauses ->or_where(function($query) { $query->where('age', '>', 25); - $query->where('votes' '>', 100); + $query->where('votes', '>', 100); }) ->get(); @@ -169,7 +169,7 @@ ## Table Joins $join->on('users.id', '=', 'phone.user_id'); $join->or_on('users.id', '=', 'phone.contact_id'); }) - ->get(array('users.email', 'phone.numer')); + ->get(array('users.email', 'phone.number')); ## Ordering Results diff --git a/laravel/documentation/database/schema.md b/laravel/documentation/database/schema.md index 16ed318c..904edbba 100644 --- a/laravel/documentation/database/schema.md +++ b/laravel/documentation/database/schema.md @@ -13,7 +13,7 @@ ## Contents ## The Basics -The Schema Bulder provides methods for creating and modifying your database tables. Using a fluent syntax, you can work with your tables without using any vendor specific SQL. +The Schema Builder provides methods for creating and modifying your database tables. Using a fluent syntax, you can work with your tables without using any vendor specific SQL. *Further Reading:* @@ -62,6 +62,7 @@ ## Adding Columns `$table->string('name', 100);` | VARCHAR equivalent with a length `$table->integer('votes');` | INTEGER equivalent to the table `$table->float('amount');` | FLOAT equivalent to the table +`$table->decimal('amount', 5, 2);` | DECIMAL equivalent with a precision and scale `$table->boolean('confirmed');` | BOOLEAN equivalent to the table `$table->date('created_at');` | DATE equivalent to the table `$table->timestamp('added_on');` | TIMESTAMP equivalent to the table @@ -69,6 +70,8 @@ ## Adding Columns `$table->text('description');` | TEXT equivalent to the table `$table->blob('data');` | BLOB equivalent to the table `->nullable()` | Designate that the column allows NULL values +`->default($value)` | Declare a default value for a column +`->unsigned()` | Set INTEGER to UNSIGNED > **Note:** Laravel's "boolean" type maps to a small integer column on all database systems. @@ -142,4 +145,10 @@ ## Foreign Keys You may also easily drop a foreign key constraint. The default foreign key names follow the [same convention](#dropping-indexes) as the other indexes created by the Schema builder. Here's an example: - $table->drop_foreign('posts_user_id_foreign'); \ No newline at end of file + $table->drop_foreign('posts_user_id_foreign'); + +> **Note:** The field referenced in the foreign key is very likely an auto increment and therefore automatically an unsigned integer. Please make sure to create the foreign key field with **unsigned()** as both fields have to be the exact same type, the engine on both tables has to be set to **InnoDB**, and the referenced table must be created **before** the table with the foreign key. + + $table->engine = 'InnoDB'; + + $table->integer('user_id')->unsigned(); \ No newline at end of file diff --git a/laravel/documentation/files.md b/laravel/documentation/files.md index d0ed3f85..ebff9e81 100644 --- a/laravel/documentation/files.md +++ b/laravel/documentation/files.md @@ -4,6 +4,7 @@ ## Contents - [Reading Files](#get) - [Writing Files](#put) +- [Removing files](#delete) - [File Uploads](#upload) - [File Extensions](#ext) - [Checking File Types](#is) @@ -29,6 +30,13 @@ #### Appending to a file: File::append('path/to/file', 'appended file content'); + +## Removing Files + +#### Deleting a single file: + + File::delete('path/to/file'); + ## File Uploads @@ -65,7 +73,7 @@ ## Getting MIME Types #### Getting the MIME type associated with an extension: - echo File::mime('gif'); + echo File::mime('gif'); // outputs 'image/gif' > **Note:** This method simply returns the MIME type defined for the extension in the **application/config/mimes.php** file. diff --git a/laravel/documentation/input.md b/laravel/documentation/input.md index 4387721e..b0aa613c 100644 --- a/laravel/documentation/input.md +++ b/laravel/documentation/input.md @@ -145,10 +145,10 @@ #### Merging new data into the current input: #### Replacing the entire input array with new data: - Input::merge(array('doctor' => 'Bones', 'captain' => 'Kirk')); + Input::replace(array('doctor' => 'Bones', 'captain' => 'Kirk')); ## Clearing Input -To clear all input data for the current request, using the `clear()` method, for example: +To clear all input data for the current request, you may use the `clear` method: Input::clear(); \ No newline at end of file diff --git a/laravel/documentation/install.md b/laravel/documentation/install.md index 12f12951..1e051e06 100644 --- a/laravel/documentation/install.md +++ b/laravel/documentation/install.md @@ -4,6 +4,7 @@ ## Contents - [Requirements](#requirements) - [Installation](#installation) +- [Server Configuration](#server-configuration) - [Basic Configuration](#basic-configuration) - [Environments](#environments) - [Cleaner URLs](#cleaner-urls) @@ -22,7 +23,8 @@ ## Installation 1. [Download Laravel](http://laravel.com/download) 2. Extract the Laravel archive and upload the contents to your web server. 3. Set the value of the **key** option in the **config/application.php** file to a random, 32 character string. -4. Navigate to your application in a web browser. +4. Verify that the `storage/views` directory is writable. +5. Navigate to your application in a web browser. If all is well, you should see a pretty Laravel splash page. Get ready, there is lots more to learn! @@ -37,8 +39,27 @@ ### Problems? If you are having problems installing, try the following: -- Make sure the **public** directory is the document root of your web server. +- Make sure the **public** directory is the document root of your web server. (see: Server Configuration below) - If you are using mod_rewrite, set the **index** option in **application/config/application.php** to an empty string. +- Verify that your storage folder and the folders within are writable by your web server. + + +## Server Configuration + +Like most web-development frameworks, Laravel is designed to protect your application code, bundles, and local storage by placing only files that are necessarily public in the web server's DocumentRoot. This prevents some types of server misconfiguration from making your code (including database passwords and other configuration data) accessible through the web server. It's best to be safe. + +In this example let's imagine that we installed Laravel to the directory **/Users/JonSnow/Sites/MySite**. + +A very basic example of an Apache VirtualHost configuration for MySite might look like this. + + + DocumentRoot /Users/JonSnow/Sites/MySite/public + ServerName mysite.dev + + +Notice that while we installed to **/Users/JonSnow/Sites/MySite** our DocumentRoot points to **/Users/JonSnow/Sites/MySite/public**. + +While pointing the DocumentRoot to the public folder is a commonly used best-practice, it's possible that you may need to use Laravel on a host that does not allow you to update your DocumentRoot. A collection of algorithms to circumvent this need can be found [on the Laravel forums.](http://forums.laravel.com/viewtopic.php?id=1258) ## Basic Configuration @@ -70,7 +91,7 @@ ## Environments ); -In this example, the local **URL** option will override the **URL** option in **application/config/application.php**. Notice that you only need to specify the options you wish to override. +In this example, the local **URL** option will override the **URL** option in **application/config/application.php**. Notice that you only need to specify the options you wish to override. Isn't it easy? Of course, you are free to create as many environments as you wish! diff --git a/laravel/documentation/ioc.md b/laravel/documentation/ioc.md index bd393178..7df9572b 100644 --- a/laravel/documentation/ioc.md +++ b/laravel/documentation/ioc.md @@ -24,7 +24,7 @@ #### Registering a resolver in the IoC container: }); -Great! Now we have registered a resolver for SwiftMailer in our container. But, what if we don't want the container to create a new mailer instance every time we need one? Maybe we just want the container to return the same instance after the intial instance is created. Just tell the container the object should be a singleton: +Great! Now we have registered a resolver for SwiftMailer in our container. But, what if we don't want the container to create a new mailer instance every time we need one? Maybe we just want the container to return the same instance after the initial instance is created. Just tell the container the object should be a singleton: #### Registering a singleton in the container: diff --git a/laravel/documentation/localization.md b/laravel/documentation/localization.md index e1941633..cbf4a463 100644 --- a/laravel/documentation/localization.md +++ b/laravel/documentation/localization.md @@ -33,7 +33,7 @@ #### Creating a language file: Nice! Now you know how to get started setting up your language files and directories. Let's keep localizing! - + ## Retrieving A Language Line #### Retrieving a language line: @@ -55,7 +55,7 @@ #### Getting a language line in a given language: ## Place Holders & Replacements -Now, let's work on our welcome message. "Welcome to our website!" is a pretty generic message. It would be helpful to be able to specify the name of the person we are welcoming. But, creating a language line for each user of our application would be time-consuming and ridiculous. Thankfully, you don't have to. You can specify "place-holders" within your language lines. Place-holders are preceeded by a colon: +Now, let's work on our welcome message. "Welcome to our website!" is a pretty generic message. It would be helpful to be able to specify the name of the person we are welcoming. But, creating a language line for each user of our application would be time-consuming and ridiculous. Thankfully, you don't have to. You can specify "place-holders" within your language lines. Place-holders are preceded by a colon: #### Creating a language line with place-holders: diff --git a/laravel/documentation/logging.md b/laravel/documentation/logging.md index c1533387..74678c65 100644 --- a/laravel/documentation/logging.md +++ b/laravel/documentation/logging.md @@ -24,7 +24,7 @@ ## Logging To enable logging, set the **log** option in the error configuration to "true". When enabled, the Closure defined by the **logger** configuration item will be executed when an error occurs. This gives you total flexibility in how the error should be logged. You can even e-mail the errors to your development team! -By default, logs are stored in the **storage/logs** direcetory, and a new log file is created for each day. This keeps your log files from getting crowded with too many messages. +By default, logs are stored in the **storage/logs** directory, and a new log file is created for each day. This keeps your log files from getting crowded with too many messages. ## The Logger Class diff --git a/laravel/documentation/requests.md b/laravel/documentation/requests.md index 8498b3ed..5a7426e2 100644 --- a/laravel/documentation/requests.md +++ b/laravel/documentation/requests.md @@ -62,7 +62,7 @@ #### Determining if the current request is using HTTPS: // This request is over HTTPS! } -#### Determing if the current request is an AJAX request: +#### Determining if the current request is an AJAX request: if (Request::ajax()) { diff --git a/laravel/documentation/routing.md b/laravel/documentation/routing.md index 18c90671..eee1bb8c 100644 --- a/laravel/documentation/routing.md +++ b/laravel/documentation/routing.md @@ -4,7 +4,7 @@ ## Contents - [The Basics](#the-basics) - [Wildcards](#wildcards) -- [The 404 Events](#the-404-event) +- [The 404 Event](#the-404-event) - [Filters](#filters) - [Pattern Filters](#pattern-filters) - [Global Filters](#global-filters) @@ -78,6 +78,13 @@ #### Allowing a URI segment to be any alpha-numeric string: // }); +#### Catching the remaining URI without limitations: + + Route::get('files/(:all)', function($path) + { + // + }); + #### Allowing a URI segment to be optional: Route::get('page/(:any?)', function($page = 'index') @@ -99,14 +106,14 @@ #### The default 404 event handler: You are free to change this to fit the needs of your application! -*Futher Reading:* +*Further Reading:* - *[Events](/docs/events)* ## Filters -Route filters may be run before or after a route is executed. If a "before" filter returns a value, that value is considered the response to the request and the route is not executed, which is conveniont when implementing authentication filters, etc. Filters are typically defined in **application/routes.php**. +Route filters may be run before or after a route is executed. If a "before" filter returns a value, that value is considered the response to the request and the route is not executed, which is convenient when implementing authentication filters, etc. Filters are typically defined in **application/routes.php**. #### Registering a filter: @@ -152,6 +159,15 @@ #### Defining a URI pattern based filter: Route::filter('pattern: admin/*', 'auth'); +Optionally you can register filters directly when attaching filters to a given URI by supplying an array with the name of the filter and a callback. + +#### Defining a filter and URI pattern based filter in one: + + Route::filter('pattern: admin/*', array('name' => 'auth', function() + { + // + })); + ## Global Filters diff --git a/laravel/documentation/session/config.md b/laravel/documentation/session/config.md index 094148c8..14821320 100644 --- a/laravel/documentation/session/config.md +++ b/laravel/documentation/session/config.md @@ -1,4 +1,3 @@ - # Session Configuration ## Contents diff --git a/laravel/documentation/session/usage.md b/laravel/documentation/session/usage.md index 5f9aad56..1b5c9d5c 100644 --- a/laravel/documentation/session/usage.md +++ b/laravel/documentation/session/usage.md @@ -5,6 +5,7 @@ ## Contents - [Storing Items](#put) - [Retrieving Items](#get) - [Removing Items](#forget) +- [Flashing Items](#flash) - [Regeneration](#regeneration) @@ -16,10 +17,6 @@ ## Storing Items The first parameter is the **key** to the session item. You will use this key to retrieve the item from the session. The second parameter is the **value** of the item. -The **flash** method stores an item in the session that will expire after the next request. It's useful for storing temporary data like status or error messages: - - Session::flash('status', 'Welcome Back!'); - ## Retrieving Items @@ -53,6 +50,27 @@ ## Removing Items Session::flush(); + +## Flashing Items + +The **flash** method stores an item in the session that will expire after the next request. It's useful for storing temporary data like status or error messages: + + Session::flash('status', 'Welcome Back!'); + +Flash items that are expiring in subsequent requests can be retained for another request by using one of the **reflash** or **keep** methods: + +Retain all items for another request: + + Session::reflash(); + +Retain an individual item for another request: + + Session::keep('status'); + +Retain several items for another request: + + Session::keep(array('status', 'other_item')); + ## Regeneration diff --git a/laravel/documentation/strings.md b/laravel/documentation/strings.md index 002d9148..4164e5ec 100644 --- a/laravel/documentation/strings.md +++ b/laravel/documentation/strings.md @@ -25,6 +25,7 @@ ## Word & Character Limiting #### Limiting the number of characters in a string: echo Str::limit($string, 10); + echo Str::limit_exact($string, 10); #### Limiting the number of words in a string: diff --git a/laravel/documentation/validation.md b/laravel/documentation/validation.md index 49401439..0f17dec0 100644 --- a/laravel/documentation/validation.md +++ b/laravel/documentation/validation.md @@ -12,7 +12,7 @@ ## Contents ## The Basics -Almost every interactive web application needs to validate data. For instance, a registration form probably requires the password to be confirmed. Maybe the e-mail address must be unique. Validating data can be a cumbersome process. Thankfully, it isn't in Laravel. The Validator class provides as awesome array of validation helpers to make validating your data a breeze. Let's walk through an example: +Almost every interactive web application needs to validate data. For instance, a registration form probably requires the password to be confirmed. Maybe the e-mail address must be unique. Validating data can be a cumbersome process. Thankfully, it isn't in Laravel. The Validator class provides an awesome array of validation helpers to make validating your data a breeze. Let's walk through an example: #### Get an array of data you want to validate: @@ -63,6 +63,9 @@ #### Validate that an attribute is present and is not an empty string: 'name' => 'required' +#### Validate that an attribute is present, when another attribute is present: + 'last_name' => 'required_with:first_name' + ### Alpha, Alpha Numeric, & Alpha Dash @@ -304,7 +307,26 @@ ## Validation Walkthrough Great! So, we have two simple registration routes. One to handle displaying the form, and one to handle the posting of the form. In the POST route, we run some validation over the input. If the validation fails, we redirect back to the registration form and flash the validation errors to the session so they will be available for us to display. -**But, notice we are not explicitly binding the errors to the view in our GET route**. However, an errors variable will still be available in the view. Laravel intelligently determines if errors exist in the session, and if they do, binds them to the view for you. If no errors exist in the session, an empty message container will still be bound to the view. In your views, this allows you to always assume you have a message container available via the errors variable. We love making your life easier. +**But, notice we are not explicitly binding the errors to the view in our GET route**. However, an errors variable ($errors) will still be available in the view. Laravel intelligently determines if errors exist in the session, and if they do, binds them to the view for you. If no errors exist in the session, an empty message container will still be bound to the view. In your views, this allows you to always assume you have a message container available via the errors variable. We love making your life easier. + +For example, if email address validation failed, we can look for 'email' within the $errors session var. + + $errors->has('email') + +Using Blade, we can then conditionally add error messages to our view. + + {{ $errors->has('email') ? 'Invalid Email Address' : 'Condition is false. Can be left blank' }} + +This will also work great when we need to conditionally add classes when using something like Twitter Bootstrap. +For example, if the email address failed validation, we may want to add the "error" class from Bootstrap to our *div class="control-group"* statement. + +
+ +When the validation fails, our rendered view will have the appended *error* class. + +
+ + ## Custom Error Messages @@ -344,7 +366,7 @@ #### Specifying a custom error message for a given attribute: However, if you are using many custom error messages, specifying inline may become cumbersome and messy. For that reason, you can specify your custom messages in the **custom** array within the validation language file: -#### Adding custom error messages to the validation langauge file: +#### Adding custom error messages to the validation language file: 'custom' => array( 'email_required' => 'We need to know your e-mail address!', @@ -395,7 +417,7 @@ #### Registering a custom validation rule: Validator::register('awesome', function($attribute, $value, $parameters) { return $value == $parameters[0]; - } + }); In this case, the parameters argument of your validation rule would receive an array containing one element: "yes". diff --git a/laravel/documentation/views/home.md b/laravel/documentation/views/home.md index be646393..27383562 100644 --- a/laravel/documentation/views/home.md +++ b/laravel/documentation/views/home.md @@ -54,9 +54,9 @@ #### Returning a custom response: return Response::make('Hello World!', 200, $headers); }); -#### Returning a custom response containing a view: +#### Returning a custom response containing a view, with binding data: - return Response::view('home', 200, $headers); + return Response::view('home', array('foo' => 'bar')); #### Returning a JSON response: @@ -257,4 +257,4 @@ #### Generating a 404 error response: #### Generating a 500 error response: - return Response::error('500'); \ No newline at end of file + return Response::error('500'); diff --git a/laravel/documentation/views/html.md b/laravel/documentation/views/html.md index d1fcae9b..aabe244d 100644 --- a/laravel/documentation/views/html.md +++ b/laravel/documentation/views/html.md @@ -15,7 +15,7 @@ ## Content ## Entities -When displaying user input in your Views, it is important to convert all characters which have signifance in HTML to their "entity" representation. +When displaying user input in your Views, it is important to convert all characters which have significance in HTML to their "entity" representation. For example, the < symbol should be converted to its entity representation. Converting HTML characters to their entity representation helps protect your application from cross-site scripting: @@ -85,7 +85,7 @@ #### Generating a link to a controller action: ### Generating a link to a controller action with wildcard values: - echo HTML::link_to_action('user@profile', array($username)); + echo HTML::link_to_action('user@profile', 'User Profile', array($username)); ## Mail-To Links @@ -119,6 +119,8 @@ #### Creating lists from an array of items: echo HTML::ol(array('Get Peanut Butter', 'Get Chocolate', 'Feast')); echo HTML::ul(array('Ubuntu', 'Snow Leopard', 'Windows')); + + echo HTML::dl(array('Ubuntu' => 'An operating system by Canonical', 'Windows' => 'An operating system by Microsoft')); ## Custom Macros diff --git a/laravel/documentation/views/pagination.md b/laravel/documentation/views/pagination.md index 602b09ba..081a6f60 100644 --- a/laravel/documentation/views/pagination.md +++ b/laravel/documentation/views/pagination.md @@ -22,6 +22,10 @@ #### Pull the paginated results from the query: $orders = DB::table('orders')->paginate($per_page); +You can also pass an optional array of table columns to select in the query: + + $orders = DB::table('orders')->paginate($per_page, array('id', 'name', 'created_at')); + #### Display the results in a view: results as $order): ?> @@ -75,30 +79,32 @@ ## Pagination Styling All pagination link elements can be style using CSS classes. Here is an example of the HTML elements generated by the links method: - When you are on the first page of results, the "Previous" link will be disabled. Likewise, the "Next" link will be disabled when you are on the last page of results. The generated HTML will look like this: - Previous \ No newline at end of file +
  • Previous
  • diff --git a/laravel/documentation/views/templating.md b/laravel/documentation/views/templating.md index a2273c19..9aabac87 100644 --- a/laravel/documentation/views/templating.md +++ b/laravel/documentation/views/templating.md @@ -5,12 +5,13 @@ ## Contents - [The Basics](#the-basics) - [Sections](#sections) - [Blade Template Engine](#blade-template-engine) +- [Blade Control Structures](#blade-control-structures) - [Blade Layouts](#blade-layouts) ## The Basics -Your application probably uses a common layout across most of its pages. Manually creating this layout within every controller action can be a pain. Specifying a controller layout will make your develompent much more enjoyable. Here's how to get started: +Your application probably uses a common layout across most of its pages. Manually creating this layout within every controller action can be a pain. Specifying a controller layout will make your development much more enjoyable. Here's how to get started: #### Specify a "layout" property on your controller: @@ -63,29 +64,63 @@ ## Blade Template Engine #### Echoing a variable using Blade: - Hello, {{$name}}. - + Hello, {{ $name }}. + #### Echoing function results using Blade: {{ Asset::styles() }} -#### Rendering a view: +#### Render a view: + +You can use **@include** to render a view into another view. The rendered view will automatically inherit all of the data from the current view.

    Profile - @include('user.profile') -> **Note:** When using the **@include** Blade expression, the view will automatically inherit all of the current view data. +Similarly, you can use **@render**, which behaves the same as **@include** except the rendered view will **not** inherit the data from the current view. -#### Creating loops using Blade: + @render('admin.list') -

    Comments

    +#### Blade comments: + + {{-- This is a comment --}} + + {{-- + This is a + multi-line + comment. + --}} + +> **Note:** Unlike HTML comments, Blade comments are not visible in the HTML source. + + +## Blade Control Structures + +#### For Loop: + + @for ($i = 0; $i <= count($comments); $i++) + The comment body is {{ $comments[$i] }} + @endfor + +#### Foreach Loop: @foreach ($comments as $comment) - The comment body is {{$comment->body}}. + The comment body is {{ $comment->body }}. @endforeach -#### Other Blade control structures: +#### While Loop: + + @while ($something) + I am still looping! + @endwhile + +#### If Statement: + + @if ( $message == true ) + I'm displaying the message! + @endif + +#### If Else Statement: @if (count($comments) > 0) I have comments! @@ -93,15 +128,17 @@ #### Other Blade control structures: I have no comments! @endif - @for ($i =0; $i < count($comments) - 1; $i++) - The comment body is {{$comments[$i]}} - @endfor +#### Else If Statement: - @while ($something) - I am still looping! - @endwhile + @if ( $message == 'success' ) + It was a success! + @elseif ( $message == 'error' ) + An error occurred. + @else + Did it work? + @endif -#### The "for-else" control structure: +#### For Else Statement: @forelse ($posts as $post) {{ $post->body }} @@ -109,29 +146,18 @@ #### The "for-else" control structure: There are not posts in the array! @endforelse - -#### The "unless" control structure: +#### Unless Statement: @unless(Auth::check()) - {{ HTML::link_to_route('login', 'Login'); }} + Login @endunless - // Equivalent... + // Equivalent to... - ... + Login - -#### Blade comments: - - @if ($check) - {{-- This is a comment --}} - ... - @endif - -> **Note:** Blade comments, unlike HTML comments, are not visible in the HTML source. - ## Blade Layouts @@ -164,7 +190,9 @@ ## Blade Layouts The profile view will automatically use the "master" template thanks to Blade's **@layout** expression. -**Important:** The **@layout** call must always be on the very first line of the file, with no leading whitespaces or newline breaks. +> **Important:** The **@layout** call must always be on the very first line of the file, with no leading whitespaces or newline breaks. + +#### Appending with @parent Sometimes you may want to only append to a section of a layout rather than overwrite it. For example, consider the navigation list in our "master" layout. Let's assume we just want to append a new list item. Here's how to do it: @@ -179,4 +207,4 @@ ## Blade Layouts Welcome to the profile page! @endsection -Notice the **@parent** Blade construct? It will be replaced with the contents of the layout's navigation section, providing you with a beautiful and powerful method of performing layout extension and inheritance. \ No newline at end of file +**@parent** will be replaced with the contents of the layout's *navigation* section, providing you with a beautiful and powerful method of performing layout extension and inheritance. diff --git a/laravel/error.php b/laravel/error.php index 729f632a..6b75d210 100644 --- a/laravel/error.php +++ b/laravel/error.php @@ -41,7 +41,7 @@ public static function exception($exception, $trace = true) { $response = Event::first('500'); - return Response::prepare($response)->send(); + echo Response::prepare($response)->render(); } exit(1); @@ -60,7 +60,7 @@ public static function native($code, $error, $file, $line) { if (error_reporting() === 0) return; - // For a PHP error, we'll create an ErrorExcepetion and then feed that + // For a PHP error, we'll create an ErrorException and then feed that // exception to the exception method, which will create a simple view // of the exception details for the developer. $exception = new \ErrorException($error, $code, 0, $file, $line); @@ -80,7 +80,7 @@ public static function native($code, $error, $file, $line) */ public static function shutdown() { - // If a fatal error occured that we have not handled yet, we will + // If a fatal error occurred that we have not handled yet, we will // create an ErrorException and feed it to the exception handler, // as it will not yet have been handled. $error = error_get_last(); diff --git a/laravel/event.php b/laravel/event.php index 1f88d99f..ccc3bf1c 100644 --- a/laravel/event.php +++ b/laravel/event.php @@ -125,7 +125,7 @@ public static function first($event, $parameters = array()) } /** - * Fire an event and return the the first response. + * Fire an event and return the first response. * * Execution will be halted after the first valid response is found. * @@ -176,7 +176,7 @@ public static function flush($queue) * $responses = Event::fire(array('start', 'loading'), $parameters); * * - * @param string|array $event + * @param string|array $events * @param array $parameters * @param bool $halt * @return array diff --git a/laravel/file.php b/laravel/file.php index efb46dec..d2022268 100644 --- a/laravel/file.php +++ b/laravel/file.php @@ -161,7 +161,7 @@ public static function mime($extension, $default = 'application/octet-stream') } /** - * Determine if a file is a given type. + * Determine if a file is of a given type. * * The Fileinfo PHP extension is used to determine the file's MIME type. * @@ -184,7 +184,7 @@ public static function is($extensions, $path) $mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path); // The MIME configuration file contains an array of file extensions and - // their associated MIME types. We will spin through each extension the + // their associated MIME types. We will loop through each extension the // developer wants to check and look for the MIME type. foreach ((array) $extensions as $extension) { @@ -296,7 +296,7 @@ public static function rmdir($directory, $preserve = false) { // If the item is a directory, we can just recurse into the // function and delete that sub-directory, otherwise we'll - // just deleete the file and keep going! + // just delete the file and keep going! if ($item->isDir()) { static::rmdir($item->getRealPath()); @@ -335,7 +335,7 @@ public static function latest($directory, $options = fIterator::SKIP_DOTS) $items = new fIterator($directory, $options); - // To get the latest created file, we'll simply spin through the + // To get the latest created file, we'll simply loop through the // directory, setting the latest file if we encounter a file // with a UNIX timestamp greater than the latest one. foreach ($items as $item) diff --git a/laravel/form.php b/laravel/form.php index 5fa6d129..5a450b52 100644 --- a/laravel/form.php +++ b/laravel/form.php @@ -20,7 +20,7 @@ class Form { * Registers a custom macro. * * @param string $name - * @param Closure $input + * @param Closure $macro * @return void */ public static function macro($name, $macro) @@ -526,7 +526,7 @@ protected static function checkable($type, $name, $value, $checked, $attributes) * @param array $attributes * @return string */ - public static function submit($value, $attributes = array()) + public static function submit($value = null, $attributes = array()) { return static::input('submit', null, $value, $attributes); } @@ -538,7 +538,7 @@ public static function submit($value, $attributes = array()) * @param array $attributes * @return string */ - public static function reset($value, $attributes = array()) + public static function reset($value = null, $attributes = array()) { return static::input('reset', null, $value, $attributes); } @@ -570,7 +570,7 @@ public static function image($url, $name = null, $attributes = array()) * @param array $attributes * @return string */ - public static function button($value, $attributes = array()) + public static function button($value = null, $attributes = array()) { return ''.HTML::entities($value).''; } diff --git a/laravel/helpers.php b/laravel/helpers.php index 07f9940a..589669ce 100644 --- a/laravel/helpers.php +++ b/laravel/helpers.php @@ -34,7 +34,10 @@ function __($key, $replacements = array(), $language = null) */ function dd($value) { - die(var_dump($value)); + echo "
    ";
    +	var_dump($value);
    +	echo "
    "; + die; } /** @@ -462,7 +465,7 @@ function root_namespace($class, $separator = '\\') /** * Get the "class basename" of a class or object. * - * The basename is considered the name of the class minus all namespaces. + * The basename is considered to be the name of the class minus all namespaces. * * @param object|string $class * @return string @@ -540,7 +543,7 @@ function render($view, $data = array()) /** * Get the rendered contents of a partial from a loop. * - * @param string $view + * @param string $partial * @param array $data * @param string $iterator * @param string $empty @@ -580,4 +583,16 @@ function get_cli_option($option, $default = null) } return value($default); +} + +/** + * Calculate the human-readable file size (with proper units). + * + * @param int $size + * @return string + */ +function get_file_size($size) +{ + $units = array('Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'); + return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2).' '.$units[$i]; } \ No newline at end of file diff --git a/laravel/html.php b/laravel/html.php index 498ea28c..211e4022 100644 --- a/laravel/html.php +++ b/laravel/html.php @@ -9,13 +9,13 @@ class HTML { */ public static $macros = array(); - /** - * Registers a custom macro. - * - * @param string $name - * @param Closure $input - * @return void - */ + /** + * Registers a custom macro. + * + * @param string $name + * @param Closure $macro + * @return void + */ public static function macro($name, $macro) { static::$macros[$name] = $macro; @@ -137,10 +137,12 @@ public static function span($value, $attributes = array()) * @param bool $https * @return string */ - public static function link($url, $title, $attributes = array(), $https = null) + public static function link($url, $title = null, $attributes = array(), $https = null) { $url = URL::to($url, $https); + if (is_null($title)) $title = $url; + return ''.static::entities($title).''; } @@ -152,7 +154,7 @@ public static function link($url, $title, $attributes = array(), $https = null) * @param array $attributes * @return string */ - public static function link_to_secure($url, $title, $attributes = array()) + public static function link_to_secure($url, $title = null, $attributes = array()) { return static::link($url, $title, $attributes, true); } @@ -168,7 +170,7 @@ public static function link_to_secure($url, $title, $attributes = array()) * @param bool $https * @return string */ - public static function link_to_asset($url, $title, $attributes = array(), $https = null) + public static function link_to_asset($url, $title = null, $attributes = array(), $https = null) { $url = URL::to_asset($url, $https); @@ -183,7 +185,7 @@ public static function link_to_asset($url, $title, $attributes = array(), $https * @param array $attributes * @return string */ - public static function link_to_secure_asset($url, $title, $attributes = array()) + public static function link_to_secure_asset($url, $title = null, $attributes = array()) { return static::link_to_asset($url, $title, $attributes, true); } @@ -207,7 +209,7 @@ public static function link_to_secure_asset($url, $title, $attributes = array()) * @param array $attributes * @return string */ - public static function link_to_route($name, $title, $parameters = array(), $attributes = array()) + public static function link_to_route($name, $title = null, $parameters = array(), $attributes = array()) { return static::link(URL::to_route($name, $parameters), $title, $attributes); } @@ -231,7 +233,7 @@ public static function link_to_route($name, $title, $parameters = array(), $attr * @param array $attributes * @return string */ - public static function link_to_action($action, $title, $parameters = array(), $attributes = array()) + public static function link_to_action($action, $title = null, $parameters = array(), $attributes = array()) { return static::link(URL::to_action($action, $parameters), $title, $attributes); } @@ -345,6 +347,28 @@ private static function listing($type, $list, $attributes = array()) return '<'.$type.static::attributes($attributes).'>'.$html.''; } + + /** + * Generate a definition list. + * + * @param array $list + * @param array $attributes + * @return string + */ + public static function dl($list, $attributes = array()) + { + $html = ''; + + if (count($list) == 0) return $html; + + foreach ($list as $term => $description) + { + $html .= '
    '.static::entities($term).'
    '; + $html .= '
    '.static::entities($description).'
    '; + } + + return ''.$html.''; + } /** * Build a list of HTML attributes from an array. @@ -359,7 +383,7 @@ public static function attributes($attributes) foreach ((array) $attributes as $key => $value) { // For numeric keys, we will assume that the key and the value are the - // same, as this will conver HTML attributes such as "required" that + // same, as this will convert HTML attributes such as "required" that // may be specified as required="required", etc. if (is_numeric($key)) $key = $value; @@ -418,7 +442,7 @@ public static function __callStatic($method, $parameters) { return call_user_func_array(static::$macros[$method], $parameters); } - + throw new \Exception("Method [$method] does not exist."); } diff --git a/laravel/input.php b/laravel/input.php index 8d712871..b76fc7c6 100644 --- a/laravel/input.php +++ b/laravel/input.php @@ -102,13 +102,14 @@ public static function query($key = null, $default = null) /** * Get the JSON payload for the request. * + * @param bool $as_array * @return object */ - public static function json() + public static function json($as_array = false) { if ( ! is_null(static::$json)) return static::$json; - return static::$json = json_decode(Request::foundation()->getContent()); + return static::$json = json_decode(Request::foundation()->getContent(), $as_array); } /** @@ -205,7 +206,7 @@ public static function file($key = null, $default = null) */ public static function has_file($key) { - return ! is_null(static::file("{$key}.tmp_name")); + return strlen(static::file("{$key}.tmp_name", "")) > 0; } /** diff --git a/laravel/ioc.php b/laravel/ioc.php index 11292925..4347cbcb 100644 --- a/laravel/ioc.php +++ b/laravel/ioc.php @@ -85,6 +85,7 @@ public static function instance($name, $instance) * * * @param string $type + * @param array $parameters * @return mixed */ public static function resolve($type, $parameters = array()) @@ -124,7 +125,7 @@ public static function resolve($type, $parameters = array()) // If the requested type is registered as a singleton, we want to cache off // the instance in memory so we can return it later without creating an // entirely new instances of the object on each subsequent request. - if (isset(static::$registry[$type]['singleton'])) + if (isset(static::$registry[$type]['singleton']) && static::$registry[$type]['singleton'] === true) { static::$singletons[$type] = $object; } @@ -154,11 +155,11 @@ protected static function build($type, $parameters = array()) $reflector = new \ReflectionClass($type); // If the type is not instantiable, the developer is attempting to resolve - // an abstract type such as an Interface of Abstract Class and there is + // an abstract type such as an Interface of an Abstract Class and there is // no binding registered for the abstraction so we need to bail out. if ( ! $reflector->isInstantiable()) { - throw new Exception("Resolution target [$type] is not instantiable."); + throw new \Exception("Resolution target [$type] is not instantiable."); } $constructor = $reflector->getConstructor(); @@ -179,7 +180,7 @@ protected static function build($type, $parameters = array()) /** * Resolve all of the dependencies from the ReflectionParameters. * - * @param array $parameterrs + * @param array $parameters * @return array */ protected static function dependencies($parameters) @@ -191,11 +192,11 @@ protected static function dependencies($parameters) $dependency = $parameter->getClass(); // If the class is null, it means the dependency is a string or some other - // primitive type, which we can not esolve since it is not a class and + // primitive type, which we can not resolve since it is not a class and // we'll just bomb out with an error since we have nowhere to go. if (is_null($dependency)) { - throw new Exception("Unresolvable dependency resolving [$parameter]."); + throw new \Exception("Unresolvable dependency resolving [$parameter]."); } $dependencies[] = static::resolve($dependency->name); diff --git a/laravel/lang.php b/laravel/lang.php index 8fd5f7ba..fd3bf177 100644 --- a/laravel/lang.php +++ b/laravel/lang.php @@ -134,7 +134,7 @@ public function get($language = null, $default = null) $line = array_get($lines, $line, $default); // If the line is not a string, it probably means the developer asked for - // the entire langauge file and the value of the requested value will be + // the entire language file and the value of the requested value will be // an array containing all of the lines in the file. if (is_string($line)) { diff --git a/laravel/laravel.php b/laravel/laravel.php index a1ca2061..74c387f9 100644 --- a/laravel/laravel.php +++ b/laravel/laravel.php @@ -54,7 +54,7 @@ |-------------------------------------------------------------------------- | | By setting error reporting to -1, we essentially force PHP to report -| every error, and this is guranteed to show every error on future +| every error, and this is guaranteed to show every error on future | releases of PHP. This allows everything to be fixed early! | */ @@ -107,6 +107,48 @@ return Event::first('404'); }); +/* +|-------------------------------------------------------------------------- +| Gather The URI And Locales +|-------------------------------------------------------------------------- +| +| When routing, we'll need to grab the URI and the supported locales for +| the route so we can properly set the language and route the request +| to the proper end-point in the application. +| +*/ + +$uri = URI::current(); + +$languages = Config::get('application.languages', array()); + +$languages[] = Config::get('application.language'); + +/* +|-------------------------------------------------------------------------- +| Set The Locale Based On The Route +|-------------------------------------------------------------------------- +| +| If the URI starts with one of the supported languages, we will set +| the default lagnauge to match that URI segment and shorten the +| URI we'll pass to the router to not include the lang segment. +| +*/ + +foreach ($languages as $language) +{ + if (starts_with($uri, $language)) + { + Config::set('application.language', $language); + + $uri = trim(substr($uri, strlen($language)), '/'); break; + } +} + +if ($uri == '') $uri = '/'; + +URI::$uri = $uri; + /* |-------------------------------------------------------------------------- | Route The Incoming Request @@ -118,8 +160,6 @@ | */ -$uri = URI::current(); - Request::$route = Routing\Router::route(Request::method(), $uri); $response = Request::$route->call(); @@ -143,7 +183,7 @@ |-------------------------------------------------------------------------- | | If a session driver has been configured, we will save the session to -| storage so it is avaiable for the next request. This will also set +| storage so it is available for the next request. This will also set | the session cookie in the cookie jar to be sent to the user. | */ @@ -172,10 +212,24 @@ | And We're Done! |-------------------------------------------------------------------------- | -| Raise the "done" event so extra output can be attached to the response +| Raise the "done" event so extra output can be attached to the response. | This allows the adding of debug toolbars, etc. to the view, or may be | used to do some kind of logging by the application. | */ -Event::fire('laravel.done', array($response)); \ No newline at end of file +Event::fire('laravel.done', array($response)); + +/* +|-------------------------------------------------------------------------- +| Finish the request for PHP-FastCGI +|-------------------------------------------------------------------------- +| +| Stopping the PHP process for PHP-FastCGI users to speed up some +| PHP queries. Acceleration is possible when there are actions in the +| process of script execution that do not affect server response. +| For example, saving the session in memcached can occur after the page +| has been formed and passed to a web server. +*/ + +$response->foundation->finish(); diff --git a/laravel/log.php b/laravel/log.php index 4cd3a30e..6de027df 100644 --- a/laravel/log.php +++ b/laravel/log.php @@ -28,7 +28,7 @@ protected static function exception_line($e) * Write a message to the log file. * * - * // Write an "error" messge to the log file + * // Write an "error" message to the log file * Log::write('error', 'Something went horribly wrong!'); * * // Write an "error" message using the class' magic method @@ -51,7 +51,7 @@ public static function write($type, $message) // If there aren't listeners on the log event, we'll just write to the // log files using the default conventions, writing one log file per - // day so they files don't get too crowded. + // day so the files don't get too crowded. else { $message = static::format($type, $message); @@ -64,7 +64,8 @@ public static function write($type, $message) * Format a log message for logging. * * @param string $type - * @param + * @param string $message + * @return string */ protected static function format($type, $message) { diff --git a/laravel/memcached.php b/laravel/memcached.php index 91e7270e..d66710bb 100644 --- a/laravel/memcached.php +++ b/laravel/memcached.php @@ -68,7 +68,7 @@ protected static function connect($servers) */ public static function __callStatic($method, $parameters) { - return call_user_func_array(array(static::instance(), $method), $parameters); + return call_user_func_array(array(static::connection(), $method), $parameters); } } \ No newline at end of file diff --git a/laravel/paginator.php b/laravel/paginator.php index ceffbe85..e9b95e35 100644 --- a/laravel/paginator.php +++ b/laravel/paginator.php @@ -47,7 +47,7 @@ class Paginator { /** * The compiled appendage that will be appended to the links. * - * This consists of a sprintf format with a page place-holder and query string. + * This consists of a sprintf format with a page place-holder and query string. * * @var string */ @@ -65,7 +65,7 @@ class Paginator { * * @var string */ - protected $dots = '...'; + protected $dots = '
  • ...
  • '; /** * Create a new Paginator instance. @@ -183,7 +183,7 @@ public function links($adjacent = 3) $links = $this->slider($adjacent); } - $content = $this->previous().' '.$links.' '.$this->next(); + $content = '
      ' . $this->previous() . $links . $this->next() . '
    '; return ''; } @@ -300,7 +300,7 @@ protected function element($element, $page, $text, $disabled) // the "first" element should be a span instead of a link. if ($disabled($this->page, $this->last)) { - return HTML::span($text, array('class' => "{$class} disabled")); + return '"{$class} disabled")).'>'.$text.''; } else { @@ -349,7 +349,7 @@ protected function range($start, $end) { if ($this->page == $page) { - $pages[] = HTML::span($page, array('class' => 'current')); + $pages[] = '
  • '.$page.'
  • '; } else { @@ -372,7 +372,7 @@ protected function link($page, $text, $class) { $query = '?page='.$page.$this->appendage($this->appends); - return HTML::link(URI::current().$query, $text, compact('class'), Request::secure()); + return ' $class)).'>'. HTML::link(URI::current().$query, $text, array(), Request::secure()).''; } /** diff --git a/laravel/pluralizer.php b/laravel/pluralizer.php index 857a7ff5..2ce72f0b 100644 --- a/laravel/pluralizer.php +++ b/laravel/pluralizer.php @@ -24,6 +24,7 @@ class Pluralizer { /** * Create a new pluralizer instance. * + * @param array $config * @return void */ public function __construct($config) @@ -48,7 +49,7 @@ public function singular($value) } // English words may be automatically inflected using regular expressions. - // If the word is english, we'll just pass off the word to the automatic + // If the word is English, we'll just pass off the word to the automatic // inflection method and return the result, which is cached. $irregular = $this->config['irregular']; @@ -77,7 +78,7 @@ public function plural($value, $count = 2) } // English words may be automatically inflected using regular expressions. - // If the word is english, we'll just pass off the word to the automatic + // If the word is English, we'll just pass off the word to the automatic // inflection method and return the result, which is cached. $irregular = array_flip($this->config['irregular']); @@ -104,7 +105,7 @@ protected function auto($value, $source, $irregular) return $value; } - // Next we will check the "irregular" patterns, which contains words + // Next, we will check the "irregular" patterns, which contain words // like "children" and "teeth" which can not be inflected using the // typically used regular expression matching approach. foreach ($irregular as $irregular => $pattern) diff --git a/laravel/profiling/profiler.js b/laravel/profiling/profiler.js index ab73ad8e..8fc9fe3e 100755 --- a/laravel/profiling/profiler.js +++ b/laravel/profiling/profiler.js @@ -6,20 +6,20 @@ var anbu = { // the DOM every time they are used. el: { - main: $('.anbu'), - close: $('#anbu-close'), - zoom: $('#anbu-zoom'), - hide: $('#anbu-hide'), - show: $('#anbu-show'), - tab_pane: $('.anbu-tab-pane'), - hidden_tab_pane: $('.anbu-tab-pane:visible'), - tab: $('.anbu-tab'), - tabs: $('.anbu-tabs'), - tab_links: $('.anbu-tabs a'), - window: $('.anbu-window'), - closed_tabs: $('#anbu-closed-tabs'), - open_tabs: $('#anbu-open-tabs'), - content_area: $('.anbu-content-area') + main: jQuery('.anbu'), + close: jQuery('#anbu-close'), + zoom: jQuery('#anbu-zoom'), + hide: jQuery('#anbu-hide'), + show: jQuery('#anbu-show'), + tab_pane: jQuery('.anbu-tab-pane'), + hidden_tab_pane: jQuery('.anbu-tab-pane:visible'), + tab: jQuery('.anbu-tab'), + tabs: jQuery('.anbu-tabs'), + tab_links: jQuery('.anbu-tabs a'), + window: jQuery('.anbu-window'), + closed_tabs: jQuery('#anbu-closed-tabs'), + open_tabs: jQuery('#anbu-open-tabs'), + content_area: jQuery('.anbu-content-area') }, // CLASS ATTRIBUTES @@ -30,7 +30,7 @@ var anbu = { is_zoomed: false, // initial height of content area - small_height: $('.anbu-content-area').height(), + small_height: jQuery('.anbu-content-area').height(), // the name of the active tab css active_tab: 'anbu-active-tab', @@ -76,7 +76,7 @@ var anbu = { event.preventDefault(); }); anbu.el.tab.click(function(event) { - anbu.clicked_tab($(this)); + anbu.clicked_tab(jQuery(this)); event.preventDefault(); }); @@ -104,8 +104,8 @@ var anbu = { open_window: function(tab) { // can't directly assign this line, but it works - $('.anbu-tab-pane:visible').fadeOut(200); - $('.' + tab.attr(anbu.tab_data)).delay(220).fadeIn(300); + jQuery('.anbu-tab-pane:visible').fadeOut(200); + jQuery('.' + tab.attr(anbu.tab_data)).delay(220).fadeIn(300); anbu.el.tab_links.removeClass(anbu.active_tab); tab.addClass(anbu.active_tab); anbu.el.window.slideDown(300); @@ -178,7 +178,7 @@ var anbu = { anbu.is_zoomed = false; } else { // the 6px is padding on the top of the window - height = ($(window).height() - anbu.el.tabs.height() - 6) + 'px'; + height = (jQuery(window).height() - anbu.el.tabs.height() - 6) + 'px'; anbu.is_zoomed = true; } diff --git a/laravel/profiling/profiler.php b/laravel/profiling/profiler.php index 9b6edfef..360e4702 100644 --- a/laravel/profiling/profiler.php +++ b/laravel/profiling/profiler.php @@ -5,6 +5,7 @@ use Laravel\Event; use Laravel\Config; use Laravel\Request; +use Laravel\Database; class Profiler { @@ -13,8 +14,8 @@ class Profiler { * * @var array */ - protected static $data = array('queries' => array(), 'logs' => array()); - + protected static $data = array('queries' => array(), 'logs' => array(), 'timers' => array()); + /** * Get the rendered contents of the Profiler. * @@ -26,15 +27,105 @@ public static function render($response) // We only want to send the profiler toolbar if the request is not an AJAX // request, as sending it on AJAX requests could mess up JSON driven API // type applications, so we will not send anything in those scenarios. - if ( ! Request::ajax()) + if ( ! Request::ajax() and Config::get('application.profiler') ) { + static::$data['memory'] = get_file_size(memory_get_usage(true)); + static::$data['memory_peak'] = get_file_size(memory_get_peak_usage(true)); + static::$data['time'] = number_format((microtime(true) - LARAVEL_START) * 1000, 2); + foreach ( static::$data['timers'] as &$timer) + { + $timer['running_time'] = number_format((microtime(true) - $timer['start'] ) * 1000, 2); + } + return render('path: '.__DIR__.'/template'.BLADE_EXT, static::$data); } } + /** + * Allow a callback to be timed. + * + * @param closure $func + * @param string $name + * @return void + */ + public static function time( $func, $name = 'default_func_timer' ) + { + // First measure the runtime of the func + $start = microtime(true); + $func(); + $end = microtime(true); + + // Check to see if a timer by that name exists + if (isset(static::$data['timers'][$name])) + { + $name = $name.uniqid(); + } + + // Push the time into the timers array for display + static::$data['timers'][$name]['start'] = $start; + static::$data['timers'][$name]['end'] = $end; + static::$data['timers'][$name]['time'] = number_format(($end - $start) * 1000, 2); + } + + /** + * Start, or add a tick to a timer. + * + * @param string $name + * @return void + */ + public static function tick($name = 'default_timer', $callback = null) + { + $name = trim($name); + if (empty($name)) $name = 'default_timer'; + + // Is this a brand new tick? + if (isset(static::$data['timers'][$name])) + { + $current_timer = static::$data['timers'][$name]; + $ticks = count($current_timer['ticks']); + + // Initialize the new time for the tick + $new_tick = array(); + $mt = microtime(true); + $new_tick['raw_time'] = $mt - $current_timer['start']; + $new_tick['time'] = number_format(($mt - $current_timer['start']) * 1000, 2); + + // Use either the start time or the last tick for the diff + if ($ticks > 0) + { + $last_tick = $current_timer['ticks'][$ticks- 1]['raw_time']; + $new_tick['diff'] = number_format(($new_tick['raw_time'] - $last_tick) * 1000, 2); + } + else + { + $new_tick['diff'] = $new_tick['time']; + } + + // Add the new tick to the stack of them + static::$data['timers'][$name]['ticks'][] = $new_tick; + } + else + { + // Initialize a start time on the first tick + static::$data['timers'][$name]['start'] = microtime(true); + static::$data['timers'][$name]['ticks'] = array(); + } + + // Run the callback for this tick if it's specified + if ( ! is_null($callback) and is_callable($callback)) + { + // After we've ticked, call the callback function + call_user_func_array($callback, array( + static::$data['timers'][$name] + )); + } + } + /** * Add a log entry to the log entries array. * + * @param string $type + * @param string $message * @return void */ public static function log($type, $message) @@ -54,6 +145,8 @@ public static function query($sql, $bindings, $time) { foreach ($bindings as $binding) { + $binding = Database::connection()->pdo->quote($binding); + $sql = preg_replace('/\?/', $binding, $sql, 1); } diff --git a/laravel/profiling/template.blade.php b/laravel/profiling/template.blade.php index 0b0ffef8..9c855b43 100755 --- a/laravel/profiling/template.blade.php +++ b/laravel/profiling/template.blade.php @@ -48,6 +48,52 @@ There have been no SQL queries executed. @endif
    + +
    + @if (count($timers) > 0) + + + + + + + @foreach ($timers as $name => $timer) + + + + + + + @if (isset($timer['ticks'])) + @foreach( $timer['ticks'] as $tick) + + + + + + @endforeach + @else + + + + + + @endif + + @endforeach +
    NameRunning Time (ms)Difference
    + {{ $name }} +
    {{ $timer['running_time'] }}ms (time from start to render)
     
    +
    Tick
    +
    +
    {{ $tick['time'] }}ms
    +
    +
    + {{ $tick['diff'] }}ms
    +
    Running Time
    {{ $timer['time'] }}ms
     
    + @else + There have been no checkpoints set. + @endif +
    @@ -61,6 +107,8 @@ @endif +
  • Time {{ $time }}ms
  • +
  • Memory {{ $memory }} ({{ $memory_peak }})
  • ×
  • @@ -73,4 +121,4 @@ - \ No newline at end of file + diff --git a/laravel/redirect.php b/laravel/redirect.php index 2f75db53..874cb172 100644 --- a/laravel/redirect.php +++ b/laravel/redirect.php @@ -6,7 +6,7 @@ class Redirect extends Response { * Create a redirect response to application root. * * @param int $status - * @param bool $secure + * @param bool $https * @return Redirect */ public static function home($status = 302, $https = null) @@ -165,4 +165,23 @@ public function with_errors($container) return $this->with('errors', $errors); } + /** + * Send the headers and content of the response to the browser. + * + * @return void + */ + public function send() + { + // Dump all output buffering, this ensures + // that symphony will send our redirect headers + // properly if we've outputted any content from + // within Laravel. + while (ob_get_level() > 0) + { + ob_end_clean(); + } + + return parent::send(); + } + } \ No newline at end of file diff --git a/laravel/redis.php b/laravel/redis.php index d00b2f52..02267d32 100644 --- a/laravel/redis.php +++ b/laravel/redis.php @@ -17,7 +17,7 @@ class Redis { protected $port; /** - * The databse number the connection selects on load. + * The database number the connection selects on load. * * @var int */ diff --git a/laravel/request.php b/laravel/request.php index 84763449..e78c943d 100644 --- a/laravel/request.php +++ b/laravel/request.php @@ -119,6 +119,7 @@ public static function accept() /** * Determine if the request accepts a given content type. * + * @param string $type * @return bool */ public static function accepts($type) @@ -177,6 +178,16 @@ public static function referrer() { return static::foundation()->headers->get('referer'); } + + /** + * Get the timestamp of the time when the request was started. + * + * @return int + */ + public static function time() + { + return (int) LARAVEL_START; + } /** * Determine if the current request is via the command line. diff --git a/laravel/response.php b/laravel/response.php index b6fa4d84..ccd53e1f 100644 --- a/laravel/response.php +++ b/laravel/response.php @@ -1,7 +1,7 @@ 'value')); *
    * - * @param Eloquenet|array $data + * @param Eloquent|array $data * @param int $status * @param array $headers * @return Response */ public static function eloquent($data, $status = 200, $headers = array()) { - $headers['Content-Type'] = 'application/json'; + $headers['Content-Type'] = 'application/json; charset=utf-8'; return new static(eloquent_to_json($data), $status, $headers); } @@ -239,7 +239,7 @@ public function send() public function render() { // If the content is a stringable object, we'll go ahead and call - // to toString method so that we can get the string content of + // the toString method so that we can get the string content of // the content object. Otherwise we'll just cast to string. if (str_object($this->content)) { diff --git a/laravel/routing/controller.php b/laravel/routing/controller.php index 0a780bbc..e81d6b5f 100644 --- a/laravel/routing/controller.php +++ b/laravel/routing/controller.php @@ -179,6 +179,8 @@ protected static function references(&$destination, &$parameters) // controllers with much less code than would be usual. foreach ($parameters as $key => $value) { + if ( ! is_string($value)) continue; + $search = '(:'.($key + 1).')'; $destination = str_replace($search, $value, $destination, $count); diff --git a/laravel/routing/filter.php b/laravel/routing/filter.php index 14b6e2e3..80beec93 100644 --- a/laravel/routing/filter.php +++ b/laravel/routing/filter.php @@ -14,7 +14,7 @@ class Filter { public static $filters = array(); /** - * The route filters that are based on pattern. + * The route filters that are based on a pattern. * * @var array */ diff --git a/laravel/routing/route.php b/laravel/routing/route.php index 73b79521..090aa59e 100644 --- a/laravel/routing/route.php +++ b/laravel/routing/route.php @@ -10,7 +10,7 @@ class Route { /** - * The URI the route response to. + * The URI the route responds to. * * @var string */ @@ -52,7 +52,7 @@ class Route { public $action; /** - * The parameters that will passed to the route callback. + * The parameters that will be passed to the route callback. * * @var array */ @@ -79,7 +79,7 @@ public function __construct($method, $uri, $action, $parameters = array()) // We'll set the parameters based on the number of parameters passed // compared to the parameters that were needed. If more parameters - // are needed, we'll merge in defaults. + // are needed, we'll merge in the defaults. $this->parameters($action, $parameters); } @@ -96,7 +96,7 @@ protected function parameters($action, $parameters) // If there are less parameters than wildcards, we will figure out how // many parameters we need to inject from the array of defaults and - // merge them in into the main array for the route. + // merge them into the main array for the route. if (count($defaults) > count($parameters)) { $defaults = array_slice($defaults, count($parameters)); @@ -213,6 +213,15 @@ protected function patterns() { if (Str::is($pattern, $this->uri)) { + // If the filter provided is an array then we need to register + // the filter before we can assign it to the route. + if (is_array($filter)) + { + list($filter, $callback) = array_values($filter); + + Filter::register($filter, $callback); + } + $filters[] = $filter; } } diff --git a/laravel/routing/router.php b/laravel/routing/router.php index 7c4888a2..e9935e4c 100644 --- a/laravel/routing/router.php +++ b/laravel/routing/router.php @@ -55,7 +55,7 @@ class Router { public static $group; /** - * The "handes" clause for the bundle currently being routed. + * The "handles" clause for the bundle currently being routed. * * @var string */ @@ -75,7 +75,7 @@ class Router { */ public static $patterns = array( '(:num)' => '([0-9]+)', - '(:any)' => '([a-zA-Z0-9\.\-_%]+)', + '(:any)' => '([a-zA-Z0-9\.\-_%=]+)', '(:all)' => '(.*)', ); @@ -86,7 +86,7 @@ class Router { */ public static $optional = array( '/(:num?)' => '(?:/([0-9]+)', - '/(:any?)' => '(?:/([a-zA-Z0-9\.\-_%]+)', + '/(:any?)' => '(?:/([a-zA-Z0-9\.\-_%=]+)', '/(:all?)' => '(?:/(.*)', ); @@ -206,7 +206,12 @@ public static function register($method, $route, $action) continue; } - $uri = str_replace('(:bundle)', static::$bundle, $uri); + $uri = ltrim(str_replace('(:bundle)', static::$bundle, $uri), '/'); + + if($uri == '') + { + $uri = '/'; + } // If the URI begins with a wildcard, we want to add this route to the // array of "fallback" routes. Fallback routes are always processed @@ -292,7 +297,7 @@ public static function secure_controller($controllers, $defaults = 'index') /** * Register a controller with the router. * - * @param string|array $controller + * @param string|array $controllers * @param string|array $defaults * @param bool $https * @return void @@ -303,7 +308,7 @@ public static function controller($controllers, $defaults = 'index', $https = nu { list($bundle, $controller) = Bundle::parse($identifier); - // First we need to replace the dots with slashes in thte controller name + // First we need to replace the dots with slashes in the controller name // so that it is in directory format. The dots allow the developer to use // a cleaner syntax when specifying the controller. We will also grab the // root URI for the controller's bundle. @@ -311,7 +316,7 @@ public static function controller($controllers, $defaults = 'index', $https = nu $root = Bundle::option($bundle, 'handles'); - // If the controller is a "home" controller, we'll need to also build a + // If the controller is a "home" controller, we'll need to also build an // index method route for the controller. We'll remove "home" from the // route root and setup a route to point to the index method. if (ends_with($controller, 'home')) @@ -428,7 +433,7 @@ public static function uses($action) // To find the route, we'll simply spin through the routes looking // for a route with a "uses" key matching the action, and if we - // find one we cache and return it. + // find one, we cache and return it. foreach (static::routes() as $method => $routes) { foreach ($routes as $key => $value) @@ -484,7 +489,7 @@ protected static function match($method, $uri) { foreach (static::method($method) as $route => $action) { - // We only need to check routes with regular expression since all other + // We only need to check routes with regular expression since all others // would have been able to be matched by the search for literal matches // we just did before we started searching. if (str_contains($route, '(')) diff --git a/laravel/session.php b/laravel/session.php index b5b833fa..877b5a45 100644 --- a/laravel/session.php +++ b/laravel/session.php @@ -1,4 +1,4 @@ -cookie($config); // Some session drivers implement the Sweeper interface meaning that - // they must clean up expired sessions manually. If the driver is a - // sweeper, we'll calculate if we need to run garbage collection. + // they must clean up expired sessions manually. Here we'll calculate + // if we need to run garbage collection. $sweepage = $config['sweepage']; - if ($this->driver instanceof Sweeper and (mt_rand(1, $sweepage[1]) <= $sweepage[0])) + if (mt_rand(1, $sweepage[1]) <= $sweepage[0]) { - $this->driver->sweep(time() - ($config['lifetime'] * 60)); + $this->sweep(); + } + } + + /** + * Clean up expired sessions. + * + * If the session driver is a sweeper, it must clean up expired sessions + * from time to time. This method triggers garbage collection. + * + * @return void + */ + public function sweep() + { + if ($this->driver instanceof Sweeper) + { + $this->driver->sweep(time() - (Config::get('session.lifetime') * 60)); } } diff --git a/laravel/str.php b/laravel/str.php index 964b5d5b..23f2b731 100644 --- a/laravel/str.php +++ b/laravel/str.php @@ -130,6 +130,31 @@ public static function limit($value, $limit = 100, $end = '...') return substr($value, 0, $limit).$end; } + /** + * Limit the number of chracters in a string including custom ending + * + * + * // Returns "Taylor..." + * echo Str::limit_exact('Taylor Otwell', 9); + * + * // Limit the number of characters and append a custom ending + * echo Str::limit_exact('Taylor Otwell', 9, '---'); + * + * + * @param string $value + * @param int $limit + * @param string $end + * @return string + */ + public static function limit_exact($value, $limit = 100, $end = '...') + { + if (static::length($value) <= $limit) return $value; + + $limit -= static::length($end); + + return static::limit($value, $limit, $end); + } + /** * Limit the number of words in a string. * diff --git a/laravel/tests/application/bundles.php b/laravel/tests/application/bundles.php new file mode 100644 index 00000000..1013f0cf --- /dev/null +++ b/laravel/tests/application/bundles.php @@ -0,0 +1,36 @@ + 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('dashboard' => array('handles' => 'dashboard'), 'dummy'); \ No newline at end of file diff --git a/laravel/tests/application/config/application.php b/laravel/tests/application/config/application.php new file mode 100644 index 00000000..596baa24 --- /dev/null +++ b/laravel/tests/application/config/application.php @@ -0,0 +1,158 @@ + '', + + /* + |-------------------------------------------------------------------------- + | 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 + | remain secret and should not be shared with anyone. Make it about 32 + | characters of random gibberish. + | + */ + + 'key' => '', + + /* + |-------------------------------------------------------------------------- + | 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', + + /* + |-------------------------------------------------------------------------- + | 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', + + /* + |-------------------------------------------------------------------------- + | SSL Link Generation + |-------------------------------------------------------------------------- + | + | Many sites use SSL to protect their users data. However, you may not + | always 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. This 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 add as many as you want. + | + | 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. + | + | We have already aliased common Laravel classes to make your life easier. + | + */ + + 'aliases' => array( + 'Auth' => 'Laravel\\Auth', + 'Asset' => 'Laravel\\Asset', + 'Autoloader' => 'Laravel\\Autoloader', + 'Blade' => 'Laravel\\Blade', + 'Bundle' => 'Laravel\\Bundle', + 'Cache' => 'Laravel\\Cache', + 'Config' => 'Laravel\\Config', + 'Controller' => 'Laravel\\Routing\\Controller', + 'Cookie' => 'Laravel\\Cookie', + 'Crypter' => 'Laravel\\Crypter', + 'DB' => 'Laravel\\Database', + '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', + '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', + ), + +); diff --git a/laravel/tests/application/config/auth.php b/laravel/tests/application/config/auth.php new file mode 100644 index 00000000..d715f063 --- /dev/null +++ b/laravel/tests/application/config/auth.php @@ -0,0 +1,73 @@ + 'fluent', + + /* + |-------------------------------------------------------------------------- + | 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' => 'username', + + /* + |-------------------------------------------------------------------------- + | 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', + +); diff --git a/laravel/tests/application/config/cache.php b/laravel/tests/application/config/cache.php new file mode 100644 index 00000000..73fd4c9c --- /dev/null +++ b/laravel/tests/application/config/cache.php @@ -0,0 +1,71 @@ + '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 identifier 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), + + ), + +); \ No newline at end of file diff --git a/laravel/tests/application/config/database.php b/laravel/tests/application/config/database.php new file mode 100644 index 00000000..b7b9fd96 --- /dev/null +++ b/laravel/tests/application/config/database.php @@ -0,0 +1,108 @@ + 'sqlite', + + /* + |-------------------------------------------------------------------------- + | 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, + + /* + |-------------------------------------------------------------------------- + | 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 particlar database of + | choice installed on your machine. + | + | Drivers: 'mysql', 'pgsql', 'sqlsrv', 'sqlite'. + | + */ + + 'connections' => array( + + 'sqlite' => array( + 'driver' => 'sqlite', + 'database' => 'application', + 'prefix' => '', + ), + + 'mysql' => array( + 'driver' => 'mysql', + 'host' => 'localhost', + 'database' => 'database', + 'username' => 'root', + 'password' => 'password', + 'charset' => 'utf8', + 'prefix' => '', + ), + + 'pgsql' => array( + 'driver' => 'pgsql', + 'host' => 'localhost', + 'database' => 'database', + 'username' => 'root', + 'password' => 'password', + 'charset' => 'utf8', + 'prefix' => '', + ), + + 'sqlsrv' => array( + 'driver' => 'sqlsrv', + 'host' => 'localhost', + 'database' => 'database', + 'username' => 'root', + 'password' => '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), + + ), + +); \ No newline at end of file diff --git a/laravel/tests/application/config/error.php b/laravel/tests/application/config/error.php new file mode 100644 index 00000000..87db9665 --- /dev/null +++ b/laravel/tests/application/config/error.php @@ -0,0 +1,69 @@ + array(E_NOTICE, E_USER_NOTICE, E_DEPRECATED, E_USER_DEPRECATED), + + /* + |-------------------------------------------------------------------------- + | 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 setup for you which will log all error messages to + | text files within the application storage directory. + | + */ + + 'logger' => function($exception) + { + Log::exception($exception); + }, + +); \ No newline at end of file diff --git a/laravel/tests/application/config/local/database.php b/laravel/tests/application/config/local/database.php new file mode 100644 index 00000000..bd94d7ba --- /dev/null +++ b/laravel/tests/application/config/local/database.php @@ -0,0 +1,7 @@ + 'sqlite', + +); \ No newline at end of file diff --git a/laravel/tests/application/config/mimes.php b/laravel/tests/application/config/mimes.php new file mode 100644 index 00000000..e2bd4fbb --- /dev/null +++ b/laravel/tests/application/config/mimes.php @@ -0,0 +1,97 @@ + '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'), + +); \ No newline at end of file diff --git a/laravel/tests/application/config/session.php b/laravel/tests/application/config/session.php new file mode 100644 index 00000000..3b6e6a69 --- /dev/null +++ b/laravel/tests/application/config/session.php @@ -0,0 +1,117 @@ + '', + + /* + |-------------------------------------------------------------------------- + | Session Database + |-------------------------------------------------------------------------- + | + | The database table on 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. + | + | 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 application's size and speed. + | + */ + + '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, + +); \ No newline at end of file diff --git a/laravel/tests/application/config/strings.php b/laravel/tests/application/config/strings.php new file mode 100644 index 00000000..bbbe230c --- /dev/null +++ b/laravel/tests/application/config/strings.php @@ -0,0 +1,190 @@ + 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', + + ), + +); diff --git a/laravel/tests/application/controllers/admin/panel.php b/laravel/tests/application/controllers/admin/panel.php new file mode 100644 index 00000000..da3b49d7 --- /dev/null +++ b/laravel/tests/application/controllers/admin/panel.php @@ -0,0 +1,10 @@ +filter('before', 'test-all-before'); + $this->filter('after', 'test-all-after'); + $this->filter('before', 'test-profile-before')->only(array('profile')); + $this->filter('before', 'test-except')->except(array('index', 'profile')); + $this->filter('before', 'test-on-post')->on(array('post')); + $this->filter('before', 'test-on-get-put')->on(array('get', 'put')); + $this->filter('before', 'test-before-filter')->only('login'); + $this->filter('after', 'test-before-filter')->only('logout'); + $this->filter('before', 'test-param:1,2')->only('edit'); + $this->filter('before', 'test-multi-1|test-multi-2')->only('save'); + } + + public function action_index() + { + return __FUNCTION__; + } + + public function action_profile() + { + return __FUNCTION__; + } + + public function action_show() + { + return __FUNCTION__; + } + + public function action_edit() + { + return __FUNCTION__; + } + + public function action_save() + { + return __FUNCTION__; + } + + public function action_login() + { + return __FUNCTION__; + } + + public function action_logout() + { + return __FUNCTION__; + } + +} \ No newline at end of file diff --git a/laravel/tests/application/controllers/home.php b/laravel/tests/application/controllers/home.php new file mode 100644 index 00000000..3f442005 --- /dev/null +++ b/laravel/tests/application/controllers/home.php @@ -0,0 +1,42 @@ + '« Previous', + 'next' => 'Next »', + +); \ No newline at end of file diff --git a/laravel/tests/application/language/en/validation.php b/laravel/tests/application/language/en/validation.php new file mode 100644 index 00000000..5c6354dd --- /dev/null +++ b/laravel/tests/application/language/en/validation.php @@ -0,0 +1,96 @@ + "The :attribute must be accepted.", + "active_url" => "The :attribute is not a valid URL.", + "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.", + "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.", + "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.", + "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.", + "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('custom_required' => 'This field is required!'), + + /* + |-------------------------------------------------------------------------- + | 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('test_attribute' => 'attribute'), + +); \ No newline at end of file diff --git a/laravel/tests/application/language/sp/validation.php b/laravel/tests/application/language/sp/validation.php new file mode 100644 index 00000000..b9bcbe74 --- /dev/null +++ b/laravel/tests/application/language/sp/validation.php @@ -0,0 +1,7 @@ + 'El campo de atributo es necesario.', + +); \ No newline at end of file diff --git a/laravel/tests/application/libraries/.gitignore b/laravel/tests/application/libraries/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/laravel/tests/application/migrations/.gitignore b/laravel/tests/application/migrations/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/laravel/tests/application/models/.gitignore b/laravel/tests/application/models/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/laravel/tests/application/models/autoloader.php b/laravel/tests/application/models/autoloader.php new file mode 100644 index 00000000..0e9027dc --- /dev/null +++ b/laravel/tests/application/models/autoloader.php @@ -0,0 +1,3 @@ + 'home', function() +{ + return View::make('home.index'); +})); + +Route::controller(array( + 'auth', 'filter', 'home', 'restful', + 'template.basic', 'template.name', 'template.override', + 'admin.panel', +)); + +/* +|-------------------------------------------------------------------------- +| 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: +| +| Filter::register('filter', function() +| { +| return 'Filtered!'; +| }); +| +| Next, attach the filter to a route: +| +| Router::register('GET /', array('before' => 'filter', function() +| { +| return 'Hello World!'; +| })); +| +*/ + +Filter::register('before', function() +{ + $_SERVER['before'] = true; +}); + +Filter::register('after', function() +{ + $_SERVER['after'] = true; +}); + +Filter::register('csrf', function() +{ + if (Request::forged()) return Response::error('500'); +}); + +Filter::register('auth', function() +{ + if (Auth::guest()) return Redirect::to('login'); +}); \ No newline at end of file diff --git a/laravel/tests/application/start.php b/laravel/tests/application/start.php new file mode 100644 index 00000000..085dd090 --- /dev/null +++ b/laravel/tests/application/start.php @@ -0,0 +1,157 @@ + 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); +}); + +/* +|-------------------------------------------------------------------------- +| 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(); +} \ No newline at end of file diff --git a/laravel/tests/application/tasks/.gitignore b/laravel/tests/application/tasks/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/laravel/tests/application/views/error/404.php b/laravel/tests/application/views/error/404.php new file mode 100644 index 00000000..9b9bf55b --- /dev/null +++ b/laravel/tests/application/views/error/404.php @@ -0,0 +1,103 @@ + + + + + + Error 404 - Not Found + + + + +
    + + +

    + +

    Server Error: 404 (Not Found)

    + +

    What does this mean?

    + +

    + 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. +

    + +

    + Perhaps you would like to go to our ? +

    +
    + + \ No newline at end of file diff --git a/laravel/tests/application/views/error/500.php b/laravel/tests/application/views/error/500.php new file mode 100644 index 00000000..4dcd92ad --- /dev/null +++ b/laravel/tests/application/views/error/500.php @@ -0,0 +1,103 @@ + + + + + + Error 500 - Internal Server Error + + + + +
    + + +

    + +

    Server Error: 500 (Internal Server Error)

    + +

    What does this mean?

    + +

    + 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. +

    + +

    + Perhaps you would like to go to our ? +

    +
    + + \ No newline at end of file diff --git a/laravel/tests/application/views/home/index.php b/laravel/tests/application/views/home/index.php new file mode 100644 index 00000000..39497146 --- /dev/null +++ b/laravel/tests/application/views/home/index.php @@ -0,0 +1,122 @@ + + + + + + Laravel - A Framework For Web Artisans + + + + +
    +

    Welcome To Laravel

    + +

    A Framework For Web Artisans

    + +

    + You have successfully installed the Laravel framework. Laravel is a simple framework + that helps web artisans create beautiful, creative applications using elegant, expressive + syntax. You'll love using it. +

    + +

    Learn the terrain.

    + +

    + You've landed yourself on our default home page. The route that + is generating this page lives at: +

    + +
    APP_PATH/routes.php
    + +

    And the view sitting before you can be found at:

    + +
    APP_PATH/views/home/index.php
    + +

    Create something beautiful.

    + +

    + Now that you're up and running, it's time to start creating! + Here are some links to help you get started: +

    + + + +
    + + \ No newline at end of file diff --git a/laravel/tests/application/views/tests/basic.php b/laravel/tests/application/views/tests/basic.php new file mode 100644 index 00000000..c961dc2f --- /dev/null +++ b/laravel/tests/application/views/tests/basic.php @@ -0,0 +1 @@ + is \ No newline at end of file diff --git a/laravel/tests/application/views/tests/nested.php b/laravel/tests/application/views/tests/nested.php new file mode 100644 index 00000000..9ce498e5 --- /dev/null +++ b/laravel/tests/application/views/tests/nested.php @@ -0,0 +1 @@ +Taylor \ No newline at end of file diff --git a/laravel/tests/bundles/.gitignore b/laravel/tests/bundles/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/laravel/tests/bundles/dashboard/config/meta.php b/laravel/tests/bundles/dashboard/config/meta.php new file mode 100644 index 00000000..a82d1703 --- /dev/null +++ b/laravel/tests/bundles/dashboard/config/meta.php @@ -0,0 +1,7 @@ + 'dashboard', + +); \ No newline at end of file diff --git a/laravel/tests/bundles/dashboard/controllers/panel.php b/laravel/tests/bundles/dashboard/controllers/panel.php new file mode 100644 index 00000000..b532296d --- /dev/null +++ b/laravel/tests/bundles/dashboard/controllers/panel.php @@ -0,0 +1,10 @@ + 'dashboard', function() +{ + // +})); + +Route::controller('dashboard::panel'); \ No newline at end of file diff --git a/laravel/tests/bundles/dummy/routes.php b/laravel/tests/bundles/dummy/routes.php new file mode 100644 index 00000000..2117e2e0 --- /dev/null +++ b/laravel/tests/bundles/dummy/routes.php @@ -0,0 +1,6 @@ +assertTrue($container === Asset::container('foo')); + $this->assertInstanceOf('\\Laravel\\Asset_Container', $container); + } + + /** + * Test the Asset::container method for default container creation. + * + * @group laravel + */ + public function testDefaultContainerCreatedByDefault() + { + $this->assertEquals('default', Asset::container()->name); + } + + /** + * Test the Asset::__callStatic method. + * + * @group laravel + */ + public function testContainerMethodsCanBeDynamicallyCalled() + { + Asset::style('common', 'common.css'); + + $this->assertEquals('common.css', Asset::container()->assets['style']['common']['source']); + } + + /** + * Test the Asset_Container constructor. + * + * @group laravel + */ + public function testNameIsSetOnAssetContainerConstruction() + { + $container = $this->getContainer(); + + $this->assertEquals('foo', $container->name); + } + + /** + * Test the Asset_Container::add method. + * + * @group laravel + */ + public function testAddMethodProperlySniffsAssetType() + { + $container = $this->getContainer(); + + $container->add('jquery', 'jquery.js'); + $container->add('common', 'common.css'); + + $this->assertEquals('jquery.js', $container->assets['script']['jquery']['source']); + $this->assertEquals('common.css', $container->assets['style']['common']['source']); + } + + /** + * Test the Asset_Container::style method. + * + * @group laravel + */ + public function testStyleMethodProperlyRegistersAnAsset() + { + $container = $this->getContainer(); + + $container->style('common', 'common.css'); + + $this->assertEquals('common.css', $container->assets['style']['common']['source']); + } + + /** + * Test the Asset_Container::style method sets media attribute. + * + * @group laravel + */ + public function testStyleMethodProperlySetsMediaAttributeIfNotSet() + { + $container = $this->getContainer(); + + $container->style('common', 'common.css'); + + $this->assertEquals('all', $container->assets['style']['common']['attributes']['media']); + } + + /** + * Test the Asset_Container::style method sets media attribute. + * + * @group laravel + */ + public function testStyleMethodProperlyIgnoresMediaAttributeIfSet() + { + $container = $this->getContainer(); + + $container->style('common', 'common.css', array(), array('media' => 'print')); + + $this->assertEquals('print', $container->assets['style']['common']['attributes']['media']); + } + + /** + * Test the Asset_Container::script method. + * + * @group laravel + */ + public function testScriptMethodProperlyRegistersAnAsset() + { + $container = $this->getContainer(); + + $container->script('jquery', 'jquery.js'); + + $this->assertEquals('jquery.js', $container->assets['script']['jquery']['source']); + } + + /** + * Test the Asset_Container::add method properly sets dependencies. + * + * @group laravel + */ + public function testAddMethodProperlySetsDependencies() + { + $container = $this->getContainer(); + + $container->add('common', 'common.css', 'jquery'); + $container->add('jquery', 'jquery.js', array('jquery-ui')); + + $this->assertEquals(array('jquery'), $container->assets['style']['common']['dependencies']); + $this->assertEquals(array('jquery-ui'), $container->assets['script']['jquery']['dependencies']); + } + + /** + * Test the Asset_Container::add method properly sets attributes. + * + * @group laravel + */ + public function testAddMethodProperlySetsAttributes() + { + $container = $this->getContainer(); + + $container->add('common', 'common.css', array(), array('media' => 'print')); + $container->add('jquery', 'jquery.js', array(), array('defer')); + + $this->assertEquals(array('media' => 'print'), $container->assets['style']['common']['attributes']); + $this->assertEquals(array('defer'), $container->assets['script']['jquery']['attributes']); + } + + /** + * Test the Asset_Container::bundle method. + * + * @group laravel + */ + public function testBundleMethodCorrectlySetsTheAssetBundle() + { + $container = $this->getContainer(); + + $container->bundle('eloquent'); + + $this->assertEquals('eloquent', $container->bundle); + } + + /** + * Test the Asset_Container::path method. + * + * @group laravel + */ + public function testPathMethodReturnsCorrectPathForABundleAsset() + { + $container = $this->getContainer(); + + $container->bundle('eloquent'); + + $this->assertEquals('/bundles/eloquent/foo.jpg', $container->path('foo.jpg')); + } + + /** + * Test the Asset_Container::path method. + * + * @group laravel + */ + public function testPathMethodReturnsCorrectPathForAnApplicationAsset() + { + $container = $this->getContainer(); + + $this->assertEquals('/foo.jpg', $container->path('foo.jpg')); + } + + /** + * Test the Asset_Container::scripts method. + * + * @group laravel + */ + public function testScriptsCanBeRetrieved() + { + $container = $this->getContainer(); + + $container->script('dojo', 'dojo.js', array('jquery-ui')); + $container->script('jquery', 'jquery.js', array('jquery-ui', 'dojo')); + $container->script('jquery-ui', 'jquery-ui.js'); + + $scripts = $container->scripts(); + + $this->assertTrue(strpos($scripts, 'jquery.js') > 0); + $this->assertTrue(strpos($scripts, 'jquery.js') > strpos($scripts, 'jquery-ui.js')); + $this->assertTrue(strpos($scripts, 'dojo.js') > strpos($scripts, 'jquery-ui.js')); + } + + /** + * Test the Asset_Container::styles method. + * + * @group laravel + */ + public function testStylesCanBeRetrieved() + { + $container = $this->getContainer(); + + $container->style('dojo', 'dojo.css', array('jquery-ui'), array('media' => 'print')); + $container->style('jquery', 'jquery.css', array('jquery-ui', 'dojo')); + $container->style('jquery-ui', 'jquery-ui.css'); + + $styles = $container->styles(); + + $this->assertTrue(strpos($styles, 'jquery.css') > 0); + $this->assertTrue(strpos($styles, 'media="print"') > 0); + $this->assertTrue(strpos($styles, 'jquery.css') > strpos($styles, 'jquery-ui.css')); + $this->assertTrue(strpos($styles, 'dojo.css') > strpos($styles, 'jquery-ui.css')); + } + + /** + * Get an asset container instance. + * + * @param string $name + * @return Asset_Container + */ + private function getContainer($name = 'foo') + { + return new Laravel\Asset_Container($name); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/auth.test.php b/laravel/tests/cases/auth.test.php new file mode 100644 index 00000000..16ba428a --- /dev/null +++ b/laravel/tests/cases/auth.test.php @@ -0,0 +1,359 @@ +user = null; + Session::$instance = null; + Config::set('database.default', 'sqlite'); + } + + /** + * Tear down the test environment. + */ + public function tearDown() + { + $_SERVER['auth.login.stub'] = null; + Cookie::$jar = array(); + Config::$items = array(); + Auth::driver()->user = null; + Session::$instance = null; + Config::set('database.default', 'mysql'); + } + + /** + * Set one of the $_SERVER variables. + * + * @param string $key + * @param string $value + */ + protected function setServerVar($key, $value) + { + $_SERVER[$key] = $value; + + $this->restartRequest(); + } + + /** + * Reinitialize the global request. + * + * @return void + */ + protected function restartRequest() + { + // FIXME: Ugly hack, but old contents from previous requests seem to + // trip up the Foundation class. + $_FILES = array(); + + Request::$foundation = RequestFoundation::createFromGlobals(); + } + + /** + * Test the Auth::user method. + * + * @group laravel + */ + public function testUserMethodReturnsCurrentUser() + { + Auth::driver()->user = 'Taylor'; + + $this->assertEquals('Taylor', Auth::user()); + } + + /** + * Test the Auth::check method. + * + * @group laravel + */ + public function testCheckMethodReturnsTrueWhenUserIsSet() + { + $auth = new AuthUserReturnsDummy; + + $this->assertTrue($auth->check()); + } + + /** + * Test the Auth::check method. + * + * @group laravel + */ + public function testCheckMethodReturnsFalseWhenNoUserIsSet() + { + $auth = new AuthUserReturnsNull; + + $this->assertFalse($auth->check()); + } + + /** + * Test the Auth::guest method. + * + * @group laravel + */ + public function testGuestReturnsTrueWhenNoUserIsSet() + { + $auth = new AuthUserReturnsNull; + + $this->assertTrue($auth->guest()); + } + + /** + * Test the Auth::guest method. + * + * @group laravel + */ + public function testGuestReturnsFalseWhenUserIsSet() + { + $auth = new AuthUserReturnsDummy; + + $this->assertFalse($auth->guest()); + } + + /** + * Test the Auth::user method. + * + * @group laravel + */ + public function testUserMethodReturnsNullWhenNoUserExistsAndNoRecallerExists() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + $this->assertNull(Auth::user()); + } + + /** + * Test the Auth::user method. + * + * @group laravel + */ + public function testUserReturnsUserByID() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + Auth::login(1); + + $this->assertEquals('Taylor Otwell', Auth::user()->name); + + Auth::logout(); + } + + /** + * Test the Auth::user method. + * + * @group laravel + */ + public function testNullReturnedWhenUserIDNotValidInteger() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + Auth::login('asdlkasd'); + + $this->assertNull(Auth::user()); + } + + /** + * Test the Auth::recall method. + * + * @group laravel + */ + public function testUserCanBeRecalledViaCookie() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + $cookie = Crypter::encrypt('1|'.Str::random(40)); + Cookie::forever('authloginstub_remember', $cookie); + + $auth = new AuthLoginStub; + + $this->assertEquals('Taylor Otwell', $auth->user()->name); + + $this->assertTrue($auth->user()->id === $_SERVER['auth.login.stub']['user']); + } + + /** + * Test the Auth::attempt method. + * + * @group laravel + */ + public function testAttemptMethodReturnsFalseWhenCredentialsAreInvalid() + { + $this->assertFalse(Auth::attempt(array('username' => 'foo', 'password' => 'foo'))); + $this->assertFalse(Auth::attempt(array('username' => 'foo', 'password' => null))); + $this->assertFalse(Auth::attempt(array('username' => null, 'password' => null))); + $this->assertFalse(Auth::attempt(array('username' => 'taylor', 'password' => 'password'))); + $this->assertFalse(Auth::attempt(array('username' => 'taylor', 'password' => 232))); + } + + /** + * Test the Auth::attempt method. + * + * @group laravel + */ + public function testAttemptReturnsTrueWhenCredentialsAreCorrect() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + $auth = new AuthLoginStub; + + $this->assertTrue($auth->attempt(array('username' => 'taylor', 'password' => 'password1'))); + $this->assertEquals('1', $_SERVER['auth.login.stub']['user']); + $this->assertFalse($_SERVER['auth.login.stub']['remember']); + + $auth_secure = new AuthLoginStub; + + $this->assertTrue($auth_secure->attempt(array('username' => 'taylor', 'password' => 'password1', 'remember' => true))); + $this->assertEquals('1', $_SERVER['auth.login.stub']['user']); + $this->assertTrue($_SERVER['auth.login.stub']['remember']); + + $auth_secure->logout(); + $auth->logout(); + } + + /** + * Test Auth::login method. + * + * @group laravel + */ + public function testLoginMethodStoresUserKeyInSession() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + $user = new StdClass; + $user->id = 10; + Auth::login($user); + // FIXME: Not sure whether hard-coding the key is a good idea. + $user = Session::$instance->session['data']['laravel_auth_drivers_fluent_login']; + $this->assertEquals(10, $user->id); + + + Auth::logout(); + + Auth::login(5); + $user = Session::$instance->session['data']['laravel_auth_drivers_fluent_login']; + $this->assertEquals(5, $user); + Auth::logout(5); + } + + /** + * Test the Auth::login method. + * + * @group laravel + */ + public function testLoginStoresRememberCookieWhenNeeded() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + $this->setServerVar('HTTPS', 'on'); + + // Set the session vars to make sure remember cookie uses them + Config::set('session.path', 'foo'); + Config::set('session.domain', 'bar'); + Config::set('session.secure', true); + + Auth::login(1, true); + + $this->assertTrue(isset(Cookie::$jar['laravel_auth_drivers_fluent_remember'])); + + $cookie = Cookie::$jar['laravel_auth_drivers_fluent_remember']['value']; + $cookie = explode('|', Crypter::decrypt($cookie)); + $this->assertEquals(1, $cookie[0]); + $this->assertEquals('foo', Cookie::$jar['laravel_auth_drivers_fluent_remember']['path']); + $this->assertEquals('bar', Cookie::$jar['laravel_auth_drivers_fluent_remember']['domain']); + $this->assertTrue(Cookie::$jar['laravel_auth_drivers_fluent_remember']['secure']); + + Auth::logout(); + + $this->setServerVar('HTTPS', 'off'); + } + + /** + * Test the Auth::logout method. + * + * @group laravel + */ + public function testLogoutMethodLogsOutUser() + { + Session::$instance = new Payload($this->getMock('Laravel\\Session\\Drivers\\Driver')); + + $data = Session::$instance->session['data']['laravel_auth_drivers_fluent_login'] = 1; + + Auth::logout(); + + // A workaround since Cookie will is only stored in memory, until Response class is called. + Auth::driver()->token = null; + + $this->assertNull(Auth::user()); + + $this->assertFalse(isset(Session::$instance->session['data']['laravel_auth_drivers_fluent_login'])); + $this->assertTrue(Cookie::$jar['laravel_auth_drivers_fluent_remember']['expiration'] < time()); + } + +} + +class AuthUserReturnsNull extends Laravel\Auth\Drivers\Driver { + + public function user() { return null; } + + public function retrieve($id) { return null; } + + public function attempt($arguments = array()) { return null; } + +} + +class AuthUserReturnsDummy extends Laravel\Auth\Drivers\Driver { + + public function user() { return 'Taylor'; } + + public function retrieve($id) { return null; } + + public function attempt($arguments = array()) + { + return $this->login($arguments['username']); + } + +} + +class AuthLoginStub extends Laravel\Auth\Drivers\Fluent { + + public function login($user, $remember = false) + { + if (is_null($remember)) $remember = false; + + $_SERVER['auth.login.stub'] = compact('user', 'remember'); + + return parent::login($user, $remember); + } + + public function logout() + { + parent::logout(); + } + + public function retrieve($id) + { + $user = parent::retrieve($id); + + $_SERVER['auth.login.stub'] = array( + 'user' => $user->id, + 'remember' => false, + ); + + return $user; + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/autoloader.test.php b/laravel/tests/cases/autoloader.test.php new file mode 100644 index 00000000..80605447 --- /dev/null +++ b/laravel/tests/cases/autoloader.test.php @@ -0,0 +1,102 @@ + path('app').'models/foo.php', + )); + + $this->assertEquals(path('app').'models/foo.php', Autoloader::$mappings['Foo']); + } + + /** + * Test the Autoloader::alias method. + * + * @group laravel + */ + public function testAliasesCanBeRegistered() + { + Autoloader::alias('Foo\\Bar', 'Foo'); + + $this->assertEquals('Foo\\Bar', Autoloader::$aliases['Foo']); + } + + /** + * Test the Autoloader::directories method. + * + * @group laravel + */ + public function testPsrDirectoriesCanBeRegistered() + { + Autoloader::directories(array( + path('app').'foo'.DS.'bar', + path('app').'foo'.DS.'baz'.DS.DS, + )); + + $this->assertTrue(in_array(path('app').'foo'.DS.'bar'.DS, Autoloader::$directories)); + $this->assertTrue(in_array(path('app').'foo'.DS.'baz'.DS, Autoloader::$directories)); + } + + /** + * Test the Autoloader::namespaces method. + * + * @group laravel + */ + public function testNamespacesCanBeRegistered() + { + Autoloader::namespaces(array( + 'Autoloader_1' => path('bundle').'autoload'.DS.'models', + 'Autoloader_2' => path('bundle').'autoload'.DS.'libraries'.DS.DS, + )); + + $this->assertEquals(path('bundle').'autoload'.DS.'models'.DS, Autoloader::$namespaces['Autoloader_1\\']); + $this->assertEquals(path('bundle').'autoload'.DS.'libraries'.DS, Autoloader::$namespaces['Autoloader_2\\']); + } + + /** + * Test the loading of PSR-0 models and libraries. + * + * @group laravel + */ + public function testPsrLibrariesAndModelsCanBeLoaded() + { + $this->assertInstanceOf('User', new User); + $this->assertInstanceOf('Repositories\\User', new Repositories\User); + } + + /** + * Test the loading of hard-coded classes. + * + * @group laravel + */ + public function testHardcodedClassesCanBeLoaded() + { + Autoloader::map(array( + 'Autoloader_HardCoded' => path('app').'models'.DS.'autoloader.php', + )); + + $this->assertInstanceOf('Autoloader_HardCoded', new Autoloader_HardCoded); + } + + /** + * Test the loading of classes mapped by namespaces. + * + * @group laravel + */ + public function testClassesMappedByNamespaceCanBeLoaded() + { + Autoloader::namespaces(array( + 'Dashboard' => path('bundle').'dashboard'.DS.'models', + )); + + $this->assertInstanceOf('Dashboard\\Repository', new Dashboard\Repository); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/blade.test.php b/laravel/tests/cases/blade.test.php new file mode 100644 index 00000000..70e80b3b --- /dev/null +++ b/laravel/tests/cases/blade.test.php @@ -0,0 +1,63 @@ +assertEquals('', Blade::compile_string($blade1)); + $this->assertEquals('', Blade::compile_string($blade2)); + } + + /** + * Test the compilation of control structures. + * + * @group laravel + */ + public function testControlStructuresAreCreatedCorrectly() + { + $blade1 = "@if (true)\nfoo\n@endif"; + $blade2 = "@if (count(".'$something'.") > 0)\nfoo\n@endif"; + $blade3 = "@if (true)\nfoo\n@elseif (false)\nbar\n@endif"; + $blade4 = "@if (true)\nfoo\n@else\nbar\n@endif"; + + $this->assertEquals("\nfoo\n", Blade::compile_string($blade1)); + $this->assertEquals(" 0): ?>\nfoo\n", Blade::compile_string($blade2)); + $this->assertEquals("\nfoo\n\nbar\n", Blade::compile_string($blade3)); + $this->assertEquals("\nfoo\n\nbar\n", Blade::compile_string($blade4)); + } + + /** + * Test the compilation of yield statements. + * + * @group laravel + */ + public function testYieldsAreCompiledCorrectly() + { + $blade = "@yield('something')"; + + $this->assertEquals("", Blade::compile_string($blade)); + } + + /** + * Test the compilation of section statements. + * + * @group laravel + */ + public function testSectionsAreCompiledCorrectly() + { + $blade = "@section('something')\nfoo\n@endsection"; + + $this->assertEquals("\nfoo\n", Blade::compile_string($blade)); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/bundle.test.php b/laravel/tests/cases/bundle.test.php new file mode 100644 index 00000000..9826a50f --- /dev/null +++ b/laravel/tests/cases/bundle.test.php @@ -0,0 +1,251 @@ + 'foo-baz')); + $this->assertEquals('foo-baz', Bundle::$bundles['foo-baz']['handles']); + $this->assertFalse(Bundle::$bundles['foo-baz']['auto']); + + Bundle::register('foo-bar', array()); + $this->assertFalse(Bundle::$bundles['foo-baz']['auto']); + $this->assertNull(Bundle::$bundles['foo-bar']['handles']); + + unset(Bundle::$bundles['foo-baz']); + unset(Bundle::$bundles['foo-bar']); + } + + /** + * Test the Bundle::start method. + * + * @group laravel + */ + public function testStartMethodStartsBundle() + { + $_SERVER['bundle.dummy.start'] = 0; + $_SERVER['bundle.dummy.routes'] = 0; + + $_SERVER['started.dummy'] = false; + + Event::listen('laravel.started: dummy', function() + { + $_SERVER['started.dummy'] = true; + }); + + Bundle::register('dummy'); + Bundle::start('dummy'); + + $this->assertTrue($_SERVER['started.dummy']); + $this->assertEquals(1, $_SERVER['bundle.dummy.start']); + $this->assertEquals(1, $_SERVER['bundle.dummy.routes']); + + Bundle::start('dummy'); + + $this->assertEquals(1, $_SERVER['bundle.dummy.start']); + $this->assertEquals(1, $_SERVER['bundle.dummy.routes']); + } + + /** + * Test Bundle::handles method. + * + * @group laravel + */ + public function testHandlesMethodReturnsBundleThatHandlesURI() + { + Bundle::register('foo', array('handles' => 'foo-bar')); + $this->assertEquals('foo', Bundle::handles('foo-bar/admin')); + unset(Bundle::$bundles['foo']); + } + + /** + * Test the Bundle::exist method. + * + * @group laravel + */ + public function testExistMethodIndicatesIfBundleExist() + { + $this->assertTrue(Bundle::exists('dashboard')); + $this->assertFalse(Bundle::exists('foo')); + } + + /** + * Test the Bundle::started method. + * + * @group laravel + */ + public function testStartedMethodIndicatesIfBundleIsStarted() + { + Bundle::register('dummy'); + Bundle::start('dummy'); + $this->assertTrue(Bundle::started('dummy')); + } + + /** + * Test the Bundle::prefix method. + * + * @group laravel + */ + public function testPrefixMethodReturnsCorrectPrefix() + { + $this->assertEquals('dummy::', Bundle::prefix('dummy')); + $this->assertEquals('', Bundle::prefix(DEFAULT_BUNDLE)); + } + + /** + * Test the Bundle::class_prefix method. + * + * @group laravel + */ + public function testClassPrefixMethodReturnsProperClassPrefixForBundle() + { + $this->assertEquals('Dummy_', Bundle::class_prefix('dummy')); + $this->assertEquals('', Bundle::class_prefix(DEFAULT_BUNDLE)); + } + + /** + * Test the Bundle::path method. + * + * @group laravel + */ + public function testPathMethodReturnsCorrectPath() + { + $this->assertEquals(path('app'), Bundle::path(null)); + $this->assertEquals(path('app'), Bundle::path(DEFAULT_BUNDLE)); + $this->assertEquals(path('bundle').'dashboard'.DS, Bundle::path('dashboard')); + } + + /** + * Test the Bundle::asset method. + * + * @group laravel + */ + public function testAssetPathReturnsPathToBundlesAssets() + { + $this->assertEquals('/bundles/dashboard/', Bundle::assets('dashboard')); + $this->assertEquals('/', Bundle::assets(DEFAULT_BUNDLE)); + + Config::set('application.url', ''); + } + + /** + * Test the Bundle::name method. + * + * @group laravel + */ + public function testBundleNameCanBeRetrievedFromIdentifier() + { + $this->assertEquals(DEFAULT_BUNDLE, Bundle::name('something')); + $this->assertEquals(DEFAULT_BUNDLE, Bundle::name('something.else')); + $this->assertEquals('bundle', Bundle::name('bundle::something.else')); + } + + /** + * Test the Bundle::element method. + * + * @group laravel + */ + public function testElementCanBeRetrievedFromIdentifier() + { + $this->assertEquals('something', Bundle::element('something')); + $this->assertEquals('something.else', Bundle::element('something.else')); + $this->assertEquals('something.else', Bundle::element('bundle::something.else')); + } + + /** + * Test the Bundle::identifier method. + * + * @group laravel + */ + public function testIdentifierCanBeConstructed() + { + $this->assertEquals('something.else', Bundle::identifier(DEFAULT_BUNDLE, 'something.else')); + $this->assertEquals('dashboard::something', Bundle::identifier('dashboard', 'something')); + $this->assertEquals('dashboard::something.else', Bundle::identifier('dashboard', 'something.else')); + } + + /** + * Test the Bundle::resolve method. + * + * @group laravel + */ + public function testBundleNamesCanBeResolved() + { + $this->assertEquals(DEFAULT_BUNDLE, Bundle::resolve('foo')); + $this->assertEquals('dashboard', Bundle::resolve('dashboard')); + } + + /** + * Test the Bundle::parse method. + * + * @group laravel + */ + public function testParseMethodReturnsElementAndIdentifier() + { + $this->assertEquals(array('application', 'something'), Bundle::parse('something')); + $this->assertEquals(array('application', 'something.else'), Bundle::parse('something.else')); + $this->assertEquals(array('dashboard', 'something'), Bundle::parse('dashboard::something')); + $this->assertEquals(array('dashboard', 'something.else'), Bundle::parse('dashboard::something.else')); + } + + /** + * Test the Bundle::get method. + * + * @group laravel + */ + public function testOptionMethodReturnsBundleOption() + { + $this->assertFalse(Bundle::option('dashboard', 'auto')); + $this->assertEquals('dashboard', Bundle::option('dashboard', 'location')); + } + + /** + * Test the Bundle::all method. + * + * @group laravel + */ + public function testAllMethodReturnsBundleArray() + { + Bundle::register('foo'); + $this->assertEquals(Bundle::$bundles, Bundle::all()); + unset(Bundle::$bundles['foo']); + } + + /** + * Test the Bundle::names method. + * + * @group laravel + */ + public function testNamesMethodReturnsBundleNames() + { + Bundle::register('foo'); + $this->assertEquals(array('dashboard', 'dummy', 'foo'), Bundle::names()); + unset(Bundle::$bundles['foo']); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/config.test.php b/laravel/tests/cases/config.test.php new file mode 100644 index 00000000..573b8cff --- /dev/null +++ b/laravel/tests/cases/config.test.php @@ -0,0 +1,79 @@ +assertEquals('UTF-8', Config::get('application.encoding')); + $this->assertEquals('mysql', Config::get('database.connections.mysql.driver')); + $this->assertEquals('dashboard', Config::get('dashboard::meta.bundle')); + } + + /** + * Test the Config::has method. + * + * @group laravel + */ + public function testHasMethodIndicatesIfConfigItemExists() + { + $this->assertFalse(Config::has('application.foo')); + $this->assertTrue(Config::has('application.encoding')); + } + + /** + * Test the Config::set method. + * + * @group laravel + */ + public function testConfigItemsCanBeSet() + { + Config::set('application.encoding', 'foo'); + Config::set('dashboard::meta.bundle', 'bar'); + + $this->assertEquals('foo', Config::get('application.encoding')); + $this->assertEquals('bar', Config::get('dashboard::meta.bundle')); + } + + /** + * Test that environment configurations are loaded correctly. + * + * @group laravel + */ + public function testEnvironmentConfigsOverrideNormalConfigurations() + { + $_SERVER['LARAVEL_ENV'] = 'local'; + + $this->assertEquals('sqlite', Config::get('database.default')); + + unset($_SERVER['LARAVEL_ENV']); + } + + /** + * Test that items can be set after the entire file has already been loaded. + * + * @group laravel + */ + public function testItemsCanBeSetAfterEntireFileIsLoaded() + { + Config::get('application'); + Config::set('application.key', 'taylor'); + $application = Config::get('application'); + + $this->assertEquals('taylor', $application['key']); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/controller.test.php b/laravel/tests/cases/controller.test.php new file mode 100644 index 00000000..9eb192b9 --- /dev/null +++ b/laravel/tests/cases/controller.test.php @@ -0,0 +1,267 @@ +assertEquals('action_index', Controller::call('auth@index')->content); + $this->assertEquals('Admin_Panel_Index', Controller::call('admin.panel@index')->content); + $this->assertEquals('Taylor', Controller::call('auth@profile', array('Taylor'))->content); + $this->assertEquals('Dashboard_Panel_Index', Controller::call('dashboard::panel@index')->content); + } + + /** + * Test basic controller filters are called. + * + * @group laravel + */ + public function testAssignedBeforeFiltersAreRun() + { + $_SERVER['test-all-after'] = false; + $_SERVER['test-all-before'] = false; + + Controller::call('filter@index'); + + $this->assertTrue($_SERVER['test-all-after']); + $this->assertTrue($_SERVER['test-all-before']); + } + + /** + * Test that "only" filters only apply to their assigned methods. + * + * @group laravel + */ + public function testOnlyFiltersOnlyApplyToTheirAssignedMethods() + { + $_SERVER['test-profile-before'] = false; + + Controller::call('filter@index'); + + $this->assertFalse($_SERVER['test-profile-before']); + + Controller::call('filter@profile'); + + $this->assertTrue($_SERVER['test-profile-before']); + } + + /** + * Test that "except" filters only apply to the excluded methods. + * + * @group laravel + */ + public function testExceptFiltersOnlyApplyToTheExlucdedMethods() + { + $_SERVER['test-except'] = false; + + Controller::call('filter@index'); + Controller::call('filter@profile'); + + $this->assertFalse($_SERVER['test-except']); + + Controller::call('filter@show'); + + $this->assertTrue($_SERVER['test-except']); + } + + /** + * Test that filters can be constrained by the request method. + * + * @group laravel + */ + public function testFiltersCanBeConstrainedByRequestMethod() + { + $_SERVER['test-on-post'] = false; + + Request::$foundation->setMethod('GET'); + Controller::call('filter@index'); + + $this->assertFalse($_SERVER['test-on-post']); + + Request::$foundation->setMethod('POST'); + Controller::call('filter@index'); + + $this->assertTrue($_SERVER['test-on-post']); + + $_SERVER['test-on-get-put'] = false; + + Request::$foundation->setMethod('POST'); + Controller::call('filter@index'); + + $this->assertFalse($_SERVER['test-on-get-put']); + + Request::$foundation->setMethod('PUT'); + Controller::call('filter@index'); + + $this->assertTrue($_SERVER['test-on-get-put']); + } + + public function testGlobalBeforeFilterIsNotCalledByController() + { + $_SERVER['before'] = false; + $_SERVER['after'] = false; + + Controller::call('auth@index'); + + $this->assertFalse($_SERVER['before']); + $this->assertFalse($_SERVER['after']); + } + + /** + * Test that before filters can override the controller response. + * + * @group laravel + */ + public function testBeforeFiltersCanOverrideResponses() + { + $this->assertEquals('Filtered!', Controller::call('filter@login')->content); + } + + /** + * Test that after filters do not affect the response. + * + * @group laravel + */ + public function testAfterFiltersDoNotAffectControllerResponse() + { + $this->assertEquals('action_logout', Controller::call('filter@logout')->content); + } + + /** + * Test that filter parameters are passed to the filter. + * + * @group laravel + */ + public function testFilterParametersArePassedToTheFilter() + { + $this->assertEquals('12', Controller::call('filter@edit')->content); + } + + /** + * Test that multiple filters can be assigned to a single method. + * + * @group laravel + */ + public function testMultipleFiltersCanBeAssignedToAnAction() + { + $_SERVER['test-multi-1'] = false; + $_SERVER['test-multi-2'] = false; + + Controller::call('filter@save'); + + $this->assertTrue($_SERVER['test-multi-1']); + $this->assertTrue($_SERVER['test-multi-2']); + } + + /** + * Test Restful controllers respond by request method. + * + * @group laravel + */ + public function testRestfulControllersRespondWithRestfulMethods() + { + Request::$foundation->setMethod('GET'); + //$_SERVER['REQUEST_METHOD'] = 'GET'; + + $this->assertEquals('get_index', Controller::call('restful@index')->content); + + //$_SERVER['REQUEST_METHOD'] = 'PUT'; + Request::$foundation->setMethod('PUT'); + + $this->assertEquals(404, Controller::call('restful@index')->status()); + + //$_SERVER['REQUEST_METHOD'] = 'POST'; + Request::$foundation->setMethod('POST'); + + $this->assertEquals('post_index', Controller::call('restful@index')->content); + } + + /** + * Test that the template is returned by template controllers. + * + * @group laravel + */ + public function testTemplateControllersReturnTheTemplate() + { + $response = Controller::call('template.basic@index'); + + $home = file_get_contents(path('app').'views/home/index.php'); + + $this->assertEquals($home, $response->content); + } + + /** + * Test that controller templates can be named views. + * + * @group laravel + */ + public function testControllerTemplatesCanBeNamedViews() + { + View::name('home.index', 'home'); + + $response = Controller::call('template.named@index'); + + $home = file_get_contents(path('app').'views/home/index.php'); + + $this->assertEquals($home, $response->content); + + View::$names = array(); + } + + /** + * Test that the "layout" method is called on the controller. + * + * @group laravel + */ + public function testTheTemplateCanBeOverriden() + { + $this->assertEquals('Layout', Controller::call('template.override@index')->content); + } + + /** + * Test the Controller::resolve method. + * + * @group laravel + */ + public function testResolveMethodChecksTheIoCContainer() + { + IoC::register('controller: home', function() + { + require_once path('app').'controllers/home.php'; + + $controller = new Home_Controller; + + $controller->foo = 'bar'; + + return $controller; + }); + + $controller = Controller::resolve(DEFAULT_BUNDLE, 'home'); + + $this->assertEquals('bar', $controller->foo); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/cookie.test.php b/laravel/tests/cases/cookie.test.php new file mode 100644 index 00000000..f62f7857 --- /dev/null +++ b/laravel/tests/cases/cookie.test.php @@ -0,0 +1,134 @@ +restartRequest(); + } + + /** + * Reinitialize the global request. + * + * @return void + */ + protected function restartRequest() + { + // FIXME: Ugly hack, but old contents from previous requests seem to + // trip up the Foundation class. + $_FILES = array(); + + Request::$foundation = RequestFoundation::createFromGlobals(); + } + + /** + * Test Cookie::has method. + * + * @group laravel + */ + public function testHasMethodIndicatesIfCookieInSet() + { + Cookie::$jar['foo'] = array('value' => 'bar'); + $this->assertTrue(Cookie::has('foo')); + $this->assertFalse(Cookie::has('bar')); + + Cookie::put('baz', 'foo'); + $this->assertTrue(Cookie::has('baz')); + } + + /** + * Test the Cookie::get method. + * + * @group laravel + */ + public function testGetMethodCanReturnValueOfCookies() + { + Cookie::$jar['foo'] = array('value' => 'bar'); + $this->assertEquals('bar', Cookie::get('foo')); + + Cookie::put('bar', 'baz'); + $this->assertEquals('baz', Cookie::get('bar')); + } + + /** + * Test Cookie::forever method. + * + * @group laravel + */ + public function testForeverShouldUseATonOfMinutes() + { + Cookie::forever('foo', 'bar'); + $this->assertEquals('bar', Cookie::$jar['foo']['value']); + + // Shouldn't be able to test this cause while we indicate -2000 seconds + // cookie expiration store timestamp. + // $this->assertEquals(525600, Cookie::$jar['foo']['expiration']); + + $this->setServerVar('HTTPS', 'on'); + + Cookie::forever('bar', 'baz', 'path', 'domain', true); + $this->assertEquals('path', Cookie::$jar['bar']['path']); + $this->assertEquals('domain', Cookie::$jar['bar']['domain']); + $this->assertTrue(Cookie::$jar['bar']['secure']); + + $this->setServerVar('HTTPS', 'off'); + } + + /** + * Test the Cookie::forget method. + * + * @group laravel + */ + public function testForgetSetsCookieWithExpiration() + { + Cookie::forget('bar', 'path', 'domain'); + + // Shouldn't be able to test this cause while we indicate -2000 seconds + // cookie expiration store timestamp. + //$this->assertEquals(-2000, Cookie::$jar['bar']['expiration']); + + $this->assertEquals('path', Cookie::$jar['bar']['path']); + $this->assertEquals('domain', Cookie::$jar['bar']['domain']); + $this->assertFalse(Cookie::$jar['bar']['secure']); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/database.test.php b/laravel/tests/cases/database.test.php new file mode 100644 index 00000000..84b1faaf --- /dev/null +++ b/laravel/tests/cases/database.test.php @@ -0,0 +1,74 @@ +assertTrue(isset(DB::$connections[Config::get('database.default')])); + + $connection = DatabaseConnectStub::connection('mysql'); + $this->assertTrue(isset(DB::$connections['mysql'])); + $this->assertEquals(DB::$connections['mysql']->pdo->laravel_config, Config::get('database.connections.mysql')); + } + + /** + * Test the DB::profile method. + * + * @group laravel + */ + public function testProfileMethodReturnsQueries() + { + Laravel\Database\Connection::$queries = array('Taylor'); + $this->assertEquals(array('Taylor'), DB::profile()); + Laravel\Database\Connection::$queries = array(); + } + + /** + * Test the __callStatic method. + * + * @group laravel + */ + public function testConnectionMethodsCanBeCalledStaticly() + { + $this->assertEquals('sqlite', DB::driver()); + } + +} + +class DatabaseConnectStub extends Laravel\Database { + + protected static function connect($config) { return new PDOStub($config); } + +} + +class PDOStub extends PDO { + + public $laravel_config; + + public function __construct($config) { $this->laravel_config = $config; } + + public function foo() { return 'foo'; } + +} \ No newline at end of file diff --git a/laravel/tests/cases/event.test.php b/laravel/tests/cases/event.test.php new file mode 100644 index 00000000..52063833 --- /dev/null +++ b/laravel/tests/cases/event.test.php @@ -0,0 +1,43 @@ +assertEquals(1, $responses[0]); + $this->assertEquals(2, $responses[1]); + } + + /** + * Test parameters can be passed to event listeners. + * + * @group laravel + */ + public function testParametersCanBePassedToEvents() + { + Event::listen('test.event', function($var) { return $var; }); + + $responses = Event::fire('test.event', array('Taylor')); + + $this->assertEquals('Taylor', $responses[0]); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/fluent.test.php b/laravel/tests/cases/fluent.test.php new file mode 100644 index 00000000..87c0e0db --- /dev/null +++ b/laravel/tests/cases/fluent.test.php @@ -0,0 +1,50 @@ + 'Taylor', 'age' => 25); + + $fluent = new Fluent($array); + + $this->assertEquals($array, $fluent->attributes); + } + + /** + * Test the Fluent::get method. + * + * @group laravel + */ + public function testGetMethodReturnsAttribute() + { + $fluent = new Fluent(array('name' => 'Taylor')); + + $this->assertEquals('Taylor', $fluent->get('name')); + $this->assertEquals('Default', $fluent->get('foo', 'Default')); + $this->assertEquals('Taylor', $fluent->name); + $this->assertNull($fluent->foo); + } + + public function testMagicMethodsCanBeUsedToSetAttributes() + { + $fluent = new Fluent; + + $fluent->name = 'Taylor'; + $fluent->developer(); + $fluent->age(25); + + $this->assertEquals('Taylor', $fluent->name); + $this->assertTrue($fluent->developer); + $this->assertEquals(25, $fluent->age); + $this->assertInstanceOf('Laravel\\Fluent', $fluent->programmer()); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/hash.test.php b/laravel/tests/cases/hash.test.php new file mode 100644 index 00000000..4dca2713 --- /dev/null +++ b/laravel/tests/cases/hash.test.php @@ -0,0 +1,37 @@ +assertTrue(strlen(Hash::make('taylor')) == 60); + } + + /** + * Test the Hash::check method. + * + * @group laravel + */ + public function testHashCheckFailsWhenNotMatching() + { + $hash = Hash::make('taylor'); + + $this->assertFalse(Hash::check('foo', $hash)); + } + + /** + * Test the Hash::check method. + * + * @group laravel + */ + public function testHashCheckPassesWhenMatches() + { + $this->assertTrue(Hash::check('taylor', Hash::make('taylor'))); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/input.test.php b/laravel/tests/cases/input.test.php new file mode 100644 index 00000000..5a1890f0 --- /dev/null +++ b/laravel/tests/cases/input.test.php @@ -0,0 +1,174 @@ +request->add(array('name' => 'Taylor')); + + $_FILES = array('age' => 25); + + $this->assertEquals(Input::all(), array('name' => 'Taylor', 'age' => 25)); + } + + /** + * Test the Input::has method. + * + * @group laravel + */ + public function testHasMethodIndicatesTheExistenceOfInput() + { + $this->assertFalse(Input::has('foo')); + + Request::foundation()->request->add(array('name' => 'Taylor')); + + $this->assertTrue(Input::has('name')); + } + + /** + * Test the Input::get method. + * + * @group laravel + */ + public function testGetMethodReturnsInputValue() + { + Request::foundation()->request->add(array('name' => 'Taylor')); + + $this->assertEquals('Taylor', Input::get('name')); + $this->assertEquals('Default', Input::get('foo', 'Default')); + } + + /** + * Test the Input::only method. + * + * @group laravel + */ + public function testOnlyMethodReturnsSubsetOfInput() + { + Request::foundation()->request->add(array('name' => 'Taylor', 'age' => 25)); + + $this->assertEquals(array('name' => 'Taylor'), Input::only(array('name'))); + } + + /** + * Test the Input::except method. + * + * @group laravel + */ + public function testExceptMethodReturnsSubsetOfInput() + { + Request::foundation()->request->add(array('name' => 'Taylor', 'age' => 25)); + + $this->assertEquals(array('age' => 25), Input::except(array('name'))); + } + + /** + * Test the Input::old method. + * + * @group laravel + */ + public function testOldInputCanBeRetrievedFromSession() + { + $this->setSession(); + + Session::$instance->session['data']['laravel_old_input'] = array('name' => 'Taylor'); + + $this->assertNull(Input::old('foo')); + $this->assertTrue(Input::had('name')); + $this->assertFalse(Input::had('foo')); + $this->assertEquals('Taylor', Input::old('name')); + } + + /** + * Test the Input::file method. + * + * @group laravel + */ + public function testFileMethodReturnsFromFileArray() + { + $_FILES['foo'] = array('name' => 'Taylor', 'size' => 100); + + $this->assertEquals('Taylor', Input::file('foo.name')); + $this->assertEquals(array('name' => 'Taylor', 'size' => 100), Input::file('foo')); + } + + /** + * Test the Input::flash method. + * + * @group laravel + */ + public function testFlashMethodFlashesInputToSession() + { + $this->setSession(); + + $input = array('name' => 'Taylor', 'age' => 25); + Request::foundation()->request->add($input); + + Input::flash(); + + $this->assertEquals($input, Session::$instance->session['data'][':new:']['laravel_old_input']); + + Input::flash('only', array('name')); + + $this->assertEquals(array('name' => 'Taylor'), Session::$instance->session['data'][':new:']['laravel_old_input']); + + Input::flash('except', array('name')); + + $this->assertEquals(array('age' => 25), Session::$instance->session['data'][':new:']['laravel_old_input']); + } + + /** + * Test the Input::flush method. + * + * @group laravel + */ + public function testFlushMethodClearsFlashedInput() + { + $this->setSession(); + + $input = array('name' => 'Taylor', 'age' => 30); + Request::foundation()->request->add($input); + + Input::flash(); + + $this->assertEquals($input, Session::$instance->session['data'][':new:']['laravel_old_input']); + + Input::flush(); + + $this->assertEquals(array(), Session::$instance->session['data'][':new:']['laravel_old_input']); + } + + /** + * Set the session payload instance. + */ + protected function setSession() + { + $driver = $this->getMock('Laravel\\Session\\Drivers\\Driver'); + + Session::$instance = new Laravel\Session\Payload($driver); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/ioc.test.php b/laravel/tests/cases/ioc.test.php new file mode 100644 index 00000000..56918337 --- /dev/null +++ b/laravel/tests/cases/ioc.test.php @@ -0,0 +1,74 @@ +assertEquals('Taylor', IoC::resolve('foo')); + } + + /** + * Test that singletons are created once. + * + * @group laravel + */ + public function testSingletonsAreCreatedOnce() + { + IoC::singleton('foo', function() + { + return new StdClass; + }); + + $object = IoC::resolve('foo'); + + $this->assertTrue($object === IoC::resolve('foo')); + } + + /** + * Test the IoC::instance method. + * + * @group laravel + */ + public function testInstancesAreReturnedBySingleton() + { + $object = new StdClass; + + IoC::instance('bar', $object); + + $this->assertTrue($object === IoC::resolve('bar')); + } + + /** + * Test the IoC::registered method. + */ + public function testRegisteredMethodIndicatesIfRegistered() + { + IoC::register('foo', function() {}); + + $this->assertTrue(IoC::registered('foo')); + $this->assertFalse(IoC::registered('baz')); + } + + /** + * Test the IoC::controller method. + * + * @group laravel + */ + public function testControllerMethodRegistersAController() + { + IoC::register('controller: ioc.test', function() {}); + + $this->assertTrue(IoC::registered('controller: ioc.test')); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/lang.test.php b/laravel/tests/cases/lang.test.php new file mode 100644 index 00000000..74640ccd --- /dev/null +++ b/laravel/tests/cases/lang.test.php @@ -0,0 +1,68 @@ +assertEquals($validation['required'], Lang::line('validation.required')->get()); + $this->assertEquals('Taylor', Lang::line('validation.foo')->get(null, 'Taylor')); + } + + /** + * Test the Lang::line method. + * + * @group laravel + */ + public function testGetMethodCanGetLinesForAGivenLanguage() + { + $validation = require path('app').'language/sp/validation.php'; + + $this->assertEquals($validation['required'], Lang::line('validation.required')->get('sp')); + } + + /** + * Test the __toString method. + * + * @group laravel + */ + public function testLineCanBeCastAsString() + { + $validation = require path('app').'language/en/validation.php'; + + $this->assertEquals($validation['required'], (string) Lang::line('validation.required')); + } + + /** + * Test that string replacements are made on lines. + * + * @group laravel + */ + public function testReplacementsAreMadeOnLines() + { + $validation = require path('app').'language/en/validation.php'; + + $line = str_replace(':attribute', 'e-mail', $validation['required']); + + $this->assertEquals($line, Lang::line('validation.required', array('attribute' => 'e-mail'))->get()); + } + + /** + * Test the Lang::has method. + * + * @group laravel + */ + public function testHasMethodIndicatesIfLangaugeLineExists() + { + $this->assertTrue(Lang::has('validation')); + $this->assertTrue(Lang::has('validation.required')); + $this->assertFalse(Lang::has('validation.foo')); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/messages.test.php b/laravel/tests/cases/messages.test.php new file mode 100644 index 00000000..f007ecb7 --- /dev/null +++ b/laravel/tests/cases/messages.test.php @@ -0,0 +1,115 @@ +messages = new Laravel\Messages; + } + + /** + * Test the Messages::add method. + * + * @group laravel + */ + public function testAddingMessagesDoesNotCreateDuplicateMessages() + { + $this->messages->add('email', 'test'); + $this->messages->add('email', 'test'); + $this->assertCount(1, $this->messages->messages); + } + + /** + * Test the Messages::add method. + * + * @group laravel + */ + public function testAddMethodPutsMessageInMessagesArray() + { + $this->messages->add('email', 'test'); + $this->assertArrayHasKey('email', $this->messages->messages); + $this->assertEquals('test', $this->messages->messages['email'][0]); + } + + /** + * Test the Messages::has method. + * + * @group laravel + */ + public function testHasMethodReturnsTrue() + { + $this->messages->add('email', 'test'); + $this->assertTrue($this->messages->has('email')); + } + + /** + * Test the Messages::has method. + * + * @group laravel + */ + public function testHasMethodReturnsFalse() + { + $this->assertFalse($this->messages->has('something')); + } + + /** + * Test the Messages::first method. + * + * @group laravel + */ + public function testFirstMethodReturnsSingleString() + { + $this->messages->add('email', 'test'); + $this->assertEquals('test', $this->messages->first('email')); + $this->assertEquals('', $this->messages->first('something')); + } + + /** + * Test the Messages::get method. + * + * @group laravel + */ + public function testGetMethodReturnsAllMessagesForAttribute() + { + $messages = array('email' => array('something', 'else')); + $this->messages->messages = $messages; + $this->assertEquals(array('something', 'else'), $this->messages->get('email')); + } + + /** + * Test the Messages::all method. + * + * @group laravel + */ + public function testAllMethodReturnsAllErrorMessages() + { + $messages = array('email' => array('something', 'else'), 'name' => array('foo')); + $this->messages->messages = $messages; + $this->assertEquals(array('something', 'else', 'foo'), $this->messages->all()); + } + + /** + * Test the Messages::get method. + * + * @group laravel + */ + public function testMessagesRespectFormat() + { + $this->messages->add('email', 'test'); + $this->assertEquals('

    test

    ', $this->messages->first('email', '

    :message

    ')); + $this->assertEquals(array('

    test

    '), $this->messages->get('email', '

    :message

    ')); + $this->assertEquals(array('

    test

    '), $this->messages->all('

    :message

    ')); + } + + +} \ No newline at end of file diff --git a/laravel/tests/cases/query.test.php b/laravel/tests/cases/query.test.php new file mode 100644 index 00000000..17279150 --- /dev/null +++ b/laravel/tests/cases/query.test.php @@ -0,0 +1,48 @@ +assertEquals('taylor@example.com', $this->query()->find(1)->email); + } + + /** + * Test the select method. + * + * @group laravel + */ + public function testSelectMethodLimitsColumns() + { + $result = $this->query()->select(array('email'))->first(); + + $this->assertTrue(isset($result->email)); + $this->assertFalse(isset($result->name)); + } + + /** + * Test the raw_where method. + * + * @group laravel + */ + public function testRawWhereCanBeUsed() + { + + } + + /** + * Get the query instance for the test case. + * + * @return Query + */ + protected function query() + { + return DB::table('query_test'); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/redirect.test.php b/laravel/tests/cases/redirect.test.php new file mode 100644 index 00000000..cce63a81 --- /dev/null +++ b/laravel/tests/cases/redirect.test.php @@ -0,0 +1,143 @@ +assertEquals(302, $redirect->status()); + $this->assertEquals('http://localhost/user/profile', $redirect->headers()->get('location')); + + $redirect = Redirect::to('user/profile', 301, true); + + $this->assertEquals(301, $redirect->status()); + $this->assertEquals('https://localhost/user/profile', $redirect->headers()->get('location')); + + $redirect = Redirect::to_secure('user/profile', 301); + + $this->assertEquals(301, $redirect->status()); + $this->assertEquals('https://localhost/user/profile', $redirect->headers()->get('location')); + } + + /** + * Test the Redirect::to_route method. + * + * @group laravel + */ + public function testRedirectsCanBeGeneratedForNamedRoutes() + { + Route::get('redirect', array('as' => 'redirect')); + Route::get('redirect/(:any)/(:any)', array('as' => 'redirect-2')); + Route::get('secure/redirect', array('https' => true, 'as' => 'redirect-3')); + + $this->assertEquals(301, Redirect::to_route('redirect', array(), 301, true)->status()); + $this->assertEquals('http://localhost/redirect', Redirect::to_route('redirect')->headers()->get('location')); + $this->assertEquals('https://localhost/secure/redirect', Redirect::to_route('redirect-3', array(), 302)->headers()->get('location')); + $this->assertEquals('http://localhost/redirect/1/2', Redirect::to_route('redirect-2', array('1', '2'))->headers()->get('location')); + } + + /** + * Test the Redirect::with method. + * + * @group laravel + */ + public function testWithMethodFlashesItemToSession() + { + $this->setSession(); + + $redirect = Redirect::to('')->with('name', 'Taylor'); + + $this->assertEquals('Taylor', Session::$instance->session['data'][':new:']['name']); + } + + /** + * Test the Redirect::with_input function. + * + * @group laravel + */ + public function testWithInputMethodFlashesInputToTheSession() + { + $this->setSession(); + + $input = array('name' => 'Taylor', 'age' => 25); + Request::foundation()->request->add($input); + + $redirect = Redirect::to('')->with_input(); + + $this->assertEquals($input, Session::$instance->session['data'][':new:']['laravel_old_input']); + + $redirect = Redirect::to('')->with_input('only', array('name')); + + $this->assertEquals(array('name' => 'Taylor'), Session::$instance->session['data'][':new:']['laravel_old_input']); + + $redirect = Redirect::to('')->with_input('except', array('name')); + + $this->assertEquals(array('age' => 25), Session::$instance->session['data'][':new:']['laravel_old_input']); + } + + /** + * Test the Redirect::with_errors method. + * + * @group laravel + */ + public function testWithErrorsFlashesErrorsToTheSession() + { + $this->setSession(); + + Redirect::to('')->with_errors(array('name' => 'Taylor')); + + $this->assertEquals(array('name' => 'Taylor'), Session::$instance->session['data'][':new:']['errors']); + + $validator = Validator::make(array(), array()); + $validator->errors = array('name' => 'Taylor'); + + Redirect::to('')->with_errors($validator); + + $this->assertEquals(array('name' => 'Taylor'), Session::$instance->session['data'][':new:']['errors']); + } + + /** + * Set the session payload instance. + */ + protected function setSession() + { + $driver = $this->getMock('Laravel\\Session\\Drivers\\Driver'); + + Session::$instance = new Laravel\Session\Payload($driver); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/request.test.php b/laravel/tests/cases/request.test.php new file mode 100644 index 00000000..4641a532 --- /dev/null +++ b/laravel/tests/cases/request.test.php @@ -0,0 +1,177 @@ +restartRequest(); + } + + /** + * Set one of the $_POST variables. + * + * @param string $key + * @param string $value + */ + protected function setPostVar($key, $value) + { + $_POST[$key] = $value; + + $this->restartRequest(); + } + + /** + * Reinitialize the global request. + * + * @return void + */ + protected function restartRequest() + { + // FIXME: Ugly hack, but old contents from previous requests seem to + // trip up the Foundation class. + $_FILES = array(); + + Request::$foundation = RequestFoundation::createFromGlobals(); + } + + /** + * Test the Request::method method. + * + * @group laravel + */ + public function testMethodReturnsTheHTTPRequestMethod() + { + $this->setServerVar('REQUEST_METHOD', 'POST'); + + $this->assertEquals('POST', Request::method()); + + $this->setPostVar(Request::spoofer, 'PUT'); + + $this->assertEquals('PUT', Request::method()); + } + + /** + * Test the Request::server method. + * + * @group laravel + */ + public function testServerMethodReturnsFromServerArray() + { + $this->setServerVar('TEST', 'something'); + $this->setServerVar('USER', array('NAME' => 'taylor')); + + $this->assertEquals('something', Request::server('test')); + $this->assertEquals('taylor', Request::server('user.name')); + } + + /** + * Test the Request::ip method. + * + * @group laravel + */ + public function testIPMethodReturnsClientIPAddress() + { + $this->setServerVar('REMOTE_ADDR', 'something'); + $this->assertEquals('something', Request::ip()); + + $this->setServerVar('HTTP_CLIENT_IP', 'something'); + $this->assertEquals('something', Request::ip()); + + $this->setServerVar('HTTP_CLIENT_IP', 'something'); + $this->assertEquals('something', Request::ip()); + + $_SERVER = array(); + $this->restartRequest(); + $this->assertEquals('0.0.0.0', Request::ip()); + } + + /** + * Test the Request::secure method. + * + * @group laravel + */ + public function testSecureMethodsIndicatesIfHTTPS() + { + $this->setServerVar('HTTPS', 'on'); + + $this->assertTrue(Request::secure()); + + $this->setServerVar('HTTPS', 'off'); + + $this->assertFalse(Request::secure()); + } + + /** + * Test the Request::ajax method. + * + * @group laravel + */ + public function testAjaxMethodIndicatesWhenAjax() + { + $this->assertFalse(Request::ajax()); + + $this->setServerVar('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'); + + $this->assertTrue(Request::ajax()); + } + + /** + * Test the Request::forged method. + * + * @group laravel + */ + public function testForgedMethodIndicatesIfRequestWasForged() + { + Session::$instance = new SessionPayloadTokenStub; + + $input = array(Session::csrf_token => 'Foo'); + Request::foundation()->request->add($input); + + $this->assertTrue(Request::forged()); + + $input = array(Session::csrf_token => 'Taylor'); + Request::foundation()->request->add($input); + + $this->assertFalse(Request::forged()); + } + + /** + * Test the Request::route method. + * + * @group laravel + */ + public function testRouteMethodReturnsStaticRoute() + { + Request::$route = 'Taylor'; + + $this->assertEquals('Taylor', Request::route()); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/response.test.php b/laravel/tests/cases/response.test.php new file mode 100644 index 00000000..11e48e74 --- /dev/null +++ b/laravel/tests/cases/response.test.php @@ -0,0 +1,89 @@ + 'baz')); + + $this->assertEquals('foo', $response->content); + $this->assertEquals(201, $response->status()); + $this->assertArrayHasKey('bar', $response->headers()->all()); + $this->assertEquals('baz', $response->headers()->get('bar')); + } + + /** + * Test the Response::view method. + * + * @group laravel + */ + public function testViewMethodSetsContentToView() + { + $response = Response::view('home.index', array('name' => 'Taylor')); + + $this->assertEquals('home.index', $response->content->view); + $this->assertEquals('Taylor', $response->content->data['name']); + } + + /** + * Test the Response::error method. + * + * @group laravel + */ + public function testErrorMethodSetsContentToErrorView() + { + $response = Response::error('404', array('name' => 'Taylor')); + + $this->assertEquals(404, $response->status()); + $this->assertEquals('error.404', $response->content->view); + $this->assertEquals('Taylor', $response->content->data['name']); + } + + /** + * Test the Response::prepare method. + * + * @group laravel + */ + public function testPrepareMethodCreatesAResponseInstanceFromGivenValue() + { + $response = Response::prepare('Taylor'); + + $this->assertInstanceOf('Laravel\\Response', $response); + $this->assertEquals('Taylor', $response->content); + + $response = Response::prepare(new Response('Taylor')); + + $this->assertInstanceOf('Laravel\\Response', $response); + $this->assertEquals('Taylor', $response->content); + } + + /** + * Test the Response::header method. + * + * @group laravel + */ + public function testHeaderMethodSetsValueInHeaderArray() + { + $response = Response::make('')->header('foo', 'bar'); + + $this->assertEquals('bar', $response->headers()->get('foo')); + } + + /** + * Test the Response::status method. + * + * @group laravel + */ + public function testStatusMethodSetsStatusCode() + { + $response = Response::make('')->status(404); + + $this->assertEquals(404, $response->status()); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/route.test.php b/laravel/tests/cases/route.test.php new file mode 100644 index 00000000..48919135 --- /dev/null +++ b/laravel/tests/cases/route.test.php @@ -0,0 +1,179 @@ + 'profile')); + $this->assertTrue($route->is('profile')); + $this->assertFalse($route->is('something')); + } + + /** + * Test the basic execution of a route. + * + * @group laravel + */ + public function testBasicRoutesCanBeExecutedProperly() + { + $route = new Route('GET', '', array(function() { return 'Route!'; })); + + $this->assertEquals('Route!', $route->call()->content); + $this->assertInstanceOf('Laravel\\Response', $route->call()); + } + + /** + * Test that route parameters are passed into the handlers. + * + * @group laravel + */ + public function testRouteParametersArePassedIntoTheHandler() + { + $route = new Route('GET', '', array(function($var) { return $var; }), array('Taylor')); + + $this->assertEquals('Taylor', $route->call()->content); + $this->assertInstanceOf('Laravel\\Response', $route->call()); + } + + /** + * Test that calling a route calls the global before and after filters. + * + * @group laravel + */ + public function testCallingARouteCallsTheBeforeAndAfterFilters() + { + $route = new Route('GET', '', array(function() { return 'Hi!'; })); + + $_SERVER['before'] = false; + $_SERVER['after'] = false; + + $route->call(); + + $this->assertTrue($_SERVER['before']); + $this->assertTrue($_SERVER['after']); + } + + /** + * Test that before filters override the route response. + * + * @group laravel + */ + public function testBeforeFiltersOverrideTheRouteResponse() + { + Filter::register('test-before', function() + { + return 'Filtered!'; + }); + + $route = new Route('GET', '', array('before' => 'test-before', function() { + return 'Route!'; + })); + + $this->assertEquals('Filtered!', $route->call()->content); + } + + /** + * Test that after filters do not affect the route response. + * + * @group laravel + */ + public function testAfterFilterDoesNotAffectTheResponse() + { + $_SERVER['test-after'] = false; + + Filter::register('test-after', function() + { + $_SERVER['test-after'] = true; + return 'Filtered!'; + }); + + $route = new Route('GET', '', array('after' => 'test-after', function() + { + return 'Route!'; + })); + + $this->assertEquals('Route!', $route->call()->content); + $this->assertTrue($_SERVER['test-after']); + } + + /** + * Test that the route calls the appropriate controller method when delegating. + * + * @group laravel + */ + public function testControllerActionCalledWhenDelegating() + { + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $route = new Route('GET', '', array('uses' => 'auth@index')); + + $this->assertEquals('action_index', $route->call()->content); + } + + /** + * Test that filter parameters are passed to the filter. + * + * @group laravel + */ + public function testFilterParametersArePassedToFilter() + { + Filter::register('test-params', function($var1, $var2) + { + return $var1.$var2; + }); + + $route = new Route('GET', '', array('before' => 'test-params:1,2')); + + $this->assertEquals('12', $route->call()->content); + } + + /** + * Test that multiple filters can be assigned to a route. + * + * @group laravel + */ + public function testMultipleFiltersCanBeAssignedToARoute() + { + $_SERVER['test-multi-1'] = false; + $_SERVER['test-multi-2'] = false; + + Filter::register('test-multi-1', function() { $_SERVER['test-multi-1'] = true; }); + Filter::register('test-multi-2', function() { $_SERVER['test-multi-2'] = true; }); + + $route = new Route('GET', '', array('before' => 'test-multi-1|test-multi-2')); + + $route->call(); + + $this->assertTrue($_SERVER['test-multi-1']); + $this->assertTrue($_SERVER['test-multi-2']); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/routing.test.php b/laravel/tests/cases/routing.test.php new file mode 100644 index 00000000..68a112a0 --- /dev/null +++ b/laravel/tests/cases/routing.test.php @@ -0,0 +1,160 @@ + 'home')); + Route::get('dashboard', array('as' => 'dashboard')); + + $home = Router::find('home'); + $dashboard = Router::find('dashboard'); + + $this->assertTrue(isset($home['/'])); + $this->assertTrue(isset($dashboard['dashboard'])); + } + + /** + * Test the basic routing mechanism. + * + * @group laravel + */ + public function testBasicRouteCanBeRouted() + { + Route::get('/', function() {}); + Route::get('home, main', function() {}); + + $this->assertEquals('/', Router::route('GET', '/')->uri); + $this->assertEquals('home', Router::route('GET', 'home')->uri); + $this->assertEquals('main', Router::route('GET', 'main')->uri); + } + + /** + * Test that the router can handle basic wildcards. + * + * @group laravel + */ + public function testWildcardRoutesCanBeRouted() + { + Route::get('user/(:num)', function() {}); + Route::get('profile/(:any)/(:num)', function() {}); + + $this->assertNull(Router::route('GET', 'user/1.5')); + $this->assertNull(Router::route('GET', 'user/taylor')); + $this->assertEquals(array(25), Router::route('GET', 'user/25')->parameters); + $this->assertEquals('user/(:num)', Router::route('GET', 'user/1')->uri); + + $this->assertNull(Router::route('GET', 'profile/1/otwell')); + $this->assertNull(Router::route('POST', 'profile/taylor/1')); + $this->assertNull(Router::route('GET', 'profile/taylor/otwell')); + $this->assertNull(Router::route('GET', 'profile/taylor/1/otwell')); + $this->assertEquals(array('taylor', 25), Router::route('GET', 'profile/taylor/25')->parameters); + $this->assertEquals('profile/(:any)/(:num)', Router::route('GET', 'profile/taylor/1')->uri); + } + + /** + * Test that optional wildcards can be routed. + * + * @group laravel + */ + public function testOptionalWildcardsCanBeRouted() + { + Route::get('user/(:num?)', function() {}); + Route::get('profile/(:any)/(:any?)', function() {}); + + $this->assertNull(Router::route('GET', 'user/taylor')); + $this->assertEquals('user/(:num?)', Router::route('GET', 'user')->uri); + $this->assertEquals(array(25), Router::route('GET', 'user/25')->parameters); + $this->assertEquals('user/(:num?)', Router::route('GET', 'user/1')->uri); + + $this->assertNull(Router::route('GET', 'profile/taylor/otwell/test')); + $this->assertEquals('profile/(:any)/(:any?)', Router::route('GET', 'profile/taylor')->uri); + $this->assertEquals('profile/(:any)/(:any?)', Router::route('GET', 'profile/taylor/25')->uri); + $this->assertEquals('profile/(:any)/(:any?)', Router::route('GET', 'profile/taylor/otwell')->uri); + $this->assertEquals(array('taylor', 'otwell'), Router::route('GET', 'profile/taylor/otwell')->parameters); + } + + /** + * Test that basic controller routing is working. + * + * @group laravel + */ + public function testBasicRouteToControllerIsRouted() + { + $this->assertEquals('auth@(:1)', Router::route('GET', 'auth')->action['uses']); + $this->assertEquals('home@(:1)', Router::route('GET', 'home/index')->action['uses']); + $this->assertEquals('home@(:1)', Router::route('GET', 'home/profile')->action['uses']); + $this->assertEquals('admin.panel@(:1)', Router::route('GET', 'admin/panel')->action['uses']); + $this->assertEquals('admin.panel@(:1)', Router::route('GET', 'admin/panel/show')->action['uses']); + } + + /** + * Test basic bundle route resolution. + * + * @group laravel + */ + public function testRoutesToBundlesCanBeResolved() + { + $this->assertNull(Router::route('GET', 'dashboard/foo')); + $this->assertEquals('dashboard', Router::route('GET', 'dashboard')->uri); + } + + /** + * Test bundle controller route resolution. + * + * @group laravel + */ + public function testBundleControllersCanBeResolved() + { + $this->assertEquals('dashboard::panel@(:1)', Router::route('GET', 'dashboard/panel')->action['uses']); + $this->assertEquals('dashboard::panel@(:1)', Router::route('GET', 'dashboard/panel/show')->action['uses']); + } + + /** + * Test foreign characters can be used in routes. + * + * @group laravel + */ + public function testForeignCharsInRoutes() + { + Route::get(urlencode('مدرس_رياضيات').'/(:any)', function() {}); + Route::get(urlencode('مدرس_رياضيات'), function() {}); + Route::get(urlencode('ÇœŪ'), function() {}); + Route::get(urlencode('私は料理が大好き'), function() {}); + + $this->assertEquals(array(urlencode('مدرس_رياضيات')), Router::route('GET', urlencode('مدرس_رياضيات').'/'.urlencode('مدرس_رياضيات'))->parameters); + $this->assertEquals(urlencode('مدرس_رياضيات'), Router::route('GET', urlencode('مدرس_رياضيات'))->uri); + $this->assertEquals(urlencode('ÇœŪ'), Router::route('GET', urlencode('ÇœŪ'))->uri); + $this->assertEquals(urlencode('私は料理が大好き'), Router::route('GET', urlencode('私は料理が大好き'))->uri); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/session.test.php b/laravel/tests/cases/session.test.php new file mode 100644 index 00000000..cf6946a7 --- /dev/null +++ b/laravel/tests/cases/session.test.php @@ -0,0 +1,443 @@ +assertEquals('Foo', Session::test()); + } + + /** + * Test the Session::started method. + * + * @group laravel + */ + public function testStartedMethodIndicatesIfSessionIsStarted() + { + $this->assertFalse(Session::started()); + Session::$instance = 'foo'; + $this->assertTrue(Session::started()); + } + + /** + * Test the Payload::load method. + * + * @group laravel + */ + public function testLoadMethodCreatesNewSessionWithNullIDGiven() + { + $payload = $this->getPayload(); + $payload->load(null); + $this->verifyNewSession($payload); + } + + /** + * Test the Payload::load method. + * + * @group laravel + */ + public function testLoadMethodCreatesNewSessionWhenSessionIsExpired() + { + $payload = $this->getPayload(); + + $session = $this->getSession(); + $session['last_activity'] = time() - 10000; + + $payload->driver->expects($this->any()) + ->method('load') + ->will($this->returnValue($session)); + + $payload->load('foo'); + + $this->verifyNewSession($payload); + $this->assertTrue($payload->session['id'] !== $session['id']); + } + + /** + * Assert that a session is new. + * + * @param Payload $payload + * @return void + */ + protected function verifyNewSession($payload) + { + $this->assertFalse($payload->exists); + $this->assertTrue(isset($payload->session['id'])); + $this->assertEquals(array(), $payload->session['data'][':new:']); + $this->assertEquals(array(), $payload->session['data'][':old:']); + $this->assertTrue(isset($payload->session['data'][Session::csrf_token])); + } + + /** + * Test the Payload::load method. + * + * @group laravel + */ + public function testLoadMethodSetsValidSession() + { + $payload = $this->getPayload(); + + $session = $this->getSession(); + + $payload->driver->expects($this->any()) + ->method('load') + ->will($this->returnValue($session)); + + $payload->load('foo'); + + $this->assertEquals($session, $payload->session); + } + + /** + * Test the Payload::load method. + * + * @group laravel + */ + public function testLoadMethodSetsCSRFTokenIfDoesntExist() + { + $payload = $this->getPayload(); + + $session = $this->getSession(); + + unset($session['data']['csrf_token']); + + $payload->driver->expects($this->any()) + ->method('load') + ->will($this->returnValue($session)); + + $payload->load('foo'); + + $this->assertEquals('foo', $payload->session['id']); + $this->assertTrue(isset($payload->session['data']['csrf_token'])); + } + + /** + * Test the various data retrieval methods. + * + * @group laravel + */ + public function testSessionDataCanBeRetrievedProperly() + { + $payload = $this->getPayload(); + + $payload->session = $this->getSession(); + + $this->assertTrue($payload->has('name')); + $this->assertEquals('Taylor', $payload->get('name')); + $this->assertFalse($payload->has('foo')); + $this->assertEquals('Default', $payload->get('foo', 'Default')); + $this->assertTrue($payload->has('votes')); + $this->assertEquals(10, $payload->get('votes')); + $this->assertTrue($payload->has('state')); + $this->assertEquals('AR', $payload->get('state')); + } + + /** + * Test the various data manipulation methods. + * + * @group laravel + */ + public function testDataCanBeSetProperly() + { + $payload = $this->getPayload(); + + $payload->session = $this->getSession(); + + // Test the "put" and "flash" methods. + $payload->put('name', 'Weldon'); + $this->assertEquals('Weldon', $payload->session['data']['name']); + $payload->flash('language', 'php'); + $this->assertEquals('php', $payload->session['data'][':new:']['language']); + + // Test the "reflash" method. + $payload->session['data'][':new:'] = array('name' => 'Taylor'); + $payload->session['data'][':old:'] = array('age' => 25); + $payload->reflash(); + $this->assertEquals(array('name' => 'Taylor', 'age' => 25), $payload->session['data'][':new:']); + + // Test the "keep" method. + $payload->session['data'][':new:'] = array(); + $payload->keep(array('age')); + $this->assertEquals(25, $payload->session['data'][':new:']['age']); + } + + /** + * Test the Payload::forget method. + * + * @group laravel + */ + public function testSessionDataCanBeForgotten() + { + $payload = $this->getPayload(); + + $payload->session = $this->getSession(); + + $this->assertTrue(isset($payload->session['data']['name'])); + $payload->forget('name'); + $this->assertFalse(isset($payload->session['data']['name'])); + } + + /** + * Test the Payload::flush method. + * + * @group laravel + */ + public function testFlushMaintainsTokenButDeletesEverythingElse() + { + $payload = $this->getPayload(); + + $payload->session = $this->getSession(); + + $this->assertTrue(isset($payload->session['data']['name'])); + $payload->flush(); + $this->assertFalse(isset($payload->session['data']['name'])); + $this->assertEquals('bar', $payload->session['data']['csrf_token']); + $this->assertEquals(array(), $payload->session['data'][':new:']); + $this->assertEquals(array(), $payload->session['data'][':old:']); + } + + /** + * Test the Payload::regenerate method. + * + * @group laravel + */ + public function testRegenerateMethodSetsNewIDAndTurnsOffExistenceIndicator() + { + $payload = $this->getPayload(); + + $payload->sesion = $this->getSession(); + $payload->exists = true; + $payload->regenerate(); + + $this->assertFalse($payload->exists); + $this->assertTrue(strlen($payload->session['id']) == 40); + } + + /** + * Test the Payload::token method. + * + * @group laravel + */ + public function testTokenMethodReturnsCSRFToken() + { + $payload = $this->getPayload(); + $payload->session = $this->getSession(); + + $this->assertEquals('bar', $payload->token()); + } + + /** + * Test the Payload::save method. + * + * @group laravel + */ + public function testSaveMethodCorrectlyCallsDriver() + { + $payload = $this->getPayload(); + $session = $this->getSession(); + $payload->session = $session; + $payload->exists = true; + $config = Laravel\Config::get('session'); + + $expect = $session; + $expect['data'][':old:'] = $session['data'][':new:']; + $expect['data'][':new:'] = array(); + + $payload->driver->expects($this->once()) + ->method('save') + ->with($this->equalTo($expect), $this->equalTo($config), $this->equalTo(true)); + + $payload->save(); + + $this->assertEquals($session['data'][':new:'], $payload->session['data'][':old:']); + } + + /** + * Test the Payload::save method. + * + * @group laravel + */ + public function testSaveMethodSweepsIfSweeperAndOddsHitWithTimeGreaterThanThreshold() + { + Config::set('session.sweepage', array(100, 100)); + + $payload = $this->getPayload(); + $payload->driver = $this->getMock('Laravel\\Session\\Drivers\\File', array('save', 'sweep'), array(null)); + $payload->session = $this->getSession(); + + $expiration = time() - (Config::get('session.lifetime') * 60); + + // Here we set the time to the expected expiration minus 5 seconds, just to + // allow plenty of room for PHP execution. In the next test, we'll do the + // same thing except add 5 seconds to check that the time is between a + // given window. + $payload->driver->expects($this->once()) + ->method('sweep') + ->with($this->greaterThan($expiration - 5)); + + $payload->save(); + + Config::set('session.sweepage', array(2, 100)); + } + + /** + * Test the Payload::save method. + * + * @group laravel + */ + public function testSaveMethodSweepsIfSweeperAndOddsHitWithTimeLessThanThreshold() + { + Config::set('session.sweepage', array(100, 100)); + + $payload = $this->getPayload(); + $payload->driver = $this->getMock('Laravel\\Session\\Drivers\\File', array('save', 'sweep'), array(null)); + $payload->session = $this->getSession(); + + $expiration = time() - (Config::get('session.lifetime') * 60); + + $payload->driver->expects($this->once()) + ->method('sweep') + ->with($this->lessThan($expiration + 5)); + + $payload->save(); + + Config::set('session.sweepage', array(2, 100)); + } + + /** + * Test that the session sweeper is never called if not a sweeper. + * + * @group laravel + */ + public function testSweeperShouldntBeCalledIfDriverIsntSweeper() + { + Config::set('session.sweepage', array(100, 100)); + + $payload = $this->getPayload(); + $payload->driver = $this->getMock('Laravel\\Session\\Drivers\\APC', array('save', 'sweep'), array(), '', false); + $payload->session = $this->getSession(); + + $payload->driver->expects($this->never())->method('sweep'); + + $payload->save(); + + Config::set('session.sweepage', array(2, 100)); + } + + /** + * Test the Payload::save method. + * + * @group laravel + */ + public function testSaveMethodSetsCookieWithCorrectValues() + { + $payload = $this->getPayload(); + $payload->session = $this->getSession(); + $payload->save(); + + $this->assertTrue(isset(Cookie::$jar[Config::get('session.cookie')])); + + $cookie = Cookie::$jar[Config::get('session.cookie')]; + + $this->assertEquals('foo', $cookie['value']); + // Shouldn't be able to test this cause session.lifetime store number of minutes + // while cookie expiration store timestamp when it going to expired. + // $this->assertEquals(Config::get('session.lifetime'), $cookie['expiration']); + $this->assertEquals(Config::get('session.domain'), $cookie['domain']); + $this->assertEquals(Config::get('session.path'), $cookie['path']); + $this->assertEquals(Config::get('session.secure'), $cookie['secure']); + } + + /** + * Test the Session::activity method. + * + * @group laravel + */ + public function testActivityMethodReturnsLastActivity() + { + $payload = $this->getPayload(); + $payload->session['last_activity'] = 10; + $this->assertEquals(10, $payload->activity()); + } + + /** + * Get a session payload instance. + * + * @return Payload + */ + protected function getPayload() + { + return new Payload($this->getMockDriver()); + } + + /** + * Get a mock driver instance. + * + * @return Driver + */ + protected function getMockDriver() + { + $mock = $this->getMock('Laravel\\Session\\Drivers\\Driver', array('id', 'load', 'save', 'delete')); + + $mock->expects($this->any())->method('id')->will($this->returnValue(Str::random(40))); + + return $mock; + } + + /** + * Get a dummy session. + * + * @return array + */ + protected function getSession() + { + return array( + 'id' => 'foo', + 'last_activity' => time(), + 'data' => array( + 'name' => 'Taylor', + 'age' => 25, + 'csrf_token' => 'bar', + ':new:' => array( + 'votes' => 10, + ), + ':old:' => array( + 'state' => 'AR', + ), + )); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/str.test.php b/laravel/tests/cases/str.test.php new file mode 100644 index 00000000..7c380600 --- /dev/null +++ b/laravel/tests/cases/str.test.php @@ -0,0 +1,135 @@ +assertEquals('UTF-8', Config::get('application.encoding')); + Config::set('application.encoding', 'foo'); + $this->assertEquals('foo', Config::get('application.encoding')); + Config::set('application.encoding', 'UTF-8'); + } + + /** + * Test the Str::length method. + * + * @group laravel + */ + public function testStringLengthIsCorrect() + { + $this->assertEquals(6, Str::length('Taylor')); + $this->assertEquals(5, Str::length('ラドクリフ')); + } + + /** + * Test the Str::lower method. + * + * @group laravel + */ + public function testStringCanBeConvertedToLowercase() + { + $this->assertEquals('taylor', Str::lower('TAYLOR')); + $this->assertEquals('άχιστη', Str::lower('ΆΧΙΣΤΗ')); + } + + /** + * Test the Str::upper method. + * + * @group laravel + */ + public function testStringCanBeConvertedToUppercase() + { + $this->assertEquals('TAYLOR', Str::upper('taylor')); + $this->assertEquals('ΆΧΙΣΤΗ', Str::upper('άχιστη')); + } + + /** + * Test the Str::title method. + * + * @group laravel + */ + public function testStringCanBeConvertedToTitleCase() + { + $this->assertEquals('Taylor', Str::title('taylor')); + $this->assertEquals('Άχιστη', Str::title('άχιστη')); + } + + /** + * Test the Str::limit method. + * + * @group laravel + */ + public function testStringCanBeLimitedByCharacters() + { + $this->assertEquals('Tay...', Str::limit('Taylor', 3)); + $this->assertEquals('Taylor', Str::limit('Taylor', 6)); + $this->assertEquals('Tay___', Str::limit('Taylor', 3, '___')); + } + + /** + * Test the Str::words method. + * + * @group laravel + */ + public function testStringCanBeLimitedByWords() + { + $this->assertEquals('Taylor...', Str::words('Taylor Otwell', 1)); + $this->assertEquals('Taylor___', Str::words('Taylor Otwell', 1, '___')); + $this->assertEquals('Taylor Otwell', Str::words('Taylor Otwell', 3)); + } + + /** + * Test the Str::plural and Str::singular methods. + * + * @group laravel + */ + public function testStringsCanBeSingularOrPlural() + { + $this->assertEquals('user', Str::singular('users')); + $this->assertEquals('users', Str::plural('user')); + $this->assertEquals('User', Str::singular('Users')); + $this->assertEquals('Users', Str::plural('User')); + $this->assertEquals('user', Str::plural('user', 1)); + $this->assertEquals('users', Str::plural('user', 2)); + $this->assertEquals('chassis', Str::plural('chassis', 2)); + $this->assertEquals('traffic', Str::plural('traffic', 2)); + } + + /** + * Test the Str::slug method. + * + * @group laravel + */ + public function testStringsCanBeSlugged() + { + $this->assertEquals('my-new-post', Str::slug('My nEw post!!!')); + $this->assertEquals('my_new_post', Str::slug('My nEw post!!!', '_')); + } + + /** + * Test the Str::classify method. + * + * @group laravel + */ + public function testStringsCanBeClassified() + { + $this->assertEquals('Something_Else', Str::classify('something.else')); + $this->assertEquals('Something_Else', Str::classify('something_else')); + } + + /** + * Test the Str::random method. + * + * @group laravel + */ + public function testRandomStringsCanBeGenerated() + { + $this->assertEquals(40, strlen(Str::random(40))); + } + +} diff --git a/laravel/tests/cases/uri.test.php b/laravel/tests/cases/uri.test.php new file mode 100644 index 00000000..8f2b85ff --- /dev/null +++ b/laravel/tests/cases/uri.test.php @@ -0,0 +1,75 @@ +setRequestUri($uri); + + $this->assertEquals($expectation, URI::current()); + } + + /** + * Test the URI::segment method. + * + * @group laravel + */ + public function testSegmentMethodReturnsAURISegment() + { + $this->setRequestUri('/user/profile'); + + $this->assertEquals('user', URI::segment(1)); + $this->assertEquals('profile', URI::segment(2)); + } + + /** + * Data provider for the URI::current test. + */ + public function requestUriProvider() + { + return array( + array('/user', 'user'), + array('/user/', 'user'), + array('', '/'), + array('/', '/'), + array('//', '/'), + array('/user', 'user'), + array('/user/', 'user'), + array('/user/profile', 'user/profile'), + ); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/url.test.php b/laravel/tests/cases/url.test.php new file mode 100644 index 00000000..603265ab --- /dev/null +++ b/laravel/tests/cases/url.test.php @@ -0,0 +1,130 @@ +assertEquals('http://localhost/index.php/user/profile', URL::to('user/profile')); + $this->assertEquals('https://localhost/index.php/user/profile', URL::to('user/profile', true)); + + Config::set('application.index', ''); + + $this->assertEquals('http://localhost/user/profile', URL::to('user/profile')); + $this->assertEquals('https://localhost/user/profile', URL::to('user/profile', true)); + + Config::set('application.ssl', false); + + $this->assertEquals('http://localhost/user/profile', URL::to('user/profile', true)); + } + + /** + * Test the URL::to_action method. + * + * @group laravel + */ + public function testToActionMethodGeneratesURLToControllerAction() + { + Route::get('foo/bar/(:any?)', 'foo@baz'); + $this->assertEquals('http://localhost/index.php/x/y', URL::to_action('x@y')); + $this->assertEquals('http://localhost/index.php/x/y/Taylor', URL::to_action('x@y', array('Taylor'))); + $this->assertEquals('http://localhost/index.php/foo/bar', URL::to_action('foo@baz')); + $this->assertEquals('http://localhost/index.php/foo/bar/Taylor', URL::to_action('foo@baz', array('Taylor'))); + } + + /** + * Test the URL::to_asset method. + * + * @group laravel + */ + public function testToAssetGeneratesURLWithoutFrontControllerInURL() + { + $this->assertEquals('http://localhost/image.jpg', URL::to_asset('image.jpg')); + $this->assertEquals('https://localhost/image.jpg', URL::to_asset('image.jpg', true)); + + Config::set('application.index', ''); + + $this->assertEquals('http://localhost/image.jpg', URL::to_asset('image.jpg')); + $this->assertEquals('https://localhost/image.jpg', URL::to_asset('image.jpg', true)); + + Request::foundation()->server->add(array('HTTPS' => 'on')); + + $this->assertEquals('https://localhost/image.jpg', URL::to_asset('image.jpg')); + + Request::foundation()->server->add(array('HTTPS' => 'off')); + } + + /** + * Test the URL::to_route method. + * + * @group laravel + */ + public function testToRouteMethodGeneratesURLsToRoutes() + { + Route::get('url/test', array('as' => 'url-test')); + Route::get('url/test/(:any)/(:any?)', array('as' => 'url-test-2')); + Route::get('url/secure/(:any)/(:any?)', array('as' => 'url-test-3', 'https' => true)); + + $this->assertEquals('http://localhost/index.php/url/test', URL::to_route('url-test')); + $this->assertEquals('http://localhost/index.php/url/test/taylor', URL::to_route('url-test-2', array('taylor'))); + $this->assertEquals('https://localhost/index.php/url/secure/taylor', URL::to_route('url-test-3', array('taylor'))); + $this->assertEquals('http://localhost/index.php/url/test/taylor/otwell', URL::to_route('url-test-2', array('taylor', 'otwell'))); + } + + + /** + * Test language based URL generation. + * + * @group laravel + */ + public function testUrlsGeneratedWithLanguages() + { + Config::set('application.languages', array('sp', 'fr')); + Config::set('application.language', 'sp'); + $this->assertEquals('http://localhost/index.php/sp/foo', URL::to('foo')); + $this->assertEquals('http://localhost/foo.jpg', URL::to_asset('foo.jpg')); + + Config::set('application.index', ''); + $this->assertEquals('http://localhost/sp/foo', URL::to('foo')); + + Config::set('application.index', 'index.php'); + Config::set('application.language', 'en'); + $this->assertEquals('http://localhost/index.php/foo', URL::to('foo')); + Config::set('application.languages', array()); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/validator.test.php b/laravel/tests/cases/validator.test.php new file mode 100644 index 00000000..bde1cea1 --- /dev/null +++ b/laravel/tests/cases/validator.test.php @@ -0,0 +1,669 @@ + 'Taylor Otwell'); + $rules = array('name' => 'required'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['name'] = ''; + $this->assertFalse(Validator::make($input, $rules)->valid()); + + unset($input['name']); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + $_FILES['name']['tmp_name'] = 'foo'; + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $_FILES['name']['tmp_name'] = ''; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the confirmed validation rule. + * + * @group laravel + */ + public function testTheConfirmedRule() + { + $input = array('password' => 'foo', 'password_confirmation' => 'foo'); + $rules = array('password' => 'confirmed'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['password_confirmation'] = 'foo_bar'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + + unset($input['password_confirmation']); + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the different validation rule. + * + * @group laravel + */ + public function testTheDifferentRule() + { + $input = array('password' => 'foo', 'password_confirmation' => 'bar'); + $rules = array('password' => 'different:password_confirmation'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['password_confirmation'] = 'foo'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + + unset($input['password_confirmation']); + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the accepted validation rule. + * + * @group laravel + */ + public function testTheAcceptedRule() + { + $input = array('terms' => '1'); + $rules = array('terms' => 'accepted'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['terms'] = 'yes'; + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['terms'] = '2'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // The accepted rule implies required, so should fail if field not present. + unset($input['terms']); + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the numeric validation rule. + * + * @group laravel + */ + public function testTheNumericRule() + { + $input = array('amount' => '1.21'); + $rules = array('amount' => 'numeric'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['amount'] = '1'; + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['amount'] = 1.2; + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['amount'] = '1.2a'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the integer validation rule. + * + * @group laravel + */ + public function testTheIntegerRule() + { + $input = array('amount' => '1'); + $rules = array('amount' => 'integer'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['amount'] = '0'; + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['amount'] = 1.2; + $this->assertFalse(Validator::make($input, $rules)->valid()); + + $input['amount'] = '1.2a'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the size validation rule. + * + * @group laravel + */ + public function testTheSizeRule() + { + $input = array('amount' => '1.21'); + $rules = array('amount' => 'numeric|size:1.21'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'numeric|size:1'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // If no numeric rule is on the field, it is treated as a string + $input = array('amount' => '111'); + $rules = array('amount' => 'size:3'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'size:4'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // The size rules checks kilobytes on files + $_FILES['photo']['tmp_name'] = 'foo'; + $_FILES['photo']['size'] = 10240; + $rules = array('photo' => 'size:10'); + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $_FILES['photo']['size'] = 14000; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the between validation rule. + * + * @group laravel + */ + public function testTheBetweenRule() + { + $input = array('amount' => '1.21'); + $rules = array('amount' => 'numeric|between:1,2'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'numeric|between:2,3'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // If no numeric rule is on the field, it is treated as a string + $input = array('amount' => '111'); + $rules = array('amount' => 'between:1,3'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'between:100,111'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // The size rules checks kilobytes on files + $_FILES['photo']['tmp_name'] = 'foo'; + $_FILES['photo']['size'] = 10240; + $rules = array('photo' => 'between:9,11'); + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $_FILES['photo']['size'] = 14000; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the between validation rule. + * + * @group laravel + */ + public function testTheMinRule() + { + $input = array('amount' => '1.21'); + $rules = array('amount' => 'numeric|min:1'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'numeric|min:2'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // If no numeric rule is on the field, it is treated as a string + $input = array('amount' => '01'); + $rules = array('amount' => 'min:2'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'min:3'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // The size rules checks kilobytes on files + $_FILES['photo']['tmp_name'] = 'foo'; + $_FILES['photo']['size'] = 10240; + $rules = array('photo' => 'min:9'); + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $_FILES['photo']['size'] = 8000; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the between validation rule. + * + * @group laravel + */ + public function testTheMaxRule() + { + $input = array('amount' => '1.21'); + $rules = array('amount' => 'numeric|max:2'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'numeric|max:1'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // If no numeric rule is on the field, it is treated as a string + $input = array('amount' => '01'); + $rules = array('amount' => 'max:3'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $rules = array('amount' => 'max:1'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + // The size rules checks kilobytes on files + $_FILES['photo']['tmp_name'] = 'foo'; + $_FILES['photo']['size'] = 10240; + $rules = array('photo' => 'max:11'); + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $_FILES['photo']['size'] = 140000; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the in validation rule. + * + * @group laravel + */ + public function testTheInRule() + { + $input = array('size' => 'L'); + $rules = array('size' => 'in:S,M,L'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['size'] = 'XL'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the not-in validation rule. + * + * @group laravel + */ + public function testTheNotInRule() + { + $input = array('size' => 'L'); + $rules = array('size' => 'not_in:S,M,L'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + $input['size'] = 'XL'; + $this->assertTrue(Validator::make($input, $rules)->valid()); + } + + /** + * Test the IP validation rule. + * + * @group laravel + */ + public function testTheIPRule() + { + $input = array('ip' => '192.168.1.1'); + $rules = array('ip' => 'ip'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['ip'] = '192.111'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the e-mail validation rule. + * + * @group laravel + */ + public function testTheEmailRule() + { + $input = array('email' => 'example@gmail.com'); + $rules = array('email' => 'email'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['email'] = 'blas-asok'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the URL validation rule. + * + * @group laravel + */ + public function testTheUrlRule() + { + $input = array('url' => 'http://www.google.com'); + $rules = array('url' => 'url'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['url'] = 'blas-asok'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the active URL validation rule. + * + * @group laravel + */ + public function testTheActiveUrlRule() + { + $input = array('url' => 'http://google.com'); + $rules = array('url' => 'active_url'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['url'] = 'http://asdlk-aselkaiwels.com'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the image validation rule. + * + * @group laravel + */ + public function testTheImageRule() + { + $_FILES['photo']['tmp_name'] = path('storage').'files/desert.jpg'; + $rules = array('photo' => 'image'); + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $_FILES['photo']['tmp_name'] = path('app').'routes.php'; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the alpha validation rule. + * + * @group laravel + */ + public function testTheAlphaRule() + { + $input = array('name' => 'TaylorOtwell'); + $rules = array('name' => 'alpha'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['name'] = 'Taylor Otwell'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the alpha_num validation rule. + * + * @group laravel + */ + public function testTheAlphaNumRule() + { + $input = array('name' => 'TaylorOtwell1'); + $rules = array('name' => 'alpha_num'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['name'] = 'Taylor Otwell'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the alpha_num validation rule. + * + * @group laravel + */ + public function testTheAlphaDashRule() + { + $input = array('name' => 'Taylor-Otwell_1'); + $rules = array('name' => 'alpha_dash'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['name'] = 'Taylor Otwell'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test the mimes validation rule. + * + * @group laravel + */ + public function testTheMimesRule() + { + $_FILES['file']['tmp_name'] = path('app').'routes.php'; + $rules = array('file' => 'mimes:php,txt'); + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $rules = array('file' => 'mimes:jpg,bmp'); + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + + $_FILES['file']['tmp_name'] = path('storage').'files/desert.jpg'; + $rules['file'] = 'mimes:jpg,bmp'; + $this->assertTrue(Validator::make($_FILES, $rules)->valid()); + + $rules['file'] = 'mimes:txt,bmp'; + $this->assertFalse(Validator::make($_FILES, $rules)->valid()); + } + + /** + * Test the unique validation rule. + * + * @group laravel + */ + public function testUniqueRule() + { + $input = array('code' => 'ZZ'); + $rules = array('code' => 'unique:validation_unique'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input = array('code' => 'AR'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + $rules = array('code' => 'unique:validation_unique,code,AR,code'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + } + + /** + * Tests the exists validation rule. + * + * @group laravel + */ + public function testExistsRule() + { + $input = array('code' => 'TX'); + $rules = array('code' => 'exists:validation_unique'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['code'] = array('TX', 'NY'); + $rules = array('code' => 'exists:validation_unique,code'); + $this->assertTrue(Validator::make($input, $rules)->valid()); + + $input['code'] = array('TX', 'XX'); + $this->assertFalse(Validator::make($input, $rules)->valid()); + + $input['code'] = 'XX'; + $this->assertFalse(Validator::make($input, $rules)->valid()); + } + + /** + * Test that the validator sets the correct messages. + * + * @group laravel + */ + public function testCorrectMessagesAreSet() + { + $lang = require path('app').'language/en/validation.php'; + + $input = array('email' => 'example-foo'); + $rules = array('name' => 'required', 'email' => 'required|email'); + $v = Validator::make($input, $rules); + $v->valid(); + $messages = $v->errors; + $this->assertInstanceOf('Laravel\\Messages', $messages); + $this->assertEquals(str_replace(':attribute', 'name', $lang['required']), $messages->first('name')); + $this->assertEquals(str_replace(':attribute', 'email', $lang['email']), $messages->first('email')); + } + + /** + * Test that custom messages are recognized. + * + * @group laravel + */ + public function testCustomMessagesAreRecognize() + { + $messages = array('required' => 'Required!'); + $rules = array('name' => 'required'); + $v = Validator::make(array(), $rules, $messages); + $v->valid(); + $this->assertEquals('Required!', $v->errors->first('name')); + + $messages['email_required'] = 'Email Required!'; + $rules = array('name' => 'required', 'email' => 'required'); + $v = Validator::make(array(), $rules, $messages); + $v->valid(); + $this->assertEquals('Required!', $v->errors->first('name')); + $this->assertEquals('Email Required!', $v->errors->first('email')); + + $rules = array('custom' => 'required'); + $v = Validator::make(array(), $rules); + $v->valid(); + $this->assertEquals('This field is required!', $v->errors->first('custom')); + } + + /** + * Test that size replacements are made on messages. + * + * @group laravel + */ + public function testNumericSizeReplacementsAreMade() + { + $lang = require path('app').'language/en/validation.php'; + + $input = array('amount' => 100); + $rules = array('amount' => 'numeric|size:80'); + $v = Validator::make($input, $rules); + $v->valid(); + $this->assertEquals(str_replace(array(':attribute', ':size'), array('amount', '80'), $lang['size']['numeric']), $v->errors->first('amount')); + + $rules = array('amount' => 'numeric|between:70,80'); + $v = Validator::make($input, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':min', ':max'), array('amount', '70', '80'), $lang['between']['numeric']); + $this->assertEquals($expect, $v->errors->first('amount')); + + $rules = array('amount' => 'numeric|min:120'); + $v = Validator::make($input, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':min'), array('amount', '120'), $lang['min']['numeric']); + $this->assertEquals($expect, $v->errors->first('amount')); + + $rules = array('amount' => 'numeric|max:20'); + $v = Validator::make($input, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':max'), array('amount', '20'), $lang['max']['numeric']); + $this->assertEquals($expect, $v->errors->first('amount')); + } + + /** + * Test that string size replacements are made on messages. + * + * @group laravel + */ + public function testStringSizeReplacementsAreMade() + { + $lang = require path('app').'language/en/validation.php'; + + $input = array('amount' => '100'); + $rules = array('amount' => 'size:80'); + $v = Validator::make($input, $rules); + $v->valid(); + $this->assertEquals(str_replace(array(':attribute', ':size'), array('amount', '80'), $lang['size']['string']), $v->errors->first('amount')); + + $rules = array('amount' => 'between:70,80'); + $v = Validator::make($input, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':min', ':max'), array('amount', '70', '80'), $lang['between']['string']); + $this->assertEquals($expect, $v->errors->first('amount')); + + $rules = array('amount' => 'min:120'); + $v = Validator::make($input, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':min'), array('amount', '120'), $lang['min']['string']); + $this->assertEquals($expect, $v->errors->first('amount')); + + $rules = array('amount' => 'max:2'); + $v = Validator::make($input, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':max'), array('amount', '2'), $lang['max']['string']); + $this->assertEquals($expect, $v->errors->first('amount')); + } + + /** + * Test that string size replacements are made on messages. + * + * @group laravel + */ + public function testFileSizeReplacementsAreMade() + { + $lang = require path('app').'language/en/validation.php'; + + $_FILES['amount']['tmp_name'] = 'foo'; + $_FILES['amount']['size'] = 10000; + $rules = array('amount' => 'size:80'); + $v = Validator::make($_FILES, $rules); + $v->valid(); + $this->assertEquals(str_replace(array(':attribute', ':size'), array('amount', '80'), $lang['size']['file']), $v->errors->first('amount')); + + $rules = array('amount' => 'between:70,80'); + $v = Validator::make($_FILES, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':min', ':max'), array('amount', '70', '80'), $lang['between']['file']); + $this->assertEquals($expect, $v->errors->first('amount')); + + $rules = array('amount' => 'min:120'); + $v = Validator::make($_FILES, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':min'), array('amount', '120'), $lang['min']['file']); + $this->assertEquals($expect, $v->errors->first('amount')); + + $rules = array('amount' => 'max:2'); + $v = Validator::make($_FILES, $rules); + $v->valid(); + $expect = str_replace(array(':attribute', ':max'), array('amount', '2'), $lang['max']['file']); + $this->assertEquals($expect, $v->errors->first('amount')); + } + + /** + * Test that values get replaced in messages. + * + * @group laravel + */ + public function testValuesGetReplaced() + { + $lang = require path('app').'language/en/validation.php'; + + $_FILES['file']['tmp_name'] = path('storage').'files/desert.jpg'; + $rules = array('file' => 'mimes:php,txt'); + $v = Validator::make($_FILES, $rules); + $v->valid(); + + $expect = str_replace(array(':attribute', ':values'), array('file', 'php, txt'), $lang['mimes']); + $this->assertEquals($expect, $v->errors->first('file')); + } + + /** + * Test custom attribute names are replaced. + * + * @group laravel + */ + public function testCustomAttributesAreReplaced() + { + $lang = require path('app').'language/en/validation.php'; + + $rules = array('test_attribute' => 'required'); + $v = Validator::make(array(), $rules); + $v->valid(); + + $expect = str_replace(':attribute', 'attribute', $lang['required']); + $this->assertEquals($expect, $v->errors->first('test_attribute')); + } + +} \ No newline at end of file diff --git a/laravel/tests/cases/view.test.php b/laravel/tests/cases/view.test.php new file mode 100644 index 00000000..9716724a --- /dev/null +++ b/laravel/tests/cases/view.test.php @@ -0,0 +1,255 @@ +assertInstanceOf('Laravel\\View', View::make('home.index')); + } + + /** + * Test the View class constructor. + * + * @group laravel + */ + public function testViewNameIsSetByConstrutor() + { + $view = new View('home.index'); + + $this->assertEquals('home.index', $view->view); + } + + /** + * Test the View class constructor. + * + * @group laravel + */ + public function testViewIsCreatedWithCorrectPath() + { + $view = new View('home.index'); + + $this->assertEquals( + str_replace(DS, '/', path('app')).'views/home/index.php', + str_replace(DS, '/', $view->path) + ); + } + + /** + * Test the View class constructor for bundles. + * + * @group laravel + */ + public function testBundleViewIsCreatedWithCorrectPath() + { + $view = new View('home.index'); + + $this->assertEquals( + str_replace(DS, '/', Bundle::path(DEFAULT_BUNDLE)).'views/home/index.php', + str_replace(DS, '/', $view->path) + ); + } + + /** + * Test the View class constructor. + * + * @group laravel + */ + public function testDataIsSetOnViewByConstructor() + { + $view = new View('home.index', array('name' => 'Taylor')); + + $this->assertEquals('Taylor', $view->data['name']); + } + + /** + * Test the View::name method. + * + * @group laravel + */ + public function testNameMethodRegistersAViewName() + { + View::name('home.index', 'home'); + + $this->assertEquals('home.index', View::$names['home']); + } + + /** + * Test the View::shared method. + * + * @group laravel + */ + public function testSharedMethodAddsDataToSharedArray() + { + View::share('comment', 'Taylor'); + + $this->assertEquals('Taylor', View::$shared['comment']); + } + + /** + * Test the View::with method. + * + * @group laravel + */ + public function testViewDataCanBeSetUsingWithMethod() + { + $view = View::make('home.index')->with('comment', 'Taylor'); + + $this->assertEquals('Taylor', $view->data['comment']); + } + + /** + * Test the View class constructor. + * + * @group laravel + */ + public function testEmptyMessageContainerSetOnViewWhenNoErrorsInSession() + { + $view = new View('home.index'); + + $this->assertInstanceOf('Laravel\\Messages', $view->data['errors']); + } + + /** + * Test the View __set method. + * + * @group laravel + */ + public function testDataCanBeSetOnViewsThroughMagicMethods() + { + $view = new View('home.index'); + + $view->comment = 'Taylor'; + + $this->assertEquals('Taylor', $view->data['comment']); + } + + /** + * Test the View __get method. + * + * @group laravel + */ + public function testDataCanBeRetrievedFromViewsThroughMagicMethods() + { + $view = new View('home.index'); + + $view->comment = 'Taylor'; + + $this->assertEquals('Taylor', $view->comment); + } + + /** + * Test the View's ArrayAccess implementation. + * + * @group laravel + */ + public function testDataCanBeSetOnTheViewThroughArrayAccess() + { + $view = new View('home.index'); + + $view['comment'] = 'Taylor'; + + $this->assertEquals('Taylor', $view->data['comment']); + } + + /** + * Test the View's ArrayAccess implementation. + * + * @group laravel + */ + public function testDataCanBeRetrievedThroughArrayAccess() + { + $view = new View('home.index'); + + $view['comment'] = 'Taylor'; + + $this->assertEquals('Taylor', $view['comment']); + } + + /** + * Test the View::nest method. + * + * @group laravel + */ + public function testNestMethodSetsViewInstanceInData() + { + $view = View::make('home.index')->nest('partial', 'tests.basic'); + + $this->assertEquals('tests.basic', $view->data['partial']->view); + + $this->assertInstanceOf('Laravel\\View', $view->data['partial']); + } + + /** + * Test that the registered data is passed to the view correctly. + * + * @group laravel + */ + public function testDataIsPassedToViewCorrectly() + { + View::share('name', 'Taylor'); + + $view = View::make('tests.basic')->with('age', 25)->render(); + + $this->assertEquals('Taylor is 25', $view); + } + + /** + * Test that the View class renders nested views. + * + * @group laravel + */ + public function testNestedViewsAreRendered() + { + $view = View::make('tests.basic') + ->with('age', 25) + ->nest('name', 'tests.nested'); + + $this->assertEquals('Taylor is 25', $view->render()); + } + + /** + * Test that the View class renders nested responses. + * + * @group laravel + */ + public function testNestedResponsesAreRendered() + { + $view = View::make('tests.basic') + ->with('age', 25) + ->with('name', Response::view('tests.nested')); + + $this->assertEquals('Taylor is 25', $view->render()); + } + + /** + * Test the View class raises a composer event. + * + * @group laravel + */ + public function testComposerEventIsCalledWhenViewIsRendering() + { + View::composer('tests.basic', function($view) + { + $view->data = array('name' => 'Taylor', 'age' => 25); + }); + + $view = View::make('tests.basic')->render(); + + $this->assertEquals('Taylor is 25', $view); + } + +} \ No newline at end of file diff --git a/laravel/tests/phpunit.php b/laravel/tests/phpunit.php new file mode 100644 index 00000000..8e5ba204 --- /dev/null +++ b/laravel/tests/phpunit.php @@ -0,0 +1,32 @@ + * // Get the first segment of the request URI diff --git a/laravel/url.php b/laravel/url.php index 44b89428..c87139e4 100644 --- a/laravel/url.php +++ b/laravel/url.php @@ -26,7 +26,7 @@ public static function full() */ public static function current() { - return static::to(URI::current()); + return static::to(URI::current(), null, false, false); } /** @@ -89,9 +89,11 @@ public static function base() * * @param string $url * @param bool $https + * @param bool $asset + * @param bool $locale * @return string */ - public static function to($url = '', $https = null) + public static function to($url = '', $https = null, $asset = false, $locale = true) { // If the given URL is already valid or begins with a hash, we'll just return // the URL unchanged since it is already well formed. Otherwise we will add @@ -101,11 +103,26 @@ public static function to($url = '', $https = null) return $url; } - // Unless $https is specified (true or false) then maintain the current request + // Unless $https is specified (true or false), we maintain the current request // security for any new links generated. So https for all secure links. if (is_null($https)) $https = Request::secure(); - $root = static::base().'/'.Config::get('application.index'); + $root = static::base(); + + if ( ! $asset) + { + $root .= '/'.Config::get('application.index'); + } + + $languages = Config::get('application.languages'); + + if ( ! $asset and $locale and count($languages) > 0) + { + if (in_array($default = Config::get('application.language'), $languages)) + { + $root = rtrim($root, '/').'/'.$default; + } + } // Since SSL is not often used while developing the application, we allow the // developer to disable SSL on all framework generated links to make it more @@ -169,7 +186,7 @@ public static function to_action($action, $parameters = array()) } /** - * Generate a action URL from a route definition + * Generate an action URL from a route definition * * @param array $route * @param string $action @@ -196,7 +213,7 @@ protected static function convention($action, $parameters) $bundle = Bundle::get($bundle); - // If a bundle exists for the action, we will attempt to use it's "handles" + // If a bundle exists for the action, we will attempt to use its "handles" // clause as the root of the generated URL, as the bundle can only handle // URIs that begin with that string and no others. $root = $bundle['handles'] ?: ''; @@ -232,7 +249,7 @@ public static function to_asset($url, $https = null) return rtrim($root, '/').'/'.ltrim($url, '/'); } - $url = static::to($url, $https); + $url = static::to($url, $https, true); // Since assets are not served by Laravel, we do not need to come through // the front controller. So, we'll remove the application index specified @@ -316,4 +333,4 @@ public static function valid($url) return filter_var($url, FILTER_VALIDATE_URL) !== false; } -} \ No newline at end of file +} diff --git a/laravel/validator.php b/laravel/validator.php index 3290bc17..ab446860 100644 --- a/laravel/validator.php +++ b/laravel/validator.php @@ -214,7 +214,7 @@ protected function validatable($rule, $attribute, $value) */ protected function implicit($rule) { - return $rule == 'required' or $rule == 'accepted'; + return $rule == 'required' or $rule == 'accepted' or $rule == 'required_with'; } /** @@ -257,6 +257,27 @@ protected function validate_required($attribute, $value) return true; } + /** + * Validate that an attribute exists in the attributes array, if another + * attribute exists in the attributes array. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + protected function validate_required_with($attribute, $value, $parameters) + { + $other = $parameters[0]; + + if ($this->validate_required($other, $this->attributes[$other])) + { + return $this->validate_required($attribute, $value); + } + + return true; + } + /** * Validate that an attribute has a matching confirmation attribute. * @@ -401,8 +422,8 @@ protected function validate_max($attribute, $value, $parameters) protected function size($attribute, $value) { // This method will determine if the attribute is a number, string, or file and - // return the proper size accordingly. If it is a number, then number itself is - // the size; if it is a file, the size is kilobytes in the size; if it is a + // return the proper size accordingly. If it is a number, the number itself is + // the size; if it is a file, the kilobytes is the size; if it is a // string, the length is the size. if (is_numeric($value) and $this->has_rule($attribute, $this->numeric_rules)) { @@ -560,7 +581,7 @@ protected function validate_active_url($attribute, $value) { $url = str_replace(array('http://', 'https://', 'ftp://'), '', Str::lower($value)); - return checkdnsrr($url); + return (trim($url) !== '') ? checkdnsrr($url) : false; } /** @@ -616,6 +637,7 @@ protected function validate_alpha_dash($attribute, $value) * * @param string $attribute * @param mixed $value + * @param array $parameters * @return bool */ protected function validate_match($attribute, $value, $parameters) @@ -646,6 +668,70 @@ protected function validate_mimes($attribute, $value, $parameters) return false; } + /** + * Validate that an attribute is an array + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + protected function validate_array($attribute, $value) + { + return is_array($value); + } + + /** + * Validate that an attribute of type array has a specific count + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + protected function validate_count($attribute, $value, $parameters) + { + return (is_array($value) && count($value) == $parameters[0]); + } + + /** + * Validate that an attribute of type array has a minimum of elements. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + protected function validate_countmin($attribute, $value, $parameters) + { + return (is_array($value) && count($value) >= $parameters[0]); + } + + /** + * Validate that an attribute of type array has a maximum of elements. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + protected function validate_countmax($attribute, $value, $parameters) + { + return (is_array($value) && count($value) <= $parameters[0]); + } + + /** + * Validate that an attribute of type array has elements between max and min. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + protected function validate_countbetween($attribute, $value, $parameters) + { + return (is_array($value) && count($value) >= $parameters[0] && count($value) <= $parameters[1] ); + } + /** * Validate the date is before a given date. * @@ -743,7 +829,7 @@ protected function size_message($bundle, $attribute, $rule) } // We assume that attributes present in the $_FILES array are files, // which makes sense. If the attribute doesn't have numeric rules - // and isn't as file, it's a string. + // and isn't a file, it's a string. elseif (array_key_exists($attribute, Input::file())) { $line = 'file'; @@ -862,7 +948,7 @@ protected function replace_not_in($message, $attribute, $rule, $parameters) } /** - * Replace all place-holders for the not_in rule. + * Replace all place-holders for the mimes rule. * * @param string $message * @param string $attribute @@ -931,6 +1017,62 @@ protected function replace_after($message, $attribute, $rule, $parameters) return str_replace(':date', $parameters[0], $message); } + /** + * Replace all place-holders for the count rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replace_count($message, $attribute, $rule, $parameters) + { + return str_replace(':count', $parameters[0], $message); + } + + /** + * Replace all place-holders for the countmin rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replace_countmin($message, $attribute, $rule, $parameters) + { + return str_replace(':min', $parameters[0], $message); + } + + /** + * Replace all place-holders for the countmax rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replace_countmax($message, $attribute, $rule, $parameters) + { + return str_replace(':max', $parameters[0], $message); + } + + /** + * Replace all place-holders for the between rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replace_countbetween($message, $attribute, $rule, $parameters) + { + return str_replace(array(':min', ':max'), $parameters, $message); + } + /** * Get the displayable name for a given attribute. * @@ -953,7 +1095,7 @@ protected function attribute($attribute) // If no language line has been specified for the attribute, all of // the underscores are removed from the attribute name and that - // will be used as the attribtue name. + // will be used as the attribute name. else { return str_replace('_', ' ', $attribute); diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/LaravelResponse.php b/laravel/vendor/Symfony/Component/HttpFoundation/LaravelResponse.php new file mode 100644 index 00000000..9fe45ecf --- /dev/null +++ b/laravel/vendor/Symfony/Component/HttpFoundation/LaravelResponse.php @@ -0,0 +1,40 @@ + + * + * @api + */ +class LaravelResponse extends Response +{ + + /** + * Sends HTTP headers and content. + * + * @return Response + * + * @api + */ + public function send() + { + $this->sendHeaders(); + $this->sendContent(); + + return $this; + } + + /** + * Finishes the request for PHP-FastCGI + * + * @return void + */ + public function finish() + { + if (function_exists('fastcgi_finish_request')) { + fastcgi_finish_request(); + } + } + +} diff --git a/laravel/view.php b/laravel/view.php index 9a375073..d8275c6e 100644 --- a/laravel/view.php +++ b/laravel/view.php @@ -168,7 +168,7 @@ public static function file($bundle, $view, $directory) { $directory = str_finish($directory, DS); - // Views may have either the default PHP file extension of the "Blade" + // Views may have either the default PHP file extension or the "Blade" // extension, so we will need to check for both in the view path // and return the first one we find for the given view. if (file_exists($path = $directory.$view.EXT)) @@ -255,7 +255,7 @@ public static function name($view, $name) * }); * * - * @param string|array $view + * @param string|array $views * @param Closure $composer * @return void */ @@ -296,7 +296,7 @@ public static function render_each($view, array $data, $iterator, $empty = 'raw| } // If there is no data in the array, we will render the contents of - // the "empty" view. Alternative, the "empty view" can be a raw + // the "empty" view. Alternatively, the "empty view" can be a raw // string that is prefixed with "raw|" for convenience. else { @@ -551,4 +551,20 @@ public function __toString() return $this->render(); } + /** + * Magic Method for handling dynamic functions. + * + * This method handles calls to dynamic with helpers. + */ + public function __call($method, $parameters) + { + if (strpos($method, 'with_') === 0) + { + $key = substr($method, 5); + return $this->with($key, $parameters[0]); + } + + throw new \Exception("Method [$method] is not defined on the View class."); + } + } \ No newline at end of file diff --git a/paths.php b/paths.php index 3a6622ff..bd870438 100644 --- a/paths.php +++ b/paths.php @@ -3,18 +3,18 @@ * Laravel - A PHP Framework For Web Artisans * * @package Laravel - * @version 3.2.3 + * @version 3.2.8 * @author Taylor Otwell * @link http://laravel.com */ /* |---------------------------------------------------------------- -| Application Environemtns +| Application Environments |---------------------------------------------------------------- | | Laravel takes a dead simple approach to environments, and we -| think you'll love it. Just specify which URLs belongs to a +| think you'll love it. Just specify which URLs belong to a | given environment, and when you access your application | from a URL matching that pattern, we'll be sure to | merge in that environment's configuration files. diff --git a/public/index.php b/public/index.php index 00cb86cd..3b213a95 100644 --- a/public/index.php +++ b/public/index.php @@ -3,7 +3,7 @@ * Laravel - A PHP Framework For Web Artisans * * @package Laravel - * @version 3.2.3 + * @version 3.2.8 * @author Taylor Otwell * @link http://laravel.com */