From abd30eb3388fc566feea97e3ec8052049f6e7c3e Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Wed, 15 Aug 2012 17:26:33 +0300 Subject: [PATCH 01/35] Fix contribution page links in documentation. --- laravel/documentation/contents.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/laravel/documentation/contents.md b/laravel/documentation/contents.md index 88a7ac24..d29b3908 100644 --- a/laravel/documentation/contents.md +++ b/laravel/documentation/contents.md @@ -113,6 +113,6 @@ ### Contributing -- [Laravel on GitHub](docs/contrib/github) -- [Command Line](docs/contrib/command-line) -- [TortoiseGit](docs/contrib/tortoisegit) +- [Laravel on GitHub](/docs/contrib/github) +- [Command Line](/docs/contrib/command-line) +- [TortoiseGit](/docs/contrib/tortoisegit) From f97fb3a457240718b0a4c43c5e137da35b0a1d87 Mon Sep 17 00:00:00 2001 From: kapil verma Date: Sat, 1 Sep 2012 19:00:47 +0530 Subject: [PATCH 02/35] Updated Paginator to fit better with bootstrap 2.1 The Paginator Renders a list of links compatible with bootstrap 2.1 standards ... so the irritating bug that used to be there on active and disabled pages is gone --- laravel/paginator.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/laravel/paginator.php b/laravel/paginator.php index 3deb5f61..e45e7d7c 100644 --- a/laravel/paginator.php +++ b/laravel/paginator.php @@ -183,7 +183,7 @@ class Paginator { $links = $this->slider($adjacent); } - $content = $this->previous().' '.$links.' '.$this->next(); + $content = ''; return ''; } @@ -300,7 +300,7 @@ class Paginator { // 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 @@ class Paginator { { if ($this->page == $page) { - $pages[] = HTML::span($page, array('class' => 'current')); + $pages[] = '
  • '.$page.'
  • '; } else { @@ -372,7 +372,7 @@ class Paginator { { $query = '?page='.$page.$this->appendage($this->appends); - return HTML::link(URI::current().$query, $text, compact('class'), Request::secure()); + return ''. HTML::link(URI::current().$query, $text, [], Request::secure()).''; } /** From 2a5d7c3080901b30e37898e79e5df94d290ac11c Mon Sep 17 00:00:00 2001 From: kapil verma Date: Sun, 2 Sep 2012 12:27:06 +0530 Subject: [PATCH 03/35] Fixed the use of 5.4 array syntax in one place SO that things dont break for 5.3 peeps --- laravel/paginator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/paginator.php b/laravel/paginator.php index e45e7d7c..7f406281 100644 --- a/laravel/paginator.php +++ b/laravel/paginator.php @@ -372,7 +372,7 @@ class Paginator { { $query = '?page='.$page.$this->appendage($this->appends); - return ''. HTML::link(URI::current().$query, $text, [], Request::secure()).''; + return ''. HTML::link(URI::current().$query, $text, array(), Request::secure()).''; } /** From 163f39075db7dde53dd4f8fb5c60cb111c2c9fde Mon Sep 17 00:00:00 2001 From: George Drakakis Date: Mon, 3 Sep 2012 13:59:49 +0300 Subject: [PATCH 04/35] Added Greek Language Signed-off-by: George Drakakis --- application/language/gr/pagination.php | 19 +++++ application/language/gr/validation.php | 104 +++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 application/language/gr/pagination.php create mode 100644 application/language/gr/validation.php 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 From a1c7dde08bf60dcd916d529bcc315234e676d844 Mon Sep 17 00:00:00 2001 From: Joost Koehoorn Date: Mon, 3 Sep 2012 16:42:14 +0300 Subject: [PATCH 05/35] Fixed problem with manual running of Artisan tasks When running an Artisan task from within your application using `Command::run`, it fails when the same task is ran more than once. Every time the task is resolved, its file is included using `require` leading to duplicate class definitions. By using `require_once` this problem is avoided. --- laravel/cli/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/cli/command.php b/laravel/cli/command.php index 113881c2..c6a25ee4 100644 --- a/laravel/cli/command.php +++ b/laravel/cli/command.php @@ -125,7 +125,7 @@ class Command { // 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); From afe4485641b7c4baeb43dd7e3a355533fba0448d Mon Sep 17 00:00:00 2001 From: Roumen Damianoff Date: Mon, 3 Sep 2012 18:49:38 +0300 Subject: [PATCH 06/35] Bulgarian translation for array validator messages. --- application/language/bg/validation.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/application/language/bg/validation.php b/application/language/bg/validation.php index fe01d9be..c95b1ed3 100644 --- a/application/language/bg/validation.php +++ b/application/language/bg/validation.php @@ -24,7 +24,7 @@ return array( "alpha" => "Полето :attribute трябва да съдържа само букви.", "alpha_dash" => "Полето :attribute трябва да съдържа само букви, цифри, долна черта и тире.", "alpha_num" => "Полето :attribute трябва да съдържа само букви и цифри.", - "array" => "The :attribute must have selected elements.", + "array" => "Полето :attribute трябва да има избрани елементи.", "before" => "Полето :attribute трябва да бъде дата преди :date.", "between" => array( "numeric" => "Полето :attribute трябва да бъде между :min и :max.", @@ -32,10 +32,10 @@ return array( "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.", + "count" => "Полето :attribute трябва да има точно :count избрани елементи.", + "countbetween" => "Полето :attribute трябва да има от :min до :max избрани елементи.", + "countmax" => "Полето :attribute трябва да има по-малко от :max избрани елементи.", + "countmin" => "Полето :attribute трябва да има минимум :min избрани елементи.", "different" => "Полетата :attribute и :other трябва да са различни.", "email" => "Полето :attribute е с невалиден формат.", "exists" => "Избраната стойност на :attribute вече съществува.", From 6b73974505557c9663f9f6cbc00793d3225c9d20 Mon Sep 17 00:00:00 2001 From: Callum McIntyre Date: Mon, 3 Sep 2012 21:44:16 +0100 Subject: [PATCH 07/35] Added new touch function to eloquent, updates timestamps and immediately saves Signed-off-by: Callum McIntyre --- laravel/database/eloquent/model.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/laravel/database/eloquent/model.php b/laravel/database/eloquent/model.php index 306d471a..c2566496 100644 --- a/laravel/database/eloquent/model.php +++ b/laravel/database/eloquent/model.php @@ -452,6 +452,16 @@ abstract class Model { 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. * From 0161273010fd5217d0f0b2e1ee03066d2204fcb8 Mon Sep 17 00:00:00 2001 From: Callum McIntyre Date: Mon, 3 Sep 2012 22:23:58 +0100 Subject: [PATCH 08/35] Added documentation for the touch() function Signed-off-by: Callum McIntyre --- laravel/documentation/database/eloquent.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/laravel/documentation/database/eloquent.md b/laravel/documentation/database/eloquent.md index cbcf83c9..45969c79 100644 --- a/laravel/documentation/database/eloquent.md +++ b/laravel/documentation/database/eloquent.md @@ -132,6 +132,11 @@ Need to maintain creation and update timestamps on your database records? With E 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(); + > **Note:** You can change the default timezone of your application in the **application/config/application.php** file. From c8ee7ca6148942be2ccff7e26518721425f80247 Mon Sep 17 00:00:00 2001 From: Callum McIntyre Date: Mon, 3 Sep 2012 23:23:36 +0100 Subject: [PATCH 09/35] Added documentation regarding the newly public timestamp() function Signed-off-by: Callum McIntyre --- laravel/documentation/database/eloquent.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/laravel/documentation/database/eloquent.md b/laravel/documentation/database/eloquent.md index 45969c79..09493db0 100644 --- a/laravel/documentation/database/eloquent.md +++ b/laravel/documentation/database/eloquent.md @@ -137,6 +137,13 @@ In some cases it may be useful to update the **updated_at** date column without $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. From 05552f2c617550563a40a58b9b4dcfb4b10dae21 Mon Sep 17 00:00:00 2001 From: flaviozantut Date: Mon, 3 Sep 2012 19:49:32 -0300 Subject: [PATCH 10/35] Added Portuguese Language --- application/language/pt/pagination.php | 0 application/language/pt/validation.php | 99 ++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 application/language/pt/pagination.php create mode 100644 application/language/pt/validation.php diff --git a/application/language/pt/pagination.php b/application/language/pt/pagination.php new file mode 100644 index 00000000..e69de29b 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 From 8599d7833859a0ca4af14c505e7465d368428b57 Mon Sep 17 00:00:00 2001 From: flaviozantut Date: Mon, 3 Sep 2012 20:27:56 -0300 Subject: [PATCH 11/35] Added Portuguese Language --- application/language/pt/pagination.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/application/language/pt/pagination.php b/application/language/pt/pagination.php index e69de29b..e6303530 100644 --- a/application/language/pt/pagination.php +++ b/application/language/pt/pagination.php @@ -0,0 +1,19 @@ + '« Anterior', + 'next' => 'Próxima »', + +); \ No newline at end of file From 8e145e6c118d5416c95b0d1391a0c9cc0b0e1f18 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Tue, 4 Sep 2012 16:36:17 +0300 Subject: [PATCH 12/35] Make Eloquent auth driver respect a model's custom password getter. This fixes #1140. --- laravel/auth/drivers/eloquent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/auth/drivers/eloquent.php b/laravel/auth/drivers/eloquent.php index e376483e..35fe07d2 100644 --- a/laravel/auth/drivers/eloquent.php +++ b/laravel/auth/drivers/eloquent.php @@ -50,7 +50,7 @@ class Eloquent extends Driver { $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')); } From deac7b36a41ebe8890b4e1d5679c0a3c8f8b6570 Mon Sep 17 00:00:00 2001 From: George Drakakis Date: Tue, 4 Sep 2012 20:20:08 +0300 Subject: [PATCH 13/35] Changed the folder name from "gr" to "el" Signed-off-by: George Drakakis --- application/language/el/pagination.php | 19 +++++ application/language/el/validation.php | 104 +++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 application/language/el/pagination.php create mode 100644 application/language/el/validation.php 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 From 69ebe6d56aa53fc555145ac4717004cd2856a9da Mon Sep 17 00:00:00 2001 From: Aaron Kuzemchak Date: Wed, 5 Sep 2012 16:07:20 -0400 Subject: [PATCH 14/35] Allow Input::json() to return array instead of object --- laravel/input.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/laravel/input.php b/laravel/input.php index 2235ad51..b76fc7c6 100644 --- a/laravel/input.php +++ b/laravel/input.php @@ -102,13 +102,14 @@ class Input { /** * 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); } /** From c1bcfec3d2da1c6ef27b3de685228622ef21aa51 Mon Sep 17 00:00:00 2001 From: kapil verma Date: Thu, 6 Sep 2012 04:42:58 +0530 Subject: [PATCH 15/35] Turn profiler off using runtime Config just added a check in Profiler's render method to also look at Config::get('application.profiler') as laravel allows changing config during runtime. This allows turning off profiler for certain actions --- laravel/profiling/profiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/profiling/profiler.php b/laravel/profiling/profiler.php index 01469ab8..360e4702 100644 --- a/laravel/profiling/profiler.php +++ b/laravel/profiling/profiler.php @@ -27,7 +27,7 @@ class Profiler { // 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)); From 7e11bb74313fe6f388253b45d450390b663f39a7 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Fri, 7 Sep 2012 14:32:12 +0200 Subject: [PATCH 16/35] Delete phpunit.xml file. Looks like that was committed accidentally. --- phpunit.xml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 phpunit.xml diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index d7a799bf..00000000 --- a/phpunit.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - /Users/taylor/Code/Laravel/framework/laravel/tests/cases - - - \ No newline at end of file From 9348046d0eaef216eaa7e2f2c2506c25bbad2086 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Fri, 7 Sep 2012 14:32:37 +0200 Subject: [PATCH 17/35] Fix dynamically generated phpunit.xml file not being deleted automatically in the test runner. --- laravel/cli/tasks/test/runner.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/laravel/cli/tasks/test/runner.php b/laravel/cli/tasks/test/runner.php index b34e5225..0d9fb4e6 100644 --- a/laravel/cli/tasks/test/runner.php +++ b/laravel/cli/tasks/test/runner.php @@ -86,9 +86,9 @@ class Runner extends Task { // fix the spaced directories problem when using the command line // strings with spaces inside should be wrapped in quotes. - $path = escapeshellarg($path); + $esc_path = escapeshellarg($path); - passthru('phpunit --configuration '.$path, $status); + passthru('phpunit --configuration '.$esc_path, $status); @unlink($path); From f7cdb76f36bf00f9016bc28eb19162cf71fee476 Mon Sep 17 00:00:00 2001 From: Neo Ighodaro Date: Sun, 9 Sep 2012 09:08:55 +0100 Subject: [PATCH 18/35] The bundle variable is not defined anywhere in the method scope. --- laravel/cli/tasks/bundle/providers/provider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/cli/tasks/bundle/providers/provider.php b/laravel/cli/tasks/bundle/providers/provider.php index 258500c2..d22487f7 100644 --- a/laravel/cli/tasks/bundle/providers/provider.php +++ b/laravel/cli/tasks/bundle/providers/provider.php @@ -73,7 +73,7 @@ abstract class Provider { // zip that was put in the storage directory. if ($remote === false) { - throw new \Exception("Error downloading bundle [{$bundle}]."); + throw new \Exception("Error downloading bundle."); } return $remote; From f0a2ffef2b2178a4f9e56b453397cccf924f3632 Mon Sep 17 00:00:00 2001 From: Neo Ighodaro Date: Sun, 9 Sep 2012 09:09:41 +0100 Subject: [PATCH 19/35] The bundle variable is not defined anywhere in the method scope. Signed-off-by: Neo Ighodaro --- laravel/cli/tasks/bundle/providers/provider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/cli/tasks/bundle/providers/provider.php b/laravel/cli/tasks/bundle/providers/provider.php index d22487f7..8ac853ff 100644 --- a/laravel/cli/tasks/bundle/providers/provider.php +++ b/laravel/cli/tasks/bundle/providers/provider.php @@ -73,7 +73,7 @@ abstract class Provider { // zip that was put in the storage directory. if ($remote === false) { - throw new \Exception("Error downloading bundle."); + throw new \Exception("Error downloading the requested bundle."); } return $remote; From fde0d1128ad0827643497418ba7c5bbcda7d3acc Mon Sep 17 00:00:00 2001 From: Bryan te Beek Date: Sun, 9 Sep 2012 16:34:39 +0200 Subject: [PATCH 20/35] Added/fixed Dutch Translation (nl_NL) Signed-off-by: Bryan te Beek --- application/language/nl/validation.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/application/language/nl/validation.php b/application/language/nl/validation.php index ac0c8416..920e32c0 100644 --- a/application/language/nl/validation.php +++ b/application/language/nl/validation.php @@ -10,12 +10,12 @@ return array( */ "accepted" => "Het :attribute moet geaccepteerd zijn.", - "active_url" => "Het :attribute is geen geldig URL.", + "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", - "array" => "The :attribute must have selected elements.", + "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.", @@ -23,17 +23,17 @@ return array( "string" => "Het :attribute moet tussen :min en :max tekens zijn.", ), "confirmed" => "Het :attribute bevestiging komt niet overeen.", - "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.", + "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 bevatten.", + "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.", From b438fe819edf12ce6a88e77387840e7528b981ea Mon Sep 17 00:00:00 2001 From: Bryan te Beek Date: Sun, 9 Sep 2012 18:05:04 +0200 Subject: [PATCH 21/35] A few small fixes to Dutch translation (nl_NL) Signed-off-by: Bryan te Beek --- application/language/nl/validation.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/application/language/nl/validation.php b/application/language/nl/validation.php index 920e32c0..92ebf53e 100644 --- a/application/language/nl/validation.php +++ b/application/language/nl/validation.php @@ -20,7 +20,7 @@ return array( "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 tekens 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.", @@ -33,18 +33,18 @@ return array( "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.", + "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 tekens 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 characters zijn.", + "string" => "Het :attribute moet minimaal :min karakters zijn.", ), "not_in" => "Het :attribute formaat is ongeldig.", "numeric" => "Het :attribute moet een nummer zijn.", From 4de8921f2db47c6e216abfdb563dd31581f0e59d Mon Sep 17 00:00:00 2001 From: kapil verma Date: Mon, 10 Sep 2012 12:02:55 +0530 Subject: [PATCH 22/35] Fixed The $dots property So that it doesn't screw up pagination --- laravel/paginator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/paginator.php b/laravel/paginator.php index 7f406281..b12c4a27 100644 --- a/laravel/paginator.php +++ b/laravel/paginator.php @@ -65,7 +65,7 @@ class Paginator { * * @var string */ - protected $dots = '...'; + protected $dots = '
  • ...
  • '; /** * Create a new Paginator instance. From adc23dc9649aa9fce523e3b7b757cff85476af06 Mon Sep 17 00:00:00 2001 From: Jason Walton Date: Mon, 10 Sep 2012 11:25:08 -0700 Subject: [PATCH 23/35] Added traffic and chassis as uncountable words to properly feed pluralizer Signed-off-by: Jason Walton --- application/config/strings.php | 4 +++- laravel/tests/application/config/strings.php | 7 +++++-- laravel/tests/cases/str.test.php | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/application/config/strings.php b/application/config/strings.php index 3d8b68f6..bbbe230c 100644 --- a/application/config/strings.php +++ b/application/config/strings.php @@ -96,6 +96,8 @@ return array( 'sheep', 'species', 'moose', + 'chassis', + 'traffic', ), /* @@ -185,4 +187,4 @@ return array( ), -); \ No newline at end of file +); diff --git a/laravel/tests/application/config/strings.php b/laravel/tests/application/config/strings.php index 730f973e..bbbe230c 100644 --- a/laravel/tests/application/config/strings.php +++ b/laravel/tests/application/config/strings.php @@ -8,7 +8,7 @@ return array( |-------------------------------------------------------------------------- | | 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. @@ -95,6 +95,9 @@ return array( 'series', 'sheep', 'species', + 'moose', + 'chassis', + 'traffic', ), /* @@ -184,4 +187,4 @@ return array( ), -); \ No newline at end of file +); diff --git a/laravel/tests/cases/str.test.php b/laravel/tests/cases/str.test.php index 7daab540..7c380600 100644 --- a/laravel/tests/cases/str.test.php +++ b/laravel/tests/cases/str.test.php @@ -96,6 +96,8 @@ class StrTest extends PHPUnit_Framework_TestCase { $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)); } /** @@ -130,4 +132,4 @@ class StrTest extends PHPUnit_Framework_TestCase { $this->assertEquals(40, strlen(Str::random(40))); } -} \ No newline at end of file +} From 85cab82f37731f09f319418a0a308d2580c57a1d Mon Sep 17 00:00:00 2001 From: kapil verma Date: Tue, 11 Sep 2012 07:48:01 +0530 Subject: [PATCH 24/35] Fixed 2 stupid bugs for better markup Thats it .. pulling on the docs now --- laravel/paginator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/laravel/paginator.php b/laravel/paginator.php index b12c4a27..e9b95e35 100644 --- a/laravel/paginator.php +++ b/laravel/paginator.php @@ -300,7 +300,7 @@ class Paginator { // the "first" element should be a span instead of a link. if ($disabled($this->page, $this->last)) { - return '"{$class} disabled")).'>'.$text.''; + return '"{$class} disabled")).'>'.$text.''; } else { @@ -372,7 +372,7 @@ class Paginator { { $query = '?page='.$page.$this->appendage($this->appends); - return ''. HTML::link(URI::current().$query, $text, array(), Request::secure()).''; + return ' $class)).'>'. HTML::link(URI::current().$query, $text, array(), Request::secure()).''; } /** From b63b0c08294a00a0a9c30e3d5a0152f9e3088b05 Mon Sep 17 00:00:00 2001 From: kapil verma Date: Tue, 11 Sep 2012 08:09:30 +0530 Subject: [PATCH 25/35] Updated Documentation for Bootstrap-y Pagination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Docs now show bootstrap style Pagination  --- laravel/documentation/views/pagination.md | 30 ++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/laravel/documentation/views/pagination.md b/laravel/documentation/views/pagination.md index 95b5479b..081a6f60 100644 --- a/laravel/documentation/views/pagination.md +++ b/laravel/documentation/views/pagination.md @@ -80,29 +80,31 @@ Sometimes you may need to create a Paginator instance manually, without using th 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 +
  • Previous
  • From c7763a23bd7f43f8837ac7077664931518ce8e3b Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Wed, 12 Sep 2012 14:40:55 +0300 Subject: [PATCH 26/35] Add definition list helper to HTML class. --- laravel/html.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/laravel/html.php b/laravel/html.php index fd5bf82e..e3b2a993 100644 --- a/laravel/html.php +++ b/laravel/html.php @@ -347,6 +347,28 @@ class HTML { 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. From 5942771ce9bd69d46ce2b84ac683681c322a776e Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Wed, 12 Sep 2012 14:42:20 +0300 Subject: [PATCH 27/35] Add documentation for definition list helper. --- laravel/documentation/views/html.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/laravel/documentation/views/html.md b/laravel/documentation/views/html.md index 5bcaa389..aabe244d 100644 --- a/laravel/documentation/views/html.md +++ b/laravel/documentation/views/html.md @@ -119,6 +119,8 @@ The "mailto" method on the HTML class obfuscates the given e-mail address so it 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 From 65d4b2448ba43fdfa61769a770786c1c47a43780 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Fri, 14 Sep 2012 22:21:35 +0300 Subject: [PATCH 28/35] Fix closing tag in definition list helper. --- laravel/html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/html.php b/laravel/html.php index e3b2a993..211e4022 100644 --- a/laravel/html.php +++ b/laravel/html.php @@ -367,7 +367,7 @@ class HTML { $html .= '
    '.static::entities($description).'
    '; } - return ''.$html.''; + return ''.$html.''; } /** From 1474491d623b73fcba6ad0c46651a39aab00b3d5 Mon Sep 17 00:00:00 2001 From: decola977 Date: Sat, 15 Sep 2012 21:36:34 +0300 Subject: [PATCH 29/35] Update application/language/de/validation.php --- application/language/de/validation.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/language/de/validation.php b/application/language/de/validation.php index 170cc261..cb41d00c 100644 --- a/application/language/de/validation.php +++ b/application/language/de/validation.php @@ -22,8 +22,8 @@ return array( "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 sollte nur aus Buchstaben, Nummern und Bindestrichen bestehen.", - "alpha_num" => ":attribute sollte nur aus Buchstaben und Nummern bestehen.", + "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( @@ -57,7 +57,7 @@ return array( ), "not_in" => "Der gewählte Wert für :attribute ist ungültig.", "numeric" => ":attribute muss eine Zahl sein.", - "required" => ":attribute muss aufgefüllt sein.", + "required" => ":attribute muss ausgefüllt sein.", "same" => ":attribute und :other müssen übereinstimmen.", "size" => array( "numeric" => ":attribute muss gleich :size sein.", From 2d13b3d50475cef73ba8068cc6477be5f6575f52 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Mon, 17 Sep 2012 18:58:24 +0200 Subject: [PATCH 30/35] Add a CONTRIBUTING.md file for GitHub. --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 CONTRIBUTING.md 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 From 925e5bed738f3f9ab1321266e2accbc7a14e5dd3 Mon Sep 17 00:00:00 2001 From: Boris Strahija Date: Tue, 18 Sep 2012 17:22:45 +0300 Subject: [PATCH 31/35] Trimming whitespace before doctype tag When using layouts and sections --- laravel/blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laravel/blade.php b/laravel/blade.php index f5bed6f4..f0a520ab 100644 --- a/laravel/blade.php +++ b/laravel/blade.php @@ -68,7 +68,7 @@ class Blade { // 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()); }); } From 110966bd6a382da47c1cb554cd4b38b9bdcab672 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 25 Sep 2012 08:40:29 -0500 Subject: [PATCH 32/35] working on cookie fingerprinting. --- laravel/cookie.php | 42 ++++++++++++++++++++++++++-- laravel/tests/cases/auth.test.php | 2 +- laravel/tests/cases/cookie.test.php | 6 ++-- laravel/tests/cases/session.test.php | 2 +- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/laravel/cookie.php b/laravel/cookie.php index 1c3b5873..21c67bb7 100644 --- a/laravel/cookie.php +++ b/laravel/cookie.php @@ -44,9 +44,14 @@ class Cookie { */ public static function get($name, $default = null) { - if (isset(static::$jar[$name])) return static::$jar[$name]['value']; + if (isset(static::$jar[$name])) return static::parse(static::$jar[$name]['value']); - return array_get(Request::foundation()->cookies->all(), $name, $default); + if ( ! is_null($value = Request::foundation()->cookies->get($name))) + { + return static::parse($value); + } + + return value($default); } /** @@ -75,6 +80,8 @@ class Cookie { $expiration = time() + ($expiration * 60); } + $value = sha1($value.Config::get('application.key')).'+'.$value; + // 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 insecure HTTP. @@ -120,4 +127,35 @@ class Cookie { return static::put($name, null, -2000, $path, $domain, $secure); } + /** + * Parse a hash fingerprinted cookie value. + * + * @param string $value + * @return string + */ + protected static function parse($value) + { + $segments = explode('+', $value); + + // First we will make sure the cookie actually has enough segments to even + // be valid as being set by the application. If it does not we will go + // ahead and throw exceptions now since there the cookie is invalid. + if ( ! (count($segments) >= 2)) + { + throw new \Exception("Cookie was not set by application."); + } + + $value = implode('+', array_slice($segments, 1)); + + // Now we will check if the SHA-1 hash present in the first segment matches + // the ShA-1 hash of the rest of the cookie value, since the hash should + // have been set when the cookie was first created by the application. + if ($segments[0] == sha1($value.Config::get('application.key'))) + { + return $value; + } + + throw new \Exception("Cookie has been modified by client."); + } + } diff --git a/laravel/tests/cases/auth.test.php b/laravel/tests/cases/auth.test.php index 16ba428a..44ff671e 100644 --- a/laravel/tests/cases/auth.test.php +++ b/laravel/tests/cases/auth.test.php @@ -269,7 +269,7 @@ class AuthTest extends PHPUnit_Framework_TestCase { $this->assertTrue(isset(Cookie::$jar['laravel_auth_drivers_fluent_remember'])); - $cookie = Cookie::$jar['laravel_auth_drivers_fluent_remember']['value']; + $cookie = Cookie::get('laravel_auth_drivers_fluent_remember'); $cookie = explode('|', Crypter::decrypt($cookie)); $this->assertEquals(1, $cookie[0]); $this->assertEquals('foo', Cookie::$jar['laravel_auth_drivers_fluent_remember']['path']); diff --git a/laravel/tests/cases/cookie.test.php b/laravel/tests/cases/cookie.test.php index f62f7857..e17070b0 100644 --- a/laravel/tests/cases/cookie.test.php +++ b/laravel/tests/cases/cookie.test.php @@ -67,7 +67,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { */ public function testHasMethodIndicatesIfCookieInSet() { - Cookie::$jar['foo'] = array('value' => 'bar'); + Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar'); $this->assertTrue(Cookie::has('foo')); $this->assertFalse(Cookie::has('bar')); @@ -82,7 +82,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { */ public function testGetMethodCanReturnValueOfCookies() { - Cookie::$jar['foo'] = array('value' => 'bar'); + Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar'); $this->assertEquals('bar', Cookie::get('foo')); Cookie::put('bar', 'baz'); @@ -97,7 +97,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { public function testForeverShouldUseATonOfMinutes() { Cookie::forever('foo', 'bar'); - $this->assertEquals('bar', Cookie::$jar['foo']['value']); + $this->assertEquals(sha1('bar'.Config::get('application.key')).'+bar', Cookie::$jar['foo']['value']); // Shouldn't be able to test this cause while we indicate -2000 seconds // cookie expiration store timestamp. diff --git a/laravel/tests/cases/session.test.php b/laravel/tests/cases/session.test.php index cf6946a7..b46b5ba0 100644 --- a/laravel/tests/cases/session.test.php +++ b/laravel/tests/cases/session.test.php @@ -372,7 +372,7 @@ class SessionTest extends PHPUnit_Framework_TestCase { $cookie = Cookie::$jar[Config::get('session.cookie')]; - $this->assertEquals('foo', $cookie['value']); + $this->assertEquals(sha1('foo'.Config::get('application.key')).'+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']); From ad313198dfe046aea88b490db0253b25afef7e92 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 25 Sep 2012 08:40:29 -0500 Subject: [PATCH 33/35] working on cookie fingerprinting. --- laravel/cookie.php | 42 ++++++++++++++++++++++++++-- laravel/tests/cases/auth.test.php | 2 +- laravel/tests/cases/cookie.test.php | 6 ++-- laravel/tests/cases/session.test.php | 2 +- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/laravel/cookie.php b/laravel/cookie.php index 1c3b5873..21c67bb7 100644 --- a/laravel/cookie.php +++ b/laravel/cookie.php @@ -44,9 +44,14 @@ class Cookie { */ public static function get($name, $default = null) { - if (isset(static::$jar[$name])) return static::$jar[$name]['value']; + if (isset(static::$jar[$name])) return static::parse(static::$jar[$name]['value']); - return array_get(Request::foundation()->cookies->all(), $name, $default); + if ( ! is_null($value = Request::foundation()->cookies->get($name))) + { + return static::parse($value); + } + + return value($default); } /** @@ -75,6 +80,8 @@ class Cookie { $expiration = time() + ($expiration * 60); } + $value = sha1($value.Config::get('application.key')).'+'.$value; + // 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 insecure HTTP. @@ -120,4 +127,35 @@ class Cookie { return static::put($name, null, -2000, $path, $domain, $secure); } + /** + * Parse a hash fingerprinted cookie value. + * + * @param string $value + * @return string + */ + protected static function parse($value) + { + $segments = explode('+', $value); + + // First we will make sure the cookie actually has enough segments to even + // be valid as being set by the application. If it does not we will go + // ahead and throw exceptions now since there the cookie is invalid. + if ( ! (count($segments) >= 2)) + { + throw new \Exception("Cookie was not set by application."); + } + + $value = implode('+', array_slice($segments, 1)); + + // Now we will check if the SHA-1 hash present in the first segment matches + // the ShA-1 hash of the rest of the cookie value, since the hash should + // have been set when the cookie was first created by the application. + if ($segments[0] == sha1($value.Config::get('application.key'))) + { + return $value; + } + + throw new \Exception("Cookie has been modified by client."); + } + } diff --git a/laravel/tests/cases/auth.test.php b/laravel/tests/cases/auth.test.php index 16ba428a..44ff671e 100644 --- a/laravel/tests/cases/auth.test.php +++ b/laravel/tests/cases/auth.test.php @@ -269,7 +269,7 @@ class AuthTest extends PHPUnit_Framework_TestCase { $this->assertTrue(isset(Cookie::$jar['laravel_auth_drivers_fluent_remember'])); - $cookie = Cookie::$jar['laravel_auth_drivers_fluent_remember']['value']; + $cookie = Cookie::get('laravel_auth_drivers_fluent_remember'); $cookie = explode('|', Crypter::decrypt($cookie)); $this->assertEquals(1, $cookie[0]); $this->assertEquals('foo', Cookie::$jar['laravel_auth_drivers_fluent_remember']['path']); diff --git a/laravel/tests/cases/cookie.test.php b/laravel/tests/cases/cookie.test.php index f62f7857..e17070b0 100644 --- a/laravel/tests/cases/cookie.test.php +++ b/laravel/tests/cases/cookie.test.php @@ -67,7 +67,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { */ public function testHasMethodIndicatesIfCookieInSet() { - Cookie::$jar['foo'] = array('value' => 'bar'); + Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar'); $this->assertTrue(Cookie::has('foo')); $this->assertFalse(Cookie::has('bar')); @@ -82,7 +82,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { */ public function testGetMethodCanReturnValueOfCookies() { - Cookie::$jar['foo'] = array('value' => 'bar'); + Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar'); $this->assertEquals('bar', Cookie::get('foo')); Cookie::put('bar', 'baz'); @@ -97,7 +97,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { public function testForeverShouldUseATonOfMinutes() { Cookie::forever('foo', 'bar'); - $this->assertEquals('bar', Cookie::$jar['foo']['value']); + $this->assertEquals(sha1('bar'.Config::get('application.key')).'+bar', Cookie::$jar['foo']['value']); // Shouldn't be able to test this cause while we indicate -2000 seconds // cookie expiration store timestamp. diff --git a/laravel/tests/cases/session.test.php b/laravel/tests/cases/session.test.php index cf6946a7..b46b5ba0 100644 --- a/laravel/tests/cases/session.test.php +++ b/laravel/tests/cases/session.test.php @@ -372,7 +372,7 @@ class SessionTest extends PHPUnit_Framework_TestCase { $cookie = Cookie::$jar[Config::get('session.cookie')]; - $this->assertEquals('foo', $cookie['value']); + $this->assertEquals(sha1('foo'.Config::get('application.key')).'+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']); From 04f22f086d45aea006260711ea73381f5620934e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 25 Sep 2012 08:42:03 -0500 Subject: [PATCH 34/35] Update change log. --- laravel/documentation/changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/laravel/documentation/changes.md b/laravel/documentation/changes.md index d9b0ff41..013eb948 100644 --- a/laravel/documentation/changes.md +++ b/laravel/documentation/changes.md @@ -45,6 +45,7 @@ ## Laravel 3.2.8 - Fix double slash bug in URLs when using languages and no "index.php". +- Fix possible security issue in Auth "remember me" cookies. ### Upgrading From 3.2.7 From 4eac00a009cb9c8188be2948fe684ebb66c2550a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 25 Sep 2012 16:43:58 -0400 Subject: [PATCH 35/35] Use hash_hmac on cookie hashes. --- laravel/cookie.php | 19 +++++++++++++++---- laravel/tests/cases/cookie.test.php | 6 +++--- laravel/tests/cases/session.test.php | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/laravel/cookie.php b/laravel/cookie.php index 21c67bb7..56077ff7 100644 --- a/laravel/cookie.php +++ b/laravel/cookie.php @@ -80,7 +80,7 @@ class Cookie { $expiration = time() + ($expiration * 60); } - $value = sha1($value.Config::get('application.key')).'+'.$value; + $value = static::hash($value).'+'.$value; // 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 @@ -127,6 +127,17 @@ class Cookie { return static::put($name, null, -2000, $path, $domain, $secure); } + /** + * Hash the given cookie value. + * + * @param string $value + * @return string + */ + public static function hash($value) + { + return hash_hmac('sha1', $value, Config::get('application.key')); + } + /** * Parse a hash fingerprinted cookie value. * @@ -142,7 +153,7 @@ class Cookie { // ahead and throw exceptions now since there the cookie is invalid. if ( ! (count($segments) >= 2)) { - throw new \Exception("Cookie was not set by application."); + return null; } $value = implode('+', array_slice($segments, 1)); @@ -150,12 +161,12 @@ class Cookie { // Now we will check if the SHA-1 hash present in the first segment matches // the ShA-1 hash of the rest of the cookie value, since the hash should // have been set when the cookie was first created by the application. - if ($segments[0] == sha1($value.Config::get('application.key'))) + if ($segments[0] == static::hash($value)) { return $value; } - throw new \Exception("Cookie has been modified by client."); + return null; } } diff --git a/laravel/tests/cases/cookie.test.php b/laravel/tests/cases/cookie.test.php index e17070b0..37d63553 100644 --- a/laravel/tests/cases/cookie.test.php +++ b/laravel/tests/cases/cookie.test.php @@ -67,7 +67,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { */ public function testHasMethodIndicatesIfCookieInSet() { - Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar'); + Cookie::$jar['foo'] = array('value' => Cookie::hash('bar').'+bar'); $this->assertTrue(Cookie::has('foo')); $this->assertFalse(Cookie::has('bar')); @@ -82,7 +82,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { */ public function testGetMethodCanReturnValueOfCookies() { - Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar'); + Cookie::$jar['foo'] = array('value' => Cookie::hash('bar').'+bar'); $this->assertEquals('bar', Cookie::get('foo')); Cookie::put('bar', 'baz'); @@ -97,7 +97,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { public function testForeverShouldUseATonOfMinutes() { Cookie::forever('foo', 'bar'); - $this->assertEquals(sha1('bar'.Config::get('application.key')).'+bar', Cookie::$jar['foo']['value']); + $this->assertEquals(Cookie::hash('bar').'+bar', Cookie::$jar['foo']['value']); // Shouldn't be able to test this cause while we indicate -2000 seconds // cookie expiration store timestamp. diff --git a/laravel/tests/cases/session.test.php b/laravel/tests/cases/session.test.php index b46b5ba0..f93ce9b1 100644 --- a/laravel/tests/cases/session.test.php +++ b/laravel/tests/cases/session.test.php @@ -372,7 +372,7 @@ class SessionTest extends PHPUnit_Framework_TestCase { $cookie = Cookie::$jar[Config::get('session.cookie')]; - $this->assertEquals(sha1('foo'.Config::get('application.key')).'+foo', $cookie['value']); + $this->assertEquals(Cookie::hash('foo').'+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']);