diff --git a/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php b/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php
index aee2f6cc7..77629ee39 100644
--- a/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php
+++ b/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php
@@ -27,6 +27,7 @@ abstract class BaseAuthenticate {
*
* - `fields` The fields to use to identify a user by.
* - `userModel` The model name of the User, defaults to User.
+ * - `userFields` Array of fields to retrieve from User model, null to retrieve all. Defaults to null.
* - `scope` Additional conditions to use when looking up and authenticating users,
* i.e. `array('User.is_active' => 1).`
* - `recursive` The value of the recursive key passed to find(). Defaults to 0.
@@ -43,6 +44,7 @@ abstract class BaseAuthenticate {
'password' => 'password'
),
'userModel' => 'User',
+ 'userFields' => null,
'scope' => array(),
'recursive' => 0,
'contain' => null,
@@ -105,9 +107,15 @@ abstract class BaseAuthenticate {
$conditions = array_merge($conditions, $this->settings['scope']);
}
+ $userFields = $this->settings['userFields'];
+ if ($password !== null && $userFields !== null) {
+ $userFields[] = $model . '.' . $fields['password'];
+ }
+
$result = ClassRegistry::init($userModel)->find('first', array(
'conditions' => $conditions,
'recursive' => $this->settings['recursive'],
+ 'fields' => $userFields,
'contain' => $this->settings['contain'],
));
if (empty($result[$model])) {
diff --git a/lib/Cake/Controller/Component/Auth/DigestAuthenticate.php b/lib/Cake/Controller/Component/Auth/DigestAuthenticate.php
index c40f4096d..068a7c09c 100644
--- a/lib/Cake/Controller/Component/Auth/DigestAuthenticate.php
+++ b/lib/Cake/Controller/Component/Auth/DigestAuthenticate.php
@@ -60,6 +60,7 @@ class DigestAuthenticate extends BasicAuthenticate {
*
* - `fields` The fields to use to identify a user by.
* - `userModel` The model name of the User, defaults to User.
+ * - `userFields` Array of fields to retrieve from User model, null to retrieve all. Defaults to null.
* - `scope` Additional conditions to use when looking up and authenticating users,
* i.e. `array('User.is_active' => 1).`
* - `recursive` The value of the recursive key passed to find(). Defaults to 0.
@@ -78,6 +79,7 @@ class DigestAuthenticate extends BasicAuthenticate {
'password' => 'password'
),
'userModel' => 'User',
+ 'userFields' => null,
'scope' => array(),
'recursive' => 0,
'contain' => null,
diff --git a/lib/Cake/Test/Case/Controller/Component/Auth/BasicAuthenticateTest.php b/lib/Cake/Test/Case/Controller/Component/Auth/BasicAuthenticateTest.php
index cd337cf08..c4402a7f7 100644
--- a/lib/Cake/Test/Case/Controller/Component/Auth/BasicAuthenticateTest.php
+++ b/lib/Cake/Test/Case/Controller/Component/Auth/BasicAuthenticateTest.php
@@ -36,7 +36,7 @@ class BasicAuthenticateTest extends CakeTestCase {
*
* @var array
*/
- public $fixtures = array('core.user', 'core.auth_user');
+ public $fixtures = array('core.user', 'core.auth_user', 'core.article');
/**
* setup
@@ -197,6 +197,80 @@ class BasicAuthenticateTest extends CakeTestCase {
$this->assertEquals($expected, $result);
}
+/**
+ * test contain success
+ *
+ * @return void
+ */
+ public function testAuthenticateContainSuccess() {
+ $User = ClassRegistry::init('User');
+ $User->bindModel(array('hasMany' => array('Article')));
+ $User->Behaviors->load('Containable');
+ $this->auth->settings['contain'] = 'Article';
+ $request = new CakeRequest('posts/index', false);
+ $request->addParams(array('pass' => array(), 'named' => array()));
+
+ $_SERVER['PHP_AUTH_USER'] = 'mariano';
+ $_SERVER['PHP_AUTH_PW'] = 'password';
+
+ $result = $this->auth->authenticate($request, $this->response);
+ $expected = array(
+ 'id' => 1,
+ 'user_id' => 1,
+ 'title' => 'First Article',
+ 'body' => 'First Article Body',
+ 'published' => 'Y',
+ 'created' => '2007-03-18 10:39:23',
+ 'updated' => '2007-03-18 10:41:31'
+ );
+ $this->assertEquals($expected, $result['Article'][0]);
+ }
+
+/**
+ * test userFields success
+ *
+ * @return void
+ */
+ public function testAuthenticateUserFieldsSuccess() {
+ $this->auth->settings['userFields'] = array('id', 'user');
+ $request = new CakeRequest('posts/index', false);
+ $request->addParams(array('pass' => array(), 'named' => array()));
+
+ $_SERVER['PHP_AUTH_USER'] = 'mariano';
+ $_SERVER['PHP_AUTH_PW'] = 'password';
+
+ $result = $this->auth->authenticate($request, $this->response);
+ $expected = array(
+ 'id' => 1,
+ 'user' => 'mariano',
+ );
+ $this->assertEquals($expected, $result);
+ }
+
+/**
+ * test userFields and related models success
+ *
+ * @return void
+ */
+ public function testAuthenticateUserFieldsRelatedModelsSuccess() {
+ $User = ClassRegistry::init('User');
+ $User->bindModel(array('hasOne' => array('Article')));
+ $this->auth->settings['recursive'] = 0;
+ $this->auth->settings['userFields'] = array('Article.id', 'Article.title');
+ $request = new CakeRequest('posts/index', false);
+ $request->addParams(array('pass' => array(), 'named' => array()));
+
+ $_SERVER['PHP_AUTH_USER'] = 'mariano';
+ $_SERVER['PHP_AUTH_PW'] = 'password';
+
+ $result = $this->auth->authenticate($request, $this->response);
+ $expected = array(
+ 'id' => 1,
+ 'title' => 'First Article',
+ );
+ $this->assertEquals($expected, $result['Article']);
+ }
+
/**
* test scope failure.
*
diff --git a/lib/Cake/Test/Case/View/Helper/PaginatorHelperTest.php b/lib/Cake/Test/Case/View/Helper/PaginatorHelperTest.php
index bbada6605..eb574b63e 100644
--- a/lib/Cake/Test/Case/View/Helper/PaginatorHelperTest.php
+++ b/lib/Cake/Test/Case/View/Helper/PaginatorHelperTest.php
@@ -2763,4 +2763,110 @@ class PaginatorHelperTest extends CakeTestCase {
$expected = '0 of 1';
$this->assertEquals($expected, $result);
}
+
+/**
+ * Verify that no next and prev links are created for single page results
+ *
+ * @return void
+ */
+ public function testMetaPage0() {
+ $this->Paginator->request['paging'] = array(
+ 'Article' => array(
+ 'page' => 1,
+ 'prevPage' => false,
+ 'nextPage' => false,
+ 'pageCount' => 1,
+ )
+ );
+ $expected = '';
+ $result = $this->Paginator->meta();
+ $this->assertSame($expected, $result);
+ }
+
+/**
+ * Verify that page 1 only has a next link
+ *
+ * @return void
+ */
+ public function testMetaPage1() {
+ $this->Paginator->request['paging'] = array(
+ 'Article' => array(
+ 'page' => 1,
+ 'prevPage' => false,
+ 'nextPage' => true,
+ 'pageCount' => 2,
+ 'options' => array(),
+ 'paramType' => 'querystring'
+ )
+ );
+ $expected = '';
+ $result = $this->Paginator->meta();
+ $this->assertSame($expected, $result);
+ }
+
+/**
+ * Verify that the method will append to a block
+ *
+ * @return void
+ */
+ public function testMetaPage1InlineFalse() {
+ $this->Paginator->request['paging'] = array(
+ 'Article' => array(
+ 'page' => 1,
+ 'prevPage' => false,
+ 'nextPage' => true,
+ 'pageCount' => 2,
+ 'options' => array(),
+ 'paramType' => 'querystring'
+ )
+ );
+ $expected = '';
+ $this->Paginator->meta(array('block' => true));
+ $result = $this->View->fetch('meta');
+ $this->assertSame($expected, $result);
+ }
+
+/**
+ * Verify that the last page only has a prev link
+ *
+ * @return void
+ */
+ public function testMetaPage1Last() {
+ $this->Paginator->request['paging'] = array(
+ 'Article' => array(
+ 'page' => 2,
+ 'prevPage' => true,
+ 'nextPage' => false,
+ 'pageCount' => 2,
+ 'options' => array(),
+ 'paramType' => 'querystring'
+ )
+ );
+ $expected = '';
+ $result = $this->Paginator->meta();
+ $this->assertSame($expected, $result);
+ }
+
+/**
+ * Verify that a page in the middle has both links
+ *
+ * @return void
+ */
+ public function testMetaPage10Last() {
+ $this->Paginator->request['paging'] = array(
+ 'Article' => array(
+ 'page' => 5,
+ 'prevPage' => true,
+ 'nextPage' => true,
+ 'pageCount' => 10,
+ 'options' => array(),
+ 'paramType' => 'querystring'
+ )
+ );
+ $expected = '';
+ $expected .= '';
+ $result = $this->Paginator->meta();
+ $this->assertSame($expected, $result);
+ }
+
}
diff --git a/lib/Cake/View/Helper/PaginatorHelper.php b/lib/Cake/View/Helper/PaginatorHelper.php
index ccbcc4794..43c29a14f 100644
--- a/lib/Cake/View/Helper/PaginatorHelper.php
+++ b/lib/Cake/View/Helper/PaginatorHelper.php
@@ -958,4 +958,50 @@ class PaginatorHelper extends AppHelper {
return $out;
}
+/**
+ * Returns the meta-links for a paginated result set.
+ *
+ * `echo $this->Paginator->meta();`
+ *
+ * Echos the links directly, will output nothing if there is neither a previous nor next page.
+ *
+ * `$this->Paginator->meta(array('block' => true));`
+ *
+ * Will append the output of the meta function to the named block - if true is passed the "meta"
+ * block is used.
+ *
+ * ### Options:
+ *
+ * - `model` The model to use defaults to PaginatorHelper::defaultModel()
+ * - `block` The block name to append the output to, or false/absenst to return as a string
+ *
+ * @param array $options Array of options
+ * @return string|null Meta links
+ */
+ public function meta($options = array()) {
+ $model = isset($options['model']) ? $options['model'] : null;
+ $params = $this->params($model);
+ $links = array();
+ if ($this->hasPrev()) {
+ $links[] = $this->Html->meta(array(
+ 'rel' => 'prev',
+ 'link' => $this->url(array('page' => $params['page'] - 1), true)
+ ));
+ }
+ if ($this->hasNext()) {
+ $links[] = $this->Html->meta(array(
+ 'rel' => 'next',
+ 'link' => $this->url(array('page' => $params['page'] + 1), true)
+ ));
+ }
+ $out = implode($links);
+ if (empty($options['block'])) {
+ return $out;
+ }
+ if ($options['block'] === true) {
+ $options['block'] = __FUNCTION__;
+ }
+ $this->_View->append($options['block'], $out);
+ }
+
}