From 8444b115ba7a9940a3c8f91533d79c61a1f726ff Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Mon, 20 Jan 2014 02:24:39 +0100 Subject: [PATCH] Added user birthday cache --- com.woltlab.wcf/dashboardBox.xml | 5 ++ .../templates/dashboardBoxTodaysBirthdays.tpl | 30 ++++++++ .../templates/userBirthdayList.tpl | 28 ++++++++ .../data/user/UserBirthdayAction.class.php | 68 ++++++++++++++++++ .../files/lib/data/user/UserProfile.class.php | 60 ++++++++++++++-- .../UserBirthdayCacheBuilder.class.php | 48 +++++++++++++ .../box/TodaysBirthdaysDashboardBox.class.php | 71 +++++++++++++++++++ .../user/BirthdayUserOptionOutput.class.php | 18 +---- .../system/user/UserBirthdayCache.class.php | 56 +++++++++++++++ wcfsetup/install/lang/de.xml | 2 + wcfsetup/install/lang/en.xml | 4 +- 11 files changed, 367 insertions(+), 23 deletions(-) create mode 100644 com.woltlab.wcf/templates/dashboardBoxTodaysBirthdays.tpl create mode 100644 com.woltlab.wcf/templates/userBirthdayList.tpl create mode 100644 wcfsetup/install/files/lib/data/user/UserBirthdayAction.class.php create mode 100644 wcfsetup/install/files/lib/system/cache/builder/UserBirthdayCacheBuilder.class.php create mode 100644 wcfsetup/install/files/lib/system/dashboard/box/TodaysBirthdaysDashboardBox.class.php create mode 100644 wcfsetup/install/files/lib/system/user/UserBirthdayCache.class.php diff --git a/com.woltlab.wcf/dashboardBox.xml b/com.woltlab.wcf/dashboardBox.xml index aab9cbb669..da9f502f00 100644 --- a/com.woltlab.wcf/dashboardBox.xml +++ b/com.woltlab.wcf/dashboardBox.xml @@ -40,5 +40,10 @@ sidebar + + + + sidebar + diff --git a/com.woltlab.wcf/templates/dashboardBoxTodaysBirthdays.tpl b/com.woltlab.wcf/templates/dashboardBoxTodaysBirthdays.tpl new file mode 100644 index 0000000000..9058f93a00 --- /dev/null +++ b/com.woltlab.wcf/templates/dashboardBoxTodaysBirthdays.tpl @@ -0,0 +1,30 @@ + + +{if $birthdayUserProfiles|count >= 1} + {lang}wcf.global.button.showAll{/lang} + + +{/if} \ No newline at end of file diff --git a/com.woltlab.wcf/templates/userBirthdayList.tpl b/com.woltlab.wcf/templates/userBirthdayList.tpl new file mode 100644 index 0000000000..27ee627866 --- /dev/null +++ b/com.woltlab.wcf/templates/userBirthdayList.tpl @@ -0,0 +1,28 @@ +{if $users|count} +
+
    + {foreach from=$users item=user} +
  1. +
    + {@$user->getAvatar()->getImageTag(48)} + +
    +
    +

    {$user->username}{if MODULE_USER_RANK && $user->getUserTitle()} {$user->getUserTitle()}{/if}

    +
    +
      + {$user->getBirthday($year)} +
    + + {include file='userInformationButtons'} + + {include file='userInformationStatistics'} +
    +
    +
  2. + {/foreach} +
+
+{else} +

{lang}wcf.global.noItems{/lang}

+{/if} \ No newline at end of file diff --git a/wcfsetup/install/files/lib/data/user/UserBirthdayAction.class.php b/wcfsetup/install/files/lib/data/user/UserBirthdayAction.class.php new file mode 100644 index 0000000000..743da5219e --- /dev/null +++ b/wcfsetup/install/files/lib/data/user/UserBirthdayAction.class.php @@ -0,0 +1,68 @@ + + * @package com.woltlab.wcf + * @subpackage data.user + * @category Community Framework + */ +class UserBirthdayAction extends UserProfileAction implements IGroupedUserListAction { + /** + * @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess + */ + protected $allowGuestAccess = array('getGroupedUserList'); + + /** + * @see \wcf\data\IGroupedUserListAction::validateGetGroupedUserList() + */ + public function validateGetGroupedUserList() { + $this->readString('date'); + + if (!preg_match('/\d{4}-\d{2}-\d{2}/', $this->parameters['date'])) { + throw new UserInputException(); + } + } + + /** + * @see \wcf\data\IGroupedUserListAction::getGroupedUserList() + */ + public function getGroupedUserList() { + $year = $month = $day = 0; + $value = explode('-', $this->parameters['date']); + if (isset($value[0])) $year = intval($value[0]); + if (isset($value[1])) $month = intval($value[1]); + if (isset($value[2])) $day = intval($value[2]); + + // get users + $users = array(); + $userIDs = UserBirthdayCache::getInstance()->getBirthdays($month, $day); + $userList = new UserProfileList(); + $userList->setObjectIDs($userIDs); + $userList->readObjects(); + foreach ($userList->getObjects() as $user) { + if (!$user->isProtected() && $user->getAge($year) >= 0) { + $users[] = $user; + } + } + + WCF::getTPL()->assign(array( + 'users' => $users, + 'year' => $year + )); + return array( + 'pageCount' => 1, + 'template' => WCF::getTPL()->fetch('userBirthdayList') + ); + } +} diff --git a/wcfsetup/install/files/lib/data/user/UserProfile.class.php b/wcfsetup/install/files/lib/data/user/UserProfile.class.php index 63780322b1..03ceeed12c 100644 --- a/wcfsetup/install/files/lib/data/user/UserProfile.class.php +++ b/wcfsetup/install/files/lib/data/user/UserProfile.class.php @@ -497,19 +497,65 @@ class UserProfile extends DatabaseObjectDecorator implements IBreadcrumbProvider /** * Returns the age of this user. * + * @param integer $year * @return integer */ - public function getAge() { - if ($this->__age === null) { - if ($this->birthday && $this->birthdayShowYear) { - $this->__age = DateUtil::getAge($this->birthday); + public function getAge($year = null) { + if ($year !== null) { + if ($this->birthdayShowYear) { + $birthdayYear = 0; + $value = explode('-', $this->birthday); + if (isset($value[0])) $birthdayYear = intval($value[0]); + if ($birthdayYear) { + return $year - $birthdayYear; + } + } - else { - $this->__age = 0; + + return 0; + } + else { + if ($this->__age === null) { + if ($this->birthday && $this->birthdayShowYear) { + $this->__age = DateUtil::getAge($this->birthday); + } + else { + $this->__age = 0; + } + } + + return $this->__age; + } + } + + /** + * Returns the formatted birthday of this user. + * + * @param integer $year + * @return string + */ + public function getBirthday($year = null) { + // split date + $birthdayYear = $month = $day = 0; + $value = explode('-', $this->birthday); + if (isset($value[0])) $birthdayYear = intval($value[0]); + if (isset($value[1])) $month = intval($value[1]); + if (isset($value[2])) $day = intval($value[2]); + + $d = new \DateTime(); + $d->setTimezone(WCF::getUser()->getTimeZone()); + $d->setDate($birthdayYear, $month, $day); + $dateFormat = (($this->birthdayShowYear && $birthdayYear) ? WCF::getLanguage()->get(DateUtil::DATE_FORMAT) : str_replace('Y', '', WCF::getLanguage()->get(DateUtil::DATE_FORMAT))); + $birthday = DateUtil::localizeDate($d->format($dateFormat), $dateFormat, WCF::getLanguage()); + + if ($this->birthdayShowYear) { + $age = $this->getAge($year); + if ($age > 0) { + $birthday .= ' ('.$age.')'; } } - return $this->__age; + return $birthday; } /** diff --git a/wcfsetup/install/files/lib/system/cache/builder/UserBirthdayCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/UserBirthdayCacheBuilder.class.php new file mode 100644 index 0000000000..d3202a458b --- /dev/null +++ b/wcfsetup/install/files/lib/system/cache/builder/UserBirthdayCacheBuilder.class.php @@ -0,0 +1,48 @@ + + * @package com.woltlab.wcf + * @subpackage system.cache.builder + * @category Community Framework + */ +class UserBirthdayCacheBuilder extends AbstractCacheBuilder { + /** + * @see \wcf\system\cache\builder\AbstractCacheBuilder::$maxLifetime + */ + protected $maxLifetime = 3600; + + /** + * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild() + */ + protected function rebuild(array $parameters) { + $userOptionID = User::getUserOptionID('birthday'); + if ($userOptionID === null) { + // birthday profile field missing; skip + return array(); + } + + $data = array(); + $birthday = 'userOption'.$userOptionID; + $sql = "SELECT userID, ".$birthday." + FROM wcf".WCF_N."_user_option_value + WHERE ".$birthday." LIKE ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(array('%-' . ($parameters['month'] < 10 ? '0' : '') . $parameters['month'] . '-%')); + while ($row = $statement->fetchArray()) { + list($year, $month, $day) = explode('-', $row[$birthday]); + if (!isset($data[$month . '-' . $day])) $data[$month . '-' . $day] = array(); + $data[$month . '-' . $day][] = $row['userID']; + } + + return $data; + } +} diff --git a/wcfsetup/install/files/lib/system/dashboard/box/TodaysBirthdaysDashboardBox.class.php b/wcfsetup/install/files/lib/system/dashboard/box/TodaysBirthdaysDashboardBox.class.php new file mode 100644 index 0000000000..12676295e8 --- /dev/null +++ b/wcfsetup/install/files/lib/system/dashboard/box/TodaysBirthdaysDashboardBox.class.php @@ -0,0 +1,71 @@ + + * @package com.woltlab.wcf + * @subpackage system.dashboard.box + * @category Community Framework + */ +class TodaysBirthdaysDashboardBox extends AbstractSidebarDashboardBox { + /** + * user profiles + * @var arra<\wcf\data\user\UserProfile> + */ + public $userProfiles = array(); + + /** + * @see \wcf\system\dashboard\box\IDashboardBox::init() + */ + public function init(DashboardBox $box, IPage $page) { + parent::init($box, $page); + + // get current date + $currentDay = DateUtil::format(null, 'm-d'); + $date = explode('-', DateUtil::format(null, 'Y-n-j')); + + // get user ids + $userIDs = UserBirthdayCache::getInstance()->getBirthdays($date[1], $date[2]); + + if (!empty($userIDs)) { + $userProfileList = new UserProfileList(); + $userProfileList->setObjectIDs($userIDs); + $userProfileList->readObjects(); + $i = 0; + foreach ($userProfileList as $userProfile) { + if ($i == 5) break; + + if (!$userProfile->isProtected() && substr($userProfile->birthday, 5) == $currentDay) { + $this->userProfiles[] = $userProfile; + $i++; + } + } + } + + $this->fetched(); + } + + /** + * @see \wcf\system\dashboard\box\AbstractContentDashboardBox::render() + */ + protected function render() { + if (empty($this->userProfiles)) { + return ''; + } + + WCF::getTPL()->assign(array( + 'birthdayUserProfiles' => $this->userProfiles + )); + return WCF::getTPL()->fetch('dashboardBoxTodaysBirthdays'); + } +} diff --git a/wcfsetup/install/files/lib/system/option/user/BirthdayUserOptionOutput.class.php b/wcfsetup/install/files/lib/system/option/user/BirthdayUserOptionOutput.class.php index 5d79c69c1f..dad95b7068 100644 --- a/wcfsetup/install/files/lib/system/option/user/BirthdayUserOptionOutput.class.php +++ b/wcfsetup/install/files/lib/system/option/user/BirthdayUserOptionOutput.class.php @@ -2,8 +2,7 @@ namespace wcf\system\option\user; use wcf\data\user\option\UserOption; use wcf\data\user\User; -use wcf\system\WCF; -use wcf\util\DateUtil; +use wcf\data\user\UserProfile; /** * User option output implementation for the output of a user's birthday. @@ -20,18 +19,7 @@ class BirthdayUserOptionOutput extends DateUserOptionOutput { * @see \wcf\system\option\user\IUserOptionOutput::getOutput() */ public function getOutput(User $user, UserOption $option, $value) { - // set date format - $this->dateFormat = ($user->birthdayShowYear ? DateUtil::DATE_FORMAT : str_replace('Y', '', WCF::getLanguage()->get(DateUtil::DATE_FORMAT))); - - // format date - $dateString = parent::getOutput($user, $option, $value); - if ($dateString && $user->birthdayShowYear) { - $age = DateUtil::getAge($value); - if ($age > 0) { - $dateString .= ' ('.$age.')'; - } - } - - return $dateString; + $profile = new UserProfile($user); + return $profile->getBirthday(); } } diff --git a/wcfsetup/install/files/lib/system/user/UserBirthdayCache.class.php b/wcfsetup/install/files/lib/system/user/UserBirthdayCache.class.php new file mode 100644 index 0000000000..24ecc6da70 --- /dev/null +++ b/wcfsetup/install/files/lib/system/user/UserBirthdayCache.class.php @@ -0,0 +1,56 @@ + + * @package com.woltlab.wcf + * @subpackage system.user + * @category Community Framework + */ +class UserBirthdayCache extends SingletonFactory { + /** + * loaded months + * @var array + */ + protected $monthsLoaded = array(); + + /** + * user birthdays + * @var array + */ + protected $birthdays = array(); + + /** + * Loads the birthday cache. + * + * @param integer $month + */ + protected function loadMonth($month) { + if (!isset($this->monthsLoaded[$month])) { + $this->birthdays = array_merge($this->birthdays, UserBirthdayCacheBuilder::getInstance()->getData(array('month' => $month))); + $this->monthsLoaded[$month] = true; + } + } + + /** + * Gets the user birthdays for a specific day. + * + * @param integer $month + * @param integer $day + * @return array list of user ids + */ + public function getBirthdays($month, $day) { + $this->loadMonth($month); + + $index = ($month < 10 ? '0' : '') . $month . '-' . ($day < 10 ? '0' : '') . $day; + if (isset($this->birthdays[$index])) return $this->birthdays[$index]; + + return array(); + } +} diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 523dbb794a..635ee4df8e 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -1518,6 +1518,7 @@ Fehler sind beispielsweise: likesReceived} Like{if $likedMember->likesReceived != 1}s{/if}]]> + @@ -1770,6 +1771,7 @@ Fehler sind beispielsweise: + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 3c016a1572..8338123b6f 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -919,7 +919,7 @@ GmbH=Gesellschaft mit beschränkter Haftung]]> getName()}”?]]> - + package}){if $excludedPackage->excludedPackageVersion} (excluded version: {$excludedPackage->excludedPackageVersion}, installed version: {$excludedPackage->packageVersion}){/if}]]> package}){if $excludingPackage->excludedPackageVersion} (excluded version: {$excludingPackage->excludedPackageVersion}){/if}]]> @@ -1517,6 +1517,7 @@ Errors are: likesReceived} Like{if $likedMember->likesReceived != 1}s{/if}]]> + @@ -1769,6 +1770,7 @@ Errors are: + -- 2.20.1