LDAP: put out fetching of user meta data into a fully tested class of its own and update them (mail, quota, etc.) directly after mapping. Fixes #7785 properly on master
parent
d3e830e938
commit
6d64d7ec3f
@ -0,0 +1,46 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP FilesystemHelper |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2014 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib; |
||||
|
||||
/** |
||||
* @brief wraps around static ownCloud core methods |
||||
*/ |
||||
class FilesystemHelper { |
||||
|
||||
/** |
||||
* @brief states whether the filesystem was loaded |
||||
* @return bool |
||||
*/ |
||||
public function isLoaded() { |
||||
return \OC\Files\Filesystem::$loaded; |
||||
} |
||||
|
||||
/** |
||||
* @brief initializes the filesystem for the given user |
||||
* @param string the ownCloud username of the user |
||||
*/ |
||||
public function setup($uid) { |
||||
\OC_Util::setupFS($uid); |
||||
} |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP LogWrapper |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2014 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib; |
||||
|
||||
/** |
||||
* @brief wraps around static ownCloud core methods |
||||
*/ |
||||
class LogWrapper { |
||||
protected $app = 'user_ldap'; |
||||
|
||||
/** |
||||
* @brief states whether the filesystem was loaded |
||||
* @return bool |
||||
*/ |
||||
public function log($msg, $level) { |
||||
\OCP\Util::writeLog($this->app, $msg, $level); |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP User |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2014 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib\user; |
||||
|
||||
interface IUserTools { |
||||
public function getConnection(); |
||||
|
||||
public function readAttribute($dn, $attr, $filter = 'objectClass=*'); |
||||
|
||||
public function dn2username($dn, $ldapname = null); |
||||
|
||||
public function username2dn($name); |
||||
|
||||
} |
||||
@ -0,0 +1,161 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP User |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2014 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib\user; |
||||
|
||||
use OCA\user_ldap\lib\user\IUserTools; |
||||
use OCA\user_ldap\lib\user\User; |
||||
use OCA\user_ldap\lib\LogWrapper; |
||||
use OCA\user_ldap\lib\FilesystemHelper; |
||||
|
||||
class Manager { |
||||
/** |
||||
* @var IUserTools |
||||
*/ |
||||
protected $access; |
||||
/** |
||||
* @var \OCP\IConfig |
||||
*/ |
||||
protected $ocConfig; |
||||
/** |
||||
* @var FilesystemHelper |
||||
*/ |
||||
protected $ocFilesystem; |
||||
/** |
||||
* @var LogWrapper |
||||
*/ |
||||
protected $ocLog; |
||||
/** |
||||
* @var \OCP\Image |
||||
*/ |
||||
protected $image; |
||||
/** |
||||
* @param \OCP\IAvatarManager |
||||
*/ |
||||
protected $avatarManager; |
||||
/** |
||||
* @var string[][] |
||||
*/ |
||||
protected $users = array( |
||||
'byDN' => array(), |
||||
'byUid' => array(), |
||||
); |
||||
|
||||
/** |
||||
* @brief Constructor |
||||
* @param \OCP\IConfig respectively an instance that provides the methods |
||||
* setUserValue and getUserValue as implemented in \OCP\Config |
||||
* @param \OCA\user_ldap\lib\FilesystemHelper object that gives access to |
||||
* necessary functions from the OC filesystem |
||||
* @param \OCA\user_ldap\lib\LogWrapper |
||||
* @param \OCP\IAvatarManager |
||||
* @param \OCP\Image an empty image instance |
||||
* @throws Exception when the methods mentioned above do not exist |
||||
*/ |
||||
public function __construct(\OCP\IConfig $ocConfig, |
||||
FilesystemHelper $ocFilesystem, LogWrapper $ocLog, |
||||
\OCP\IAvatarManager $avatarManager, \OCP\Image $image) { |
||||
|
||||
if(!method_exists($ocConfig, 'setUserValue') |
||||
|| !method_exists($ocConfig, 'getUserValue')) { |
||||
throw new \Exception('Invalid ownCloud User Config object'); |
||||
} |
||||
$this->ocConfig = $ocConfig; |
||||
$this->ocFilesystem = $ocFilesystem; |
||||
$this->ocLog = $ocLog; |
||||
$this->avatarManager = $avatarManager; |
||||
$this->image = $image; |
||||
} |
||||
|
||||
/** |
||||
* @brief binds manager to an instance of IUserTools (implemented by |
||||
* Access). It needs to be assigned first before the manager can be used. |
||||
* @param IUserTools |
||||
*/ |
||||
public function setLdapAccess(IUserTools $access) { |
||||
$this->access = $access; |
||||
} |
||||
|
||||
/** |
||||
* @brief creates an instance of User and caches (just runtime) it in the |
||||
* property array |
||||
* @param string the DN of the user |
||||
* @param string the internal (owncloud) username |
||||
* @return \OCA\user_ldap\lib\User |
||||
*/ |
||||
private function createAndCache($dn, $uid) { |
||||
$this->checkAccess(); |
||||
$user = new User($uid, $dn, $this->access, $this->ocConfig, |
||||
$this->ocFilesystem, clone $this->image, $this->ocLog, |
||||
$this->avatarManager); |
||||
$users['byDN'][$dn] = $user; |
||||
$users['byUid'][$uid] = $user; |
||||
return $user; |
||||
} |
||||
|
||||
/** |
||||
* @brief checks whether the Access instance has been set |
||||
* @throws Exception if Access has not been set |
||||
* @return null |
||||
*/ |
||||
private function checkAccess() { |
||||
if(is_null($this->access)) { |
||||
throw new \Exception('LDAP Access instance must be set first'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief returns a User object by it's DN or ownCloud username |
||||
* @param string the DN or username of the user |
||||
* @return \OCA\user_ldap\lib\User | null |
||||
*/ |
||||
public function get($id) { |
||||
$this->checkAccess(); |
||||
if(isset($this->users['byDN'][$id])) { |
||||
return $this->users['byDN'][$id]; |
||||
} else if(isset($this->users['byUid'][$id])) { |
||||
return $this->users['byUid'][$id]; |
||||
} |
||||
|
||||
if(strpos($id, 'dc=') === false) { |
||||
//most likely a uid |
||||
$dn = $this->access->username2dn($id); |
||||
if($dn !== false) { |
||||
return $this->createAndCache($dn, $id); |
||||
} |
||||
} else { |
||||
//so it's a DN |
||||
$uid = $this->access->dn2username($id); |
||||
if($uid !== false) { |
||||
return $this->createAndCache($id, $uid); |
||||
} |
||||
} |
||||
//either funny uid or invalid. Assume funny to be on the safe side. |
||||
$dn = $this->access->username2dn($id); |
||||
if($dn !== false) { |
||||
return $this->createAndCache($dn, $id); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,320 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP User |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2014 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib\user; |
||||
|
||||
use OCA\user_ldap\lib\user\IUserTools; |
||||
use OCA\user_ldap\lib\Connection; |
||||
use OCA\user_ldap\lib\FilesystemHelper; |
||||
use OCA\user_ldap\lib\LogWrapper; |
||||
|
||||
class User { |
||||
/** |
||||
* @var IUserTools |
||||
*/ |
||||
protected $access; |
||||
/** |
||||
* @var Connection |
||||
*/ |
||||
protected $connection; |
||||
/** |
||||
* @var \OCP\IConfig |
||||
*/ |
||||
protected $config; |
||||
/** |
||||
* @var FilesystemHelper |
||||
*/ |
||||
protected $fs; |
||||
/** |
||||
* @var \OCP\Image |
||||
*/ |
||||
protected $image; |
||||
/** |
||||
* @var LogWrapper |
||||
*/ |
||||
protected $log; |
||||
/** |
||||
* @var \OCP\IAvatarManager |
||||
*/ |
||||
protected $avatarManager; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $dn; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $uid; |
||||
/** |
||||
* @var string[] |
||||
*/ |
||||
protected $refreshedFeatures = array(); |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $avatarImage; |
||||
|
||||
/** |
||||
* DB config keys for user preferences |
||||
*/ |
||||
const USER_PREFKEY_FIRSTLOGIN = 'firstLoginAccomplished'; |
||||
const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh'; |
||||
|
||||
/** |
||||
* @brief constructor, make sure the subclasses call this one! |
||||
* @param string the internal username |
||||
* @param string the LDAP DN |
||||
* @param IUserTools $access an instance that implements IUserTools for |
||||
* LDAP interaction |
||||
* @param \OCP\Config |
||||
* @param FilesystemHelper |
||||
* @param \OCP\Image any empty instance |
||||
* @param LogWrapper |
||||
* @param \OCP\IAvatarManager |
||||
*/ |
||||
public function __construct($username, $dn, IUserTools $access, |
||||
\OCP\IConfig $config, FilesystemHelper $fs, \OCP\Image $image, |
||||
LogWrapper $log, \OCP\IAvatarManager $avatarManager) { |
||||
|
||||
$this->access = $access; |
||||
$this->connection = $access->getConnection(); |
||||
$this->config = $config; |
||||
$this->fs = $fs; |
||||
$this->dn = $dn; |
||||
$this->uid = $username; |
||||
$this->image = $image; |
||||
$this->log = $log; |
||||
$this->avatarManager = $avatarManager; |
||||
} |
||||
|
||||
/** |
||||
* @brief updates properties like email, quota or avatar provided by LDAP |
||||
* @return null |
||||
*/ |
||||
public function update() { |
||||
if(is_null($this->dn)) { |
||||
return null; |
||||
} |
||||
|
||||
$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap', |
||||
self::USER_PREFKEY_FIRSTLOGIN, 0); |
||||
|
||||
if($this->needsRefresh()) { |
||||
$this->updateEmail(); |
||||
$this->updateQuota(); |
||||
if($hasLoggedIn !== 0) { |
||||
//we do not need to try it, when the user has not been logged in |
||||
//before, because the file system will not be ready. |
||||
$this->updateAvatar(); |
||||
//in order to get an avatar as soon as possible, mark the user |
||||
//as refreshed only when updating the avatar did happen |
||||
$this->markRefreshTime(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief returns the LDAP DN of the user |
||||
* @return string |
||||
*/ |
||||
public function getDN() { |
||||
return $this->dn; |
||||
} |
||||
|
||||
/** |
||||
* @brief returns the ownCloud internal username of the user |
||||
* @return string |
||||
*/ |
||||
public function getUsername() { |
||||
return $this->uid; |
||||
} |
||||
|
||||
/** |
||||
* @brief reads the image from LDAP that shall be used as Avatar |
||||
* @return string data (provided by LDAP) | false |
||||
*/ |
||||
public function getAvatarImage() { |
||||
if(!is_null($this->avatarImage)) { |
||||
return $this->avatarImage; |
||||
} |
||||
|
||||
$this->avatarImage = false; |
||||
$attributes = array('jpegPhoto', 'thumbnailPhoto'); |
||||
foreach($attributes as $attribute) { |
||||
$result = $this->access->readAttribute($this->dn, $attribute); |
||||
if($result !== false && is_array($result) && isset($result[0])) { |
||||
$this->avatarImage = $result[0]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return $this->avatarImage; |
||||
} |
||||
|
||||
/** |
||||
* @brief marks the user as having logged in at least once |
||||
* @return null |
||||
*/ |
||||
public function markLogin() { |
||||
$this->config->setUserValue( |
||||
$this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1); |
||||
} |
||||
|
||||
/** |
||||
* @brief marks the time when user features like email have been updated |
||||
* @return null |
||||
*/ |
||||
private function markRefreshTime() { |
||||
$this->config->setUserValue( |
||||
$this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time()); |
||||
} |
||||
|
||||
/** |
||||
* @brief checks whether user features needs to be updated again by |
||||
* comparing the difference of time of the last refresh to now with the |
||||
* desired interval |
||||
* @return bool |
||||
*/ |
||||
private function needsRefresh() { |
||||
$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap', |
||||
self::USER_PREFKEY_LASTREFRESH, 0); |
||||
|
||||
//TODO make interval configurable |
||||
if((time() - intval($lastChecked)) < 86400 ) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @brief checks whether an update method specified by feature was run |
||||
* already. If not, it will marked like this, because it is expected that |
||||
* the method will be run, when false is returned. |
||||
* @param string email | quota | avatar (can be extended) |
||||
* @return bool |
||||
*/ |
||||
private function wasRefreshed($feature) { |
||||
if(isset($this->refreshedFeatures[$feature])) { |
||||
return true; |
||||
} |
||||
$this->refreshedFeatures[$feature] = 1; |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @brief fetches the email from LDAP and stores it as ownCloud user value |
||||
* @return null |
||||
*/ |
||||
public function updateEmail() { |
||||
if($this->wasRefreshed('email')) { |
||||
return; |
||||
} |
||||
|
||||
$email = null; |
||||
$emailAttribute = $this->connection->ldapEmailAttribute; |
||||
if(!empty($emailAttribute)) { |
||||
$aEmail = $this->access->readAttribute($this->dn, $emailAttribute); |
||||
if($aEmail && (count($aEmail) > 0)) { |
||||
$email = $aEmail[0]; |
||||
} |
||||
if(!is_null($email)) { |
||||
$this->config->setUserValue( |
||||
$this->uid, 'settings', 'email', $email); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief fetches the quota from LDAP and stores it as ownCloud user value |
||||
* @return null |
||||
*/ |
||||
public function updateQuota() { |
||||
if($this->wasRefreshed('quota')) { |
||||
return; |
||||
} |
||||
|
||||
$quota = null; |
||||
$quotaDefault = $this->connection->ldapQuotaDefault; |
||||
$quotaAttribute = $this->connection->ldapQuotaAttribute; |
||||
if(!empty($quotaDefault)) { |
||||
$quota = $quotaDefault; |
||||
} |
||||
if(!empty($quotaAttribute)) { |
||||
$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute); |
||||
|
||||
if($aQuota && (count($aQuota) > 0)) { |
||||
$quota = $aQuota[0]; |
||||
} |
||||
} |
||||
if(!is_null($quota)) { |
||||
$this->config->setUserValue($this->uid, 'files', 'quota', |
||||
\OCP\Util::computerFileSize($quota)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief attempts to get an image from LDAP and sets it as ownCloud avatar |
||||
* @return null |
||||
*/ |
||||
public function updateAvatar() { |
||||
if($this->wasRefreshed('avatar')) { |
||||
return; |
||||
} |
||||
$avatarImage = $this->getAvatarImage(); |
||||
if($avatarImage === false) { |
||||
//not set, nothing left to do; |
||||
return; |
||||
} |
||||
$this->image->loadFromBase64(base64_encode($avatarImage)); |
||||
$this->setOwnCloudAvatar(); |
||||
} |
||||
|
||||
/** |
||||
* @brief sets an image as ownCloud avatar |
||||
* @return null |
||||
*/ |
||||
private function setOwnCloudAvatar() { |
||||
if(!$this->image->valid()) { |
||||
$this->log->log('user_ldap', 'jpegPhoto data invalid for '.$this->dn, |
||||
\OCP\Util::ERROR); |
||||
return; |
||||
} |
||||
//make sure it is a square and not bigger than 128x128 |
||||
$size = min(array($this->image->width(), $this->image->height(), 128)); |
||||
if(!$this->image->centerCrop($size)) { |
||||
$this->log->log('user_ldap', |
||||
'croping image for avatar failed for '.$this->dn, |
||||
\OCP\Util::ERROR); |
||||
return; |
||||
} |
||||
|
||||
if(!$this->fs->isLoaded()) { |
||||
$this->fs->setup($this->uid); |
||||
} |
||||
|
||||
$avatar = $this->avatarManager->getAvatar($this->uid); |
||||
$avatar->set($this->image); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,680 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2014 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\tests; |
||||
|
||||
use OCA\user_ldap\lib\user\User; |
||||
|
||||
class Test_User_User extends \PHPUnit_Framework_TestCase { |
||||
|
||||
private function getTestInstances() { |
||||
$access = $this->getMock('\OCA\user_ldap\lib\user\IUserTools'); |
||||
$config = $this->getMock('\OCP\IConfig'); |
||||
$filesys = $this->getMock('\OCA\user_ldap\lib\FilesystemHelper'); |
||||
$log = $this->getMock('\OCA\user_ldap\lib\LogWrapper'); |
||||
$avaMgr = $this->getMock('\OCP\IAvatarManager'); |
||||
$image = $this->getMock('\OCP\Image'); |
||||
|
||||
return array($access, $config, $filesys, $image, $log, $avaMgr); |
||||
} |
||||
|
||||
private function getAdvancedMocks($cfMock, $fsMock, $logMock, $avaMgr) { |
||||
static $conMethods; |
||||
static $accMethods; |
||||
static $umMethods; |
||||
|
||||
if(is_null($conMethods) || is_null($accMethods)) { |
||||
$conMethods = get_class_methods('\OCA\user_ldap\lib\Connection'); |
||||
$accMethods = get_class_methods('\OCA\user_ldap\lib\Access'); |
||||
//getConnection shall not be replaced |
||||
unset($accMethods[array_search('getConnection', $accMethods)]); |
||||
$umMethods = get_class_methods('\OCA\user_ldap\lib\user\Manager'); |
||||
} |
||||
$lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); |
||||
$im = $this->getMock('\OCP\Image'); |
||||
$um = $this->getMock('\OCA\user_ldap\lib\user\Manager', |
||||
$umMethods, array($cfMock, $fsMock, $logMock, $avaMgr, $im)); |
||||
$connector = $this->getMock('\OCA\user_ldap\lib\Connection', |
||||
$conMethods, array($lw, null, null)); |
||||
$access = $this->getMock('\OCA\user_ldap\lib\Access', |
||||
$accMethods, array($connector, $lw, $um)); |
||||
|
||||
return array($access, $connector); |
||||
} |
||||
|
||||
public function testGetDNandUsername() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$this->assertSame($dn, $user->getDN()); |
||||
$this->assertSame($uid, $user->getUsername()); |
||||
} |
||||
|
||||
public function testUpdateEmailProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->once()) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapEmailAttribute')) |
||||
->will($this->returnValue('email')); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('email')) |
||||
->will($this->returnValue(array('alice@foo.bar'))); |
||||
|
||||
$config->expects($this->once()) |
||||
->method('setUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('settings'), |
||||
$this->equalTo('email'), |
||||
$this->equalTo('alice@foo.bar')) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateEmail(); |
||||
} |
||||
|
||||
public function testUpdateEmailNotProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->once()) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapEmailAttribute')) |
||||
->will($this->returnValue('email')); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('email')) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$config->expects($this->never()) |
||||
->method('setUserValue'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateEmail(); |
||||
} |
||||
|
||||
public function testUpdateEmailNotConfigured() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->once()) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapEmailAttribute')) |
||||
->will($this->returnValue('')); |
||||
|
||||
$access->expects($this->never()) |
||||
->method('readAttribute'); |
||||
|
||||
$config->expects($this->never()) |
||||
->method('setUserValue'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateEmail(); |
||||
} |
||||
|
||||
public function testUpdateQuotaAllProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->at(0)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaDefault')) |
||||
->will($this->returnValue('23 GB')); |
||||
|
||||
$connection->expects($this->at(1)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaAttribute')) |
||||
->will($this->returnValue('myquota')); |
||||
|
||||
$connection->expects($this->exactly(2)) |
||||
->method('__get'); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('myquota')) |
||||
->will($this->returnValue(array('42 GB'))); |
||||
|
||||
$config->expects($this->once()) |
||||
->method('setUserValue') |
||||
->with($this->equalTo('alice'), |
||||
$this->equalTo('files'), |
||||
$this->equalTo('quota'), |
||||
$this->equalTo(\OCP\Util::computerFileSize('42 GB'))) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateQuota(); |
||||
} |
||||
|
||||
public function testUpdateQuotaDefaultProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->at(0)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaDefault')) |
||||
->will($this->returnValue('23 GB')); |
||||
|
||||
$connection->expects($this->at(1)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaAttribute')) |
||||
->will($this->returnValue('myquota')); |
||||
|
||||
$connection->expects($this->exactly(2)) |
||||
->method('__get'); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('myquota')) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$config->expects($this->once()) |
||||
->method('setUserValue') |
||||
->with($this->equalTo('alice'), |
||||
$this->equalTo('files'), |
||||
$this->equalTo('quota'), |
||||
$this->equalTo(\OCP\Util::computerFileSize('23 GB'))) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateQuota(); |
||||
} |
||||
|
||||
public function testUpdateQuotaIndividualProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->at(0)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaDefault')) |
||||
->will($this->returnValue('')); |
||||
|
||||
$connection->expects($this->at(1)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaAttribute')) |
||||
->will($this->returnValue('myquota')); |
||||
|
||||
$connection->expects($this->exactly(2)) |
||||
->method('__get'); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('myquota')) |
||||
->will($this->returnValue(array('23 GB'))); |
||||
|
||||
$config->expects($this->once()) |
||||
->method('setUserValue') |
||||
->with($this->equalTo('alice'), |
||||
$this->equalTo('files'), |
||||
$this->equalTo('quota'), |
||||
$this->equalTo(\OCP\Util::computerFileSize('23 GB'))) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateQuota(); |
||||
} |
||||
|
||||
public function testUpdateQuotaNoneProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->at(0)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaDefault')) |
||||
->will($this->returnValue('')); |
||||
|
||||
$connection->expects($this->at(1)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaAttribute')) |
||||
->will($this->returnValue('myquota')); |
||||
|
||||
$connection->expects($this->exactly(2)) |
||||
->method('__get'); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('myquota')) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$config->expects($this->never()) |
||||
->method('setUserValue'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateQuota(); |
||||
} |
||||
|
||||
public function testUpdateQuotaNoneConfigured() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$connection->expects($this->at(0)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaDefault')) |
||||
->will($this->returnValue('')); |
||||
|
||||
$connection->expects($this->at(1)) |
||||
->method('__get') |
||||
->with($this->equalTo('ldapQuotaAttribute')) |
||||
->will($this->returnValue('')); |
||||
|
||||
$connection->expects($this->exactly(2)) |
||||
->method('__get'); |
||||
|
||||
$access->expects($this->never()) |
||||
->method('readAttribute'); |
||||
|
||||
$config->expects($this->never()) |
||||
->method('setUserValue'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateQuota(); |
||||
} |
||||
|
||||
//the testUpdateAvatar series also implicitely tests getAvatarImage |
||||
public function testUpdateAvatarJpegPhotoProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('jpegPhoto')) |
||||
->will($this->returnValue(array('this is a photo'))); |
||||
|
||||
$image->expects($this->once()) |
||||
->method('valid') |
||||
->will($this->returnValue(true)); |
||||
$image->expects($this->once()) |
||||
->method('width') |
||||
->will($this->returnValue(128)); |
||||
$image->expects($this->once()) |
||||
->method('height') |
||||
->will($this->returnValue(128)); |
||||
$image->expects($this->once()) |
||||
->method('centerCrop') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$filesys->expects($this->once()) |
||||
->method('isLoaded') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$avatar = $this->getMock('\OCP\IAvatar'); |
||||
$avatar->expects($this->once()) |
||||
->method('set') |
||||
->with($this->isInstanceOf($image)); |
||||
|
||||
$avaMgr->expects($this->once()) |
||||
->method('getAvatar') |
||||
->with($this->equalTo('alice')) |
||||
->will($this->returnValue($avatar)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateAvatar(); |
||||
} |
||||
|
||||
public function testUpdateAvatarThumbnailPhotoProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$access->expects($this->at(0)) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('jpegPhoto')) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$access->expects($this->at(1)) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('thumbnailPhoto')) |
||||
->will($this->returnValue(array('this is a photo'))); |
||||
|
||||
$access->expects($this->exactly(2)) |
||||
->method('readAttribute'); |
||||
|
||||
$image->expects($this->once()) |
||||
->method('valid') |
||||
->will($this->returnValue(true)); |
||||
$image->expects($this->once()) |
||||
->method('width') |
||||
->will($this->returnValue(128)); |
||||
$image->expects($this->once()) |
||||
->method('height') |
||||
->will($this->returnValue(128)); |
||||
$image->expects($this->once()) |
||||
->method('centerCrop') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$filesys->expects($this->once()) |
||||
->method('isLoaded') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$avatar = $this->getMock('\OCP\IAvatar'); |
||||
$avatar->expects($this->once()) |
||||
->method('set') |
||||
->with($this->isInstanceOf($image)); |
||||
|
||||
$avaMgr->expects($this->once()) |
||||
->method('getAvatar') |
||||
->with($this->equalTo('alice')) |
||||
->will($this->returnValue($avatar)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateAvatar(); |
||||
} |
||||
|
||||
public function testUpdateAvatarNotProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$access->expects($this->at(0)) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('jpegPhoto')) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$access->expects($this->at(1)) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('thumbnailPhoto')) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$access->expects($this->exactly(2)) |
||||
->method('readAttribute'); |
||||
|
||||
$image->expects($this->never()) |
||||
->method('valid'); |
||||
$image->expects($this->never()) |
||||
->method('width'); |
||||
$image->expects($this->never()) |
||||
->method('height'); |
||||
$image->expects($this->never()) |
||||
->method('centerCrop'); |
||||
|
||||
$filesys->expects($this->never()) |
||||
->method('isLoaded'); |
||||
|
||||
$avaMgr->expects($this->never()) |
||||
->method('getAvatar'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->updateAvatar(); |
||||
} |
||||
|
||||
public function testUpdateBeforeFirstLogin() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$config->expects($this->at(0)) |
||||
->method('getUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), |
||||
$this->equalTo(0)) |
||||
->will($this->returnValue(0)); |
||||
|
||||
$config->expects($this->at(1)) |
||||
->method('getUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_LASTREFRESH), |
||||
$this->equalTo(0)) |
||||
->will($this->returnValue(0)); |
||||
|
||||
$config->expects($this->exactly(2)) |
||||
->method('getUserValue'); |
||||
|
||||
$config->expects($this->never()) |
||||
->method('setUserValue'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->update(); |
||||
} |
||||
|
||||
public function testUpdateAfterFirstLogin() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$config->expects($this->at(0)) |
||||
->method('getUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), |
||||
$this->equalTo(0)) |
||||
->will($this->returnValue(1)); |
||||
|
||||
$config->expects($this->at(1)) |
||||
->method('getUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_LASTREFRESH), |
||||
$this->equalTo(0)) |
||||
->will($this->returnValue(0)); |
||||
|
||||
$config->expects($this->exactly(2)) |
||||
->method('getUserValue'); |
||||
|
||||
$config->expects($this->once()) |
||||
->method('setUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_LASTREFRESH), |
||||
$this->anything()) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->update(); |
||||
} |
||||
|
||||
public function testUpdateNoRefresh() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
list($access, $connection) = |
||||
$this->getAdvancedMocks($config, $filesys, $log, $avaMgr); |
||||
|
||||
$config->expects($this->at(0)) |
||||
->method('getUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), |
||||
$this->equalTo(0)) |
||||
->will($this->returnValue(1)); |
||||
|
||||
$config->expects($this->at(1)) |
||||
->method('getUserValue') |
||||
->with($this->equalTo('alice'), $this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_LASTREFRESH), |
||||
$this->equalTo(0)) |
||||
->will($this->returnValue(time())); |
||||
|
||||
$config->expects($this->exactly(2)) |
||||
->method('getUserValue'); |
||||
|
||||
$config->expects($this->never()) |
||||
->method('setUserValue'); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->update(); |
||||
} |
||||
|
||||
public function testMarkLogin() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
$config->expects($this->once()) |
||||
->method('setUserValue') |
||||
->with($this->equalTo('alice'), |
||||
$this->equalTo('user_ldap'), |
||||
$this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), |
||||
$this->equalTo(1)) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$user->markLogin(); |
||||
} |
||||
|
||||
public function testGetAvatarImageProvided() { |
||||
list($access, $config, $filesys, $image, $log, $avaMgr) = |
||||
$this->getTestInstances(); |
||||
|
||||
$access->expects($this->once()) |
||||
->method('readAttribute') |
||||
->with($this->equalTo('uid=alice,dc=foo,dc=bar'), |
||||
$this->equalTo('jpegPhoto')) |
||||
->will($this->returnValue(array('this is a photo'))); |
||||
|
||||
$uid = 'alice'; |
||||
$dn = 'uid=alice,dc=foo,dc=bar'; |
||||
|
||||
$user = new User( |
||||
$uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); |
||||
|
||||
$photo = $user->getAvatarImage(); |
||||
$this->assertSame('this is a photo', $photo); |
||||
//make sure readAttribute is not called again but the already fetched |
||||
//photo is returned |
||||
$photo = $user->getAvatarImage(); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue