<import>
<box identifier="com.woltlab.wcf.RecentActivity">
<name language="de">Letzte Aktivitäten</name>
- <name language="en">Recent Activity</name>
+ <name language="en">Recent Activities</name>
<boxType>system</boxType>
- <controller>wcf\system\box\RecentActivityBoxController</controller>
+ <objectType>com.woltlab.wcf.recentActivityList</objectType>
<position>contentBottom</position>
<showHeader>0</showHeader>
<visibleEverywhere>0</visibleEverywhere>
<visibilityExceptions>
<page>com.woltlab.wcf.Dashboard</page>
</visibilityExceptions>
+ <limit>10</limit>
+
+ <content language="de">
+ <title>Letzte Aktivitäten</title>
+ </content>
+ <content language="en">
+ <title>Recent Activities</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.RecentActivitySidebar">
<name language="de">Letzte Aktivitäten (Sidebar)</name>
- <name language="en">Recent Activity (Sidebar)</name>
+ <name language="en">Recent Activities (Sidebar)</name>
<boxType>system</boxType>
- <controller>wcf\system\box\RecentActivityBoxController</controller>
+ <objectType>com.woltlab.wcf.recentActivityList</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
<visibilityExceptions>
<page>com.woltlab.wcf.Dashboard</page>
</visibilityExceptions>
+ <limit>10</limit>
+
+ <content language="de">
+ <title>Letzte Aktivitäten</title>
+ </content>
+ <content language="en">
+ <title>Recent Activities</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.PaidSubscriptions">
<name language="de">Bezahlte Mitgliedschaften</name>
<name language="en">Paid Subscriptions</name>
<boxType>system</boxType>
- <controller>wcf\system\box\PaidSubscriptionsBoxController</controller>
+ <objectType>com.woltlab.wcf.paidSubscriptions</objectType>
<position>contentBottom</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Bezahlte Mitgliedschaften</title>
+ </content>
+ <content language="en">
+ <title>Paid Subscriptions</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.PaidSubscriptionsSidebar">
<name language="de">Bezahlte Mitgliedschaften (Sidebar)</name>
<name language="en">Paid Subscriptions (Sidebar)</name>
<boxType>system</boxType>
- <controller>wcf\system\box\PaidSubscriptionsBoxController</controller>
+ <objectType>com.woltlab.wcf.paidSubscriptions</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Bezahlte Mitgliedschaften</title>
+ </content>
+ <content language="en">
+ <title>Paid Subscriptions</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.RegisterButton">
<name language="de">Registrierungs-Button</name>
<name language="en">Register Button</name>
<boxType>system</boxType>
- <controller>wcf\system\box\RegisterButtonBoxController</controller>
+ <objectType>com.woltlab.wcf.registerButton</objectType>
<position>sidebarRight</position>
<showHeader>0</showHeader>
<visibleEverywhere>0</visibleEverywhere>
<visibilityExceptions>
<page>com.woltlab.wcf.Dashboard</page>
</visibilityExceptions>
+
+ <content language="de">
+ <title>Registrierung</title>
+ </content>
+ <content language="en">
+ <title>Registration</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.SignedInAs">
<name language="de">Angemeldet als</name>
<name language="en">Signed In As</name>
<boxType>system</boxType>
- <controller>wcf\system\box\SignedInAsBoxController</controller>
+ <objectType>com.woltlab.wcf.signedInAs</objectType>
<position>sidebarRight</position>
<showHeader>0</showHeader>
<visibleEverywhere>0</visibleEverywhere>
<visibilityExceptions>
<page>com.woltlab.wcf.Dashboard</page>
</visibilityExceptions>
+
+ <!-- TODO: content title -->
</box>
<box identifier="com.woltlab.wcf.Statistics">
<name language="de">Statistiken</name>
<name language="en">Statistics</name>
<boxType>system</boxType>
- <controller>wcf\system\box\StatisticsBoxController</controller>
+ <objectType>com.woltlab.wcf.statistics</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
<visibilityExceptions>
<page>com.woltlab.wcf.Dashboard</page>
</visibilityExceptions>
+
+ <content language="de">
+ <title>Statistiken</title>
+ </content>
+ <content language="en">
+ <title>Statistics</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.NewestMembers">
<name language="de">Neueste Mitglieder</name>
<name language="en">Newest Members</name>
<boxType>system</boxType>
- <controller>wcf\system\box\NewestMembersBoxController</controller>
+ <objectType>com.woltlab.wcf.userList</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+ <sortField>registrationDate</sortField>
+ <sortOrder>DESC</sortOrder>
+
+ <content language="de">
+ <title>Neueste Mitglieder</title>
+ </content>
+ <content language="en">
+ <title>Newest Members</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.MostActiveMembers">
<name language="de">Aktivste Mitglieder</name>
<name language="en">Most Active Members</name>
<boxType>system</boxType>
- <controller>wcf\system\box\MostActiveMembersBoxController</controller>
+ <objectType>com.woltlab.wcf.userList</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+ <sortField>activityPoints</sortField>
+ <sortOrder>DESC</sortOrder>
+
+ <content language="de">
+ <title>Aktivste Mitglieder</title>
+ </content>
+ <content language="en">
+ <title>Most Active Members</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.MostLikedMembers">
<name language="de">Mitglieder mit den meisten Likes</name>
<name language="en">Most Liked Members</name>
<boxType>system</boxType>
- <controller>wcf\system\box\MostLikedMembersBoxController</controller>
+ <objectType>com.woltlab.wcf.userList</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+ <sortField>likesReceived</sortField>
+ <sortOrder>DESC</sortOrder>
+
+ <content language="de">
+ <title>Mitglieder mit den meisten Likes</title>
+ </content>
+ <content language="en">
+ <title>Most Liked Members</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.TodaysBirthdays">
<name language="de">Heutige Geburtstage</name>
<name language="en">Today’s Birthdays</name>
<boxType>system</boxType>
- <controller>wcf\system\box\TodaysBirthdaysBoxController</controller>
+ <objectType>com.woltlab.wcf.todaysBirthdays</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Heutige Geburtstage</title>
+ </content>
+ <content language="en">
+ <title>Today’s Birthdays</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.TodaysFollowingBirthdays">
<name language="de">Heutige Geburtstage von Nutzern, denen der Nutzer folgt</name>
<name language="en">Today’s Birthdays of Users the User Follows</name>
<boxType>system</boxType>
- <controller>wcf\system\box\TodaysFollowingBirthdaysBoxController</controller>
+ <objectType>com.woltlab.wcf.todaysFollowingBirthdays</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <!-- TODO: content title -->
</box>
<box identifier="com.woltlab.wcf.UsersOnline">
<name language="de">Benutzer online</name>
<name language="en">Users Online</name>
<boxType>system</boxType>
- <controller>wcf\system\box\UsersOnlineBoxController</controller>
+ <objectType>com.woltlab.wcf.userOnlineList</objectType>
<position>footerBoxes</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Benutzer online</title>
+ </content>
+ <content language="en">
+ <title>Users Online</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.UsersOnlineSidebar">
<name language="de">Benutzer online (Sidebar)</name>
<name language="en">Users Online (Sidebar)</name>
<boxType>system</boxType>
- <controller>wcf\system\box\UsersOnlineBoxController</controller>
+ <objectType>com.woltlab.wcf.userOnlineList</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Benutzer online</title>
+ </content>
+ <content language="en">
+ <title>Users Online</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.StaffOnline">
<name language="de">Team-Mitglieder online</name>
<name language="en">Staff-Members Online</name>
<boxType>system</boxType>
- <controller>wcf\system\box\StaffOnlineBoxController</controller>
+ <objectType>com.woltlab.wcf.staffOnlineList</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Team-Mitglieder online</title>
+ </content>
+ <content language="en">
+ <title>Staff-Members Online</title>
+ </content>
</box>
<box identifier="com.woltlab.wcf.FollowingsOnline">
<name language="de">Benutzer online, denen der Nutzer folgt</name>
<name language="en">Users Online the User Follows</name>
<boxType>system</boxType>
- <controller>wcf\system\box\FollowingsBoxController</controller>
+ <objectType>com.woltlab.wcf.followingsOnline</objectType>
<position>sidebarRight</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+ <limit>10</limit>
+
+ <!-- TODO: content title -->
</box>
<box identifier="com.woltlab.wcf.PageComments">
- <name language="de">Kommentare</name>
+ <name language="de">Seiten-Kommentare</name>
<name language="en">Page Comments</name>
<boxType>system</boxType>
- <controller>wcf\system\box\PageCommentsBoxController</controller>
+ <objectType>com.woltlab.wcf.pageCommentList</objectType>
<position>contentBottom</position>
<showHeader>1</showHeader>
<visibleEverywhere>0</visibleEverywhere>
+
+ <content language="de">
+ <title>Kommentare</title>
+ </content>
+ <content language="en">
+ <title>Comments</title>
+ </content>
</box>
</import>
</data>
</type>
<!-- /user search conditions -->
+ <!-- box controllers -->
+ <type>
+ <name>com.woltlab.wcf.recentActivityList</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\RecentActivityListBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.paidSubscriptions</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\PaidSubscriptionsBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.registerButton</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\RegisterButtonBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.signedInAs</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\SignedInAsBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.statistics</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\StatisticsBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.userList</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\userListBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.userOnlineList</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\UserOnlineListBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.staffOnlineList</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\StaffOnlineListBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.todaysBirthdays</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\TodaysBirthdaysBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.todaysFollowingBirthdays</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\TodaysFollowingBirthdaysBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.followingsOnline</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\FollowingsOnlineBoxController</classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.pageCommentList</name>
+ <definitionname>com.woltlab.wcf.boxController</definitionname>
+ <classname>wcf\system\box\PageCommentListBoxController</classname>
+ </type>
+ <!-- /box controllers -->
+
<!-- deprecated -->
<type>
<name>com.woltlab.wcf.page.controller</name>
<interfacename><![CDATA[wcf\system\bulk\processing\IBulkProcessingAction]]></interfacename>
</definition>
+ <definition>
+ <name>com.woltlab.wcf.boxController</name>
+ <interfacename>wcf\system\box\IBoxController</interfacename>
+ </definition>
+
<!-- deprecated -->
<definition>
<name>com.woltlab.wcf.user.online.location</name>
<category name="dashboard.content">
<parent>dashboard</parent>
</category>
- <category name="dashboard.content.recentActivities">
- <parent>dashboard.content</parent>
- </category>
<category name="dashboard.sidebar">
<parent>dashboard</parent>
</category>
- <category name="dashboard.sidebar.recentActivities">
- <parent>dashboard.sidebar</parent>
- </category>
<!-- cms -->
<category name="cms"></category>
</option>
<!-- /user.cleanup -->
- <!-- dashboard TODO -->
- <option name="recent_activity_items">
- <categoryname>dashboard.content.recentActivities</categoryname>
- <optiontype>integer</optiontype>
- <defaultvalue>10</defaultvalue>
- <minvalue>5</minvalue>
- <maxvalue>100</maxvalue>
- </option>
-
- <option name="recent_activity_sidebar_items">
- <categoryname>dashboard.sidebar.recentActivities</categoryname>
- <optiontype>integer</optiontype>
- <defaultvalue>5</defaultvalue>
- <minvalue>5</minvalue>
- <maxvalue>50</maxvalue>
- </option>
- <!-- /dashboard -->
-
<option name="like_allow_for_own_content">
<categoryname>message.general.likes</categoryname>
<optiontype>boolean</optiontype>
<option name="enable_pluginstore_widget" />
<option name="mail_use_formatted_address" />
<option name="mail_debug_logfile_path" />
+ <option name="recent_activity_items" />
+ <option name="recent_activity_sidebar_items" />
+
+ <optioncategory name="dashboard.content.recentActivities" />
+ <optioncategory name="dashboard.sidebar.recentActivities" />
</delete>
</data>
--- /dev/null
+<ul class="sidebarBoxList">
+ {foreach from=$boxUsers item=boxUser}
+ <li class="box24">
+ <a href="{link controller='User' object=$boxUser}{/link}">{@$boxUser->getAvatar()->getImageTag(24)}</a>
+
+ <div class="sidebarBoxHeadline">
+ <h3><a href="{link controller='User' object=$boxUser}{/link}" class="userLink" data-user-id="{@$boxUser->userID}">{$boxUser->username}</a></h3>
+ {capture assign='__boxUserLanguageItem'}{lang __optional=true}wcf.user.boxList.description.{$boxSortField}{/lang}{/capture}
+ {if $__boxUserLanguageItem}
+ <small>{@$__boxUserLanguageItem}</small>
+ {* TODO: else? *}
+ {/if}
+ </div>
+ </li>
+ {/foreach}
+</ul>
define('USER_CLEANUP_NOTIFICATION_LIFETIME', 14);
define('USER_CLEANUP_ACTIVITY_EVENT_LIFETIME', 60);
define('USER_CLEANUP_PROFILE_VISITOR_LIFETIME', 60);
-define('RECENT_ACTIVITY_ITEMS', 10);
-define('RECENT_ACTIVITY_SIDEBAR_ITEMS', 5);
define('LIKE_ALLOW_FOR_OWN_CONTENT', 1);
define('LIKE_ENABLE_DISLIKE', 1);
define('LIKE_SHOW_SUMMARY', 1);
use wcf\system\WCF;
// set default landing page
-$sql = "UPDATE wcf".WCF_N."_page
- SET isLandingPage = ?
- WHERE identifier = ?";
+$sql = "UPDATE wcf".WCF_N."_page
+ SET isLandingPage = ?
+ WHERE identifier = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([
1,
// update administrator user rank and user online marking
$editor = new UserEditor(WCF::getUser());
-$action = new UserProfileAction(array($editor), 'updateUserRank');
+$action = new UserProfileAction([$editor], 'updateUserRank');
$action->executeAction();
-$action = new UserProfileAction(array($editor), 'updateUserOnlineMarking');
+$action = new UserProfileAction([$editor], 'updateUserOnlineMarking');
$action->executeAction();
<script data-relocate="true">
{include file='mediaJavaScript'}
- require(['WoltLab/WCF/Media/Manager/Select'], function(MediaManagerSelect) {
+ require(['WoltLab/WCF/Acp/Ui/Box/Controller/Handler', 'WoltLab/WCF/Media/Manager/Select'], function(AcpUiBoxControllerHandler, MediaManagerSelect) {
+ AcpUiBoxControllerHandler.init({if $boxController}{@$boxController->objectTypeID}{/if});
+
new MediaManagerSelect({
dialogTitle: '{lang}wcf.acp.box.image.dialog.title{/lang}',
fileTypeFilters: {
</dd>
</dl>
+ <dl id="boxControllerContainer"{if $errorField == 'boxControllerID'} class="formError"{/if}{if !$boxController} style="display: none;"{/if}>
+ <dt><label for="boxControllerID">{lang}wcf.acp.box.boxController{/lang}</label></dt>
+ <dd>
+ <select name="boxControllerID" id="boxControllerID">
+ {foreach from=$availableBoxControllers item=availableBoxController}
+ <option value="{@$availableBoxController->objectTypeID}"{if $boxController && $availableBoxController->objectTypeID == $boxController->objectTypeID} selected="selected"{/if}>{lang}wcf.acp.box.boxController.{@$availableBoxController->objectType}{/lang}</option>
+ {/foreach}
+ </select>
+
+ {if $errorField == 'boxType'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.box.boxController.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+
<dl{if $errorField == 'position'} class="formError"{/if}>
<dt><label for="position">{lang}wcf.acp.box.position{/lang}</label></dt>
<dd>
</dd>
</dl>
- <dl{if $errorField == 'controller'} class="formError"{/if}>
- <dt><label for="controller">{lang}wcf.acp.box.controller{/lang}</label></dt>
- <dd>
- <input type="text" id="controller" name="controller" value="{$controller}" class="long" />
- {if $errorField == 'controller'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {else}
- {lang}wcf.acp.box.controller.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
<dl>
<dt></dt>
<dd>
{event name='linkFields'}
</section>
+ <div id="boxConditions">
+ {if $boxController && $boxController->getProcessor()|is_subclass_of:'wcf\system\box\IConditionBoxController'}
+ {@$boxController->getProcessor()->getConditionsTemplate()}
+ {/if}
+ </div>
+
{if !$isMultilingual}
<section class="section">
- <h2 class="sectionTitle">content</h2>
+ <h2 class="sectionTitle">{* TODO *}content</h2>
{if $__wcf->session->getPermission('admin.content.cms.canUseMedia')}
<dl{if $errorField == 'image'} class="formError"{/if}>
--- /dev/null
+{if !$errorField|isset}{assign var=errorField value=''}{/if}
+
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.acp.box.settings{/lang}</h2>
+
+ {if $defaultLimit !== null}
+ <dl{if $errorField === 'limit'} class="formError"{/if}>
+ <dt>{lang}wcf.acp.box.settings.limit{/lang}</dt>
+ <dd>
+ <input type="number" name="limit" id="limit" value="{$limit}" min="{$minimumLimit}"{if $maximumLimit !== null} max="{$maximumLimit}"{/if} class="tiny" />
+ {if $errorField === 'limit'}
+ <small class="innerError">
+ {if $errorType === 'lessThan'}
+ {lang lessThan=$maximumLimit+1}wcf.global.form.error.lessThan{/lang}
+ {elseif $errorType === 'greaterThan'}
+ {lang greaterThan=$minimumLimit-1}wcf.global.form.error.greaterThan{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+ {/if}
+
+ {if !$validSortFields|empty}
+ <dl{if $errorField === 'sorting'} class="formError"{/if}>
+ <dt>{lang}wcf.global.sorting{/lang}</dt>
+ <dd>
+ <select name="sortField" id="sortField">
+ {foreach from=$validSortFields item=validSortField}
+ <option value="{$validSortField}"{if $validSortField == $sortField} selected="selected"{/if}>{lang}{$sortFieldLanguageItemPrefix}.{$validSortField}{/lang}</option>
+ {/foreach}
+ </select>
+
+ <select name="sortOrder" id="sortOrder">
+ <option value="ASC"{if $sortOrder == 'ASC'} selected="selected"{/if}>{lang}wcf.global.sortOrder.ascending{/lang}</option>
+ <option value="DESC"{if $sortOrder == 'DESC'} selected="selected"{/if}>{lang}wcf.global.sortOrder.descending{/lang}</option>
+ </select>
+
+ {if $errorField === 'sorting'}
+ <small class="innerError">
+ {lang}wcf.global.sorting.error.{$errorType}{/lang}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+ {/if}
+
+ {event name='fields'}
+
+ {foreach from=$conditionObjectTypes item=conditionObjectType}
+ {@$conditionObjectType->getProcessor()->getHtml()}
+ {/foreach}
+</section>
--- /dev/null
+/**
+ * Provides the interface logic to add and edit menu items.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLab/WCF/Acp/Ui/Box/Controller/Handler
+ */
+define(['Ajax', 'Dictionary'], function(Ajax, Dictionary) {
+ "use strict";
+
+ var _boxType = elById('boxType');
+ var _boxControllerContainer = elById('boxControllerContainer');
+ var _boxController = elById('boxControllerID');
+ var _boxConditions = elById('boxConditions');
+ var _templates = new Dictionary();
+
+ /**
+ * @exports WoltLab/WCF/Acp/Ui/Box/Controller/Handler
+ */
+ return {
+ init: function(initialObjectTypeId) {
+ _boxType.addEventListener('change', this._updateControllers.bind(this));
+ _boxController.addEventListener('change', this._updateConditions.bind(this));
+
+ if (initialObjectTypeId) {
+ _templates.set(~~initialObjectTypeId, _boxConditions.innerHTML);
+ }
+
+ this._updateControllers();
+ },
+
+ /**
+ * Sets up ajax request object.
+ *
+ * @return {object} request options
+ */
+ _ajaxSetup: function() {
+ return {
+ data: {
+ actionName: 'getBoxConditionsTemplate',
+ className: 'wcf\\data\\box\\BoxAction'
+ }
+ };
+ },
+
+ /**
+ * Handles successful AJAX requests.
+ *
+ * @param {object} data response data
+ */
+ _ajaxSuccess: function(data) {
+ _templates.set(~~data.returnValues.objectTypeID, data.returnValues.template);
+
+ _boxConditions.innerHTML = data.returnValues.template;
+ },
+
+ /**
+ * Updates the displayed box conditions based on the selected dynamic box controller.
+ *
+ * @protected
+ */
+ _updateConditions: function() {
+ var objectTypeId = ~~_boxController.value;
+
+ if (_templates.has(objectTypeId)) {
+ if (_templates.get(objectTypeId) !== null) {
+ _boxConditions.innerHTML = _templates.get(objectTypeId);
+ }
+ }
+ else {
+ _templates.set(objectTypeId, null);
+
+ Ajax.api(this, {
+ parameters: {
+ objectTypeID: objectTypeId
+ }
+ });
+ }
+ },
+
+ /**
+ * Shows or hides the list of dynamic box controllers based on the selected box type.
+ *
+ * @protected
+ */
+ _updateControllers: function() {
+ if (_boxType.value === 'system') {
+ elShow(_boxControllerContainer);
+
+ this._updateConditions();
+ }
+ else {
+ elHide(_boxControllerContainer);
+
+ _boxConditions.innerHTML = '';
+ }
+ }
+ };
+});
use wcf\data\box\BoxEditor;
use wcf\data\media\Media;
use wcf\data\media\ViewableMediaList;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
use wcf\data\page\Page;
use wcf\data\page\PageNodeTree;
use wcf\form\AbstractForm;
+use wcf\system\box\IConditionBoxController;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\UserInputException;
use wcf\system\language\LanguageFactory;
*/
public $showHeader = 1;
- /**
- * box controller
- * @var string
- */
- public $controller = '';
-
/**
* box name
* @var string
*/
public $pageIDs = [];
+ /**
+ * object type id of the selected box controller
+ * @var integer
+ */
+ public $boxControllerID = 0;
+
+ /**
+ * selected box controller object type
+ * @var ObjectType
+ */
+ public $boxController;
+
/**
* link type
* @var string
if (isset($_POST['visibleEverywhere'])) $this->visibleEverywhere = intval($_POST['visibleEverywhere']);
if (isset($_POST['cssClassName'])) $this->cssClassName = StringUtil::trim($_POST['cssClassName']);
if (isset($_POST['showHeader'])) $this->showHeader = intval($_POST['showHeader']);
- if (isset($_POST['controller'])) $this->controller = StringUtil::trim($_POST['controller']);
if (isset($_POST['pageIDs']) && is_array($_POST['pageIDs'])) $this->pageIDs = ArrayUtil::toIntegerArray($_POST['pageIDs']);
if (isset($_POST['linkType'])) $this->linkType = $_POST['linkType'];
if (isset($_POST['title']) && is_array($_POST['title'])) $this->title = ArrayUtil::trim($_POST['title']);
if (isset($_POST['content']) && is_array($_POST['content'])) $this->content = ArrayUtil::trim($_POST['content']);
+ if (isset($_POST['boxControllerID'])) $this->boxControllerID = intval($_POST['boxControllerID']);
if (WCF::getSession()->getPermission('admin.content.cms.canUseMedia')) {
if (isset($_POST['imageID']) && is_array($_POST['imageID'])) $this->imageID = ArrayUtil::toIntegerArray($_POST['imageID']);
throw new UserInputException('boxType');
}
+ if ($this->boxType === 'system') {
+ $this->boxController = ObjectTypeCache::getInstance()->getObjectType($this->boxControllerID);
+ if ($this->boxController === null || $this->boxController->getDefinition()->definitionName != 'com.woltlab.wcf.boxController') {
+ throw new UserInputException('boxController');
+ }
+
+ if ($this->boxController && $this->boxController->getProcessor() instanceof IConditionBoxController) {
+ $this->boxController->getProcessor()->readConditions();
+ }
+ }
+ else {
+ $this->boxControllerID = 0;
+ }
+
// validate box position
if (!in_array($this->position, Box::$availablePositions)) {
throw new UserInputException('position');
}
- // validate class name
- if ($this->boxType == 'system') {
- if (empty($this->controller)) {
- throw new UserInputException('controller');
- }
-
- // @todo check controller
- }
-
// validate link
if ($this->linkType == 'internal') {
$this->externalURL = '';
}
}
}
+
+ if ($this->boxController && $this->boxController->getProcessor() instanceof IConditionBoxController) {
+ $this->boxController->getProcessor()->validateConditions();
+ }
}
/**
$this->objectAction = new BoxAction([], 'create', ['data' => array_merge($this->additionalFields, [
'name' => $this->name,
+ 'objectTypeID' => $this->boxControllerID,
'packageID' => 1,
'isMultilingual' => $this->isMultilingual,
'boxType' => $this->boxType,
'visibleEverywhere' => $this->visibleEverywhere,
'cssClassName' => $this->cssClassName,
'showHeader' => $this->showHeader,
- 'controller' => $this->controller,
'linkPageID' => $this->linkPageID,
'linkPageObjectID' => ($this->linkPageObjectID ?: 0),
'externalURL' => $this->externalURL,
'identifier' => ''
]), 'content' => $content, 'pageIDs' => $this->pageIDs ]);
- $returnValues = $this->objectAction->executeAction();
+ $box = $this->objectAction->executeAction()['returnValues'];
// set generic box identifier
- $boxEditor = new BoxEditor($returnValues['returnValues']);
+ $boxEditor = new BoxEditor($box);
$boxEditor->update([
'identifier' => 'com.woltlab.wcf.genericBox'.$boxEditor->boxID
]);
+ if ($this->boxController && $this->boxController->getProcessor() instanceof IConditionBoxController) {
+ $this->boxController->getProcessor()->setBox($box, false);
+ $this->boxController->getProcessor()->saveConditions();
+ }
+
// call saved event
$this->saved();
WCF::getTPL()->assign('success', true);
// reset variables
- $this->boxType = $this->position = $this->cssClassName = $this->controller = $this->name = '';
- $this->showOrder = 0;
+ $this->boxType = $this->position = $this->cssClassName = $this->name = '';
+ $this->showOrder = $this->boxControllerID = 0;
$this->visibleEverywhere = $this->showHeader = 1;
$this->title = $this->content = $this->images = $this->imageID = [];
+ $this->boxController = null;
}
/**
'boxType' => $this->boxType,
'position' => $this->position,
'cssClassName' => $this->cssClassName,
- 'controller' => $this->controller,
'showOrder' => $this->showOrder,
'visibleEverywhere' => $this->visibleEverywhere,
'showHeader' => $this->showHeader,
'availableLanguages' => LanguageFactory::getInstance()->getLanguages(),
'availableBoxTypes' => Box::$availableBoxTypes,
'availablePositions' => Box::$availablePositions,
+ 'availableBoxControllers' => ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.boxController'),
+ 'boxController' => $this->boxController,
'pageNodeList' => $this->pageNodeList,
'pageHandlers' => $this->pageHandlers
]);
namespace wcf\acp\form;
use wcf\data\box\Box;
use wcf\data\box\BoxAction;
+use wcf\data\object\type\ObjectTypeCache;
use wcf\form\AbstractForm;
+use wcf\system\box\IConditionBoxController;
use wcf\system\exception\IllegalLinkException;
use wcf\system\language\LanguageFactory;
use wcf\system\WCF;
public function save() {
AbstractForm::save();
- $content = array();
+ $content = [];
if ($this->isMultilingual) {
foreach (LanguageFactory::getInstance()->getLanguages() as $language) {
$content[$language->languageID] = [
$this->objectAction = new BoxAction([$this->box], 'update', ['data' => array_merge($this->additionalFields, [
'name' => $this->name,
+ 'objectTypeID' => $this->boxControllerID,
'isMultilingual' => $this->isMultilingual,
'boxType' => $this->boxType,
'position' => $this->position,
'visibleEverywhere' => $this->visibleEverywhere,
'cssClassName' => $this->cssClassName,
'showHeader' => $this->showHeader,
- 'controller' => $this->controller,
'linkPageID' => $this->linkPageID,
'linkPageObjectID' => ($this->linkPageObjectID ?: 0),
'externalURL' => $this->externalURL
]), 'content' => $content, 'pageIDs' => $this->pageIDs]);
$this->objectAction->executeAction();
+ if ($this->boxController && $this->boxController->getProcessor() instanceof IConditionBoxController) {
+ $this->boxController->getProcessor()->setBox($this->box, false);
+ $this->boxController->getProcessor()->saveConditions();
+ }
+
// call saved event
$this->saved();
$this->position = $this->box->position;
$this->showOrder = $this->box->showOrder;
$this->cssClassName = $this->box->cssClassName;
- $this->controller = $this->box->controller;
+ $this->boxControllerID = $this->box->objectTypeID;
if ($this->box->showHeader) $this->showHeader = 1;
if ($this->box->visibleEverywhere) $this->visibleEverywhere = 1;
else $this->visibleEverywhere = 0;
$this->imageID[$languageID] = $content['imageID'];
}
+ if ($this->boxControllerID) {
+ $this->boxController = ObjectTypeCache::getInstance()->getObjectType($this->boxControllerID);
+ if ($this->boxController->getProcessor() instanceof IConditionBoxController) {
+ $this->boxController->getProcessor()->setBox($this->box);
+ }
+ }
+
$this->readBoxImages();
}
}
public function assignVariables() {
parent::assignVariables();
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'action' => 'edit',
'boxID' => $this->boxID,
'box' => $this->box
- ));
+ ]);
}
}
<?php
namespace wcf\data\box;
+use wcf\data\condition\Condition;
use wcf\data\media\ViewableMedia;
use wcf\data\menu\Menu;
use wcf\data\menu\MenuCache;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\box\IConditionBoxController;
+use wcf\system\condition\ConditionHandler;
use wcf\data\page\Page;
use wcf\data\page\PageCache;
use wcf\data\DatabaseObject;
* @since 2.2
*
* @property-read integer $boxID
+ * @property-read integer|null $objectTypeID id of the box controller object type
* @property-read string $identifier
* @property-read string $name
* @property-read string $boxType
* @property-read integer $showHeader
* @property-read integer $originIsSystem
* @property-read integer $packageID
- * @property-read string $controller
* @property-read integer|null $menuID
* @property-read integer $linkPageID
* @property-read integer $linkPageObjectID
* @property-read string $externalURL
+ * @property-read mixed[] $additionalData
*/
class Box extends DatabaseObject {
/**
/**
* box to page assignments
- * @var integer[]
+ * @var integer[]
*/
protected $pageIDs;
/**
* box controller
- * @var \wcf\system\box\IBoxController
+ * @var \wcf\system\box\IBoxController
*/
- protected $__controller;
+ protected $controller;
+
+ /**
+ * @inheritDoc
+ */
+ public function __get($name) {
+ $value = parent::__get($name);
+
+ if ($value === null && isset($this->data['additionalData'][$name])) {
+ $value = $this->data['additionalData'][$name];
+ }
+
+ return $value;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function handleData($data) {
+ parent::handleData($data);
+
+ // handle condition data
+ $this->data['additionalData'] = @unserialize($data['additionalData']);
+ if (!is_array($this->data['additionalData'])) {
+ $this->data['additionalData'] = [];
+ }
+ }
/**
* @var IMenuPageHandler
return $this->boxContent;
}
+ /**
+ * Returns the title of the box as set in the box content database table.
+ *
+ * @return string
+ */
+ public function getBoxContentTitle() {
+ $boxContent = $this->getBoxContent();
+ if ($this->isMultilingual) {
+ if (isset($boxContent[WCF::getLanguage()->languageID])) {
+ return $boxContent[WCF::getLanguage()->languageID]['title'];
+ }
+ }
+ else if (isset($boxContent[0])) {
+ return $boxContent[0]['title'];
+ }
+
+ return '';
+ }
+
/**
* Returns the title for the rendered version of this box.
*
* @return string
*/
public function getTitle() {
- if ($this->boxType == 'system') {
- return $this->getController()->getTitle();
- }
- else if ($this->boxType == 'menu') {
+ if ($this->boxType == 'menu') {
return $this->getMenu()->getTitle();
}
- else {
- $boxContent = $this->getBoxContent();
- if ($this->isMultilingual) {
- if (isset($boxContent[WCF::getLanguage()->languageID])) return $boxContent[WCF::getLanguage()->languageID]['title'];
- }
- else {
- if (isset($boxContent[0])) return $boxContent[0]['title'];
- }
- }
- return '';
+ return $this->getBoxContentTitle();
}
/**
* @return \wcf\system\box\IBoxController
*/
public function getController() {
- if ($this->__controller === null) {
- if ($this->controller && class_exists($this->controller)) {
- $this->__controller = new $this->controller;
- $this->__controller->setBox($this);
- }
+ if ($this->controller === null && $this->objectTypeID) {
+ $className = ObjectTypeCache::getInstance()->getObjectType($this->objectTypeID)->className;
+
+ $this->controller = new $className;
+ $this->controller->setBox($this);
}
- return $this->__controller;
+ return $this->controller;
}
/**
WHERE boxID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([$this->boxID]);
- while ($row = $statement->fetchArray()) {
- $this->pageIDs[] = $row['pageID'];
+ while ($pageID = $statement->fetchColumn()) {
+ $this->pageIDs[] = $pageID;
}
}
return $this->pageIDs;
}
+ /**
+ * Returns the conditions of the notice.
+ *
+ * @return Condition[]
+ */
+ public function getConditions() {
+ if ($this->boxType === 'system' && $this->getController() instanceof IConditionBoxController && $this->getController()->getConditionDefinition()) {
+ return ConditionHandler::getInstance()->getConditions($this->getController()->getConditionDefinition(), $this->boxID);
+ }
+
+ return [];
+ }
+
+ /**
+ * Returns the box with the given idnetifier.
+ *
+ * @param string $identifier
+ * @return Box
+ */
+ public static function getBoxByIdentifier($identifier) {
+ $sql = "SELECT *
+ FROM wcf".WCF_N."_box
+ WHERE identifier = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$identifier]);
+
+ return $statement->fetchObject(self::class);
+ }
+
/**
* Returns the box with the given name.
*
/**
* Returns the box with the menu id.
*
- * @param int $menuID
+ * @param int $menuID
* @return Box
*/
public static function getBoxByMenuID($menuID) {
<?php
namespace wcf\data\box;
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\box\IConditionBoxController;
use wcf\system\exception\PermissionDeniedException;
+use wcf\system\exception\UserInputException;
use wcf\system\WCF;
/**
* Executes box related actions.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage data.box
/**
* @inheritDoc
*/
- protected $requireACP = ['create', 'delete', 'update'];
+ protected $requireACP = ['create', 'delete', 'getBoxConditionsTemplate', 'update'];
+
+ /**
+ * object type for which the conditions template is fetched
+ * @var ObjectType
+ */
+ public $boxController;
/**
* @inheritDoc
parent::delete();
}
+
+ /**
+ * Validates the 'getBoxConditionsTemplate' action.
+ */
+ public function validateGetBoxConditionsTemplate() {
+ WCF::getSession()->checkPermissions(['admin.content.cms.canManageBox']);
+
+ $this->readInteger('objectTypeID');
+ $this->boxController = ObjectTypeCache::getInstance()->getObjectType($this->parameters['objectTypeID']);
+ if ($this->boxController === null) {
+ throw new UserInputException('objectTypeID');
+ }
+ }
+
+ /**
+ * Returns the template
+ *
+ * @return mixed[]
+ */
+ public function getBoxConditionsTemplate() {
+ return [
+ 'objectTypeID' => $this->boxController->objectTypeID,
+ 'template' => $this->boxController->getProcessor() instanceof IConditionBoxController ? $this->boxController->getProcessor()->getConditionsTemplate() : ''
+ ];
+ }
}
<?php
namespace wcf\data\object\type;
+use wcf\data\object\type\definition\ObjectTypeDefinition;
use wcf\data\ProcessibleDatabaseObject;
use wcf\data\TDatabaseObjectOptions;
use wcf\data\TDatabaseObjectPermissions;
use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
/**
* Represents an object type.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage data.object.type
* @category Community Framework
- *
+ *
* @property-read integer $objectTypeID
* @property-read integer $definitionID
* @property-read integer $packageID
use TDatabaseObjectPermissions;
/**
- * @see \wcf\data\DatabaseObject::$databaseTableName
+ * @inheritDoc
*/
protected static $databaseTableName = 'object_type';
/**
- * @see \wcf\data\DatabaseObject::$databaseTableIndexName
+ * @inheritDoc
*/
protected static $databaseTableIndexName = 'objectTypeID';
/**
- * @see \wcf\data\IStorableObject::__get()
+ * @inheritDoc
*/
public function __get($name) {
$value = parent::__get($name);
public final function __sleep() {
// 'processor' isn't returned since it can be an instance of
// wcf\system\SingletonFactory which may not be serialized
- return array('data');
+ return ['data'];
}
/**
- * @see \wcf\data\DatabaseObject::handleData()
+ * @inheritDoc
*/
protected function handleData($data) {
parent::handleData($data);
$this->data['additionalData'] = @unserialize($this->data['additionalData']);
if (!is_array($this->data['additionalData'])) {
- $this->data['additionalData'] = array();
+ $this->data['additionalData'] = [];
}
}
/**
- * @see \wcf\data\ProcessibleDatabaseObject::getProcessor()
+ * @inheritDoc
*/
public function getProcessor() {
if ($this->processor === null) {
throw new SystemException("'".$this->className."' does not implement '".$definitionInterface."'");
}
- if (is_subclass_of($this->className, 'wcf\system\SingletonFactory')) {
- $this->processor = call_user_func(array($this->className, 'getInstance'));
+ if (is_subclass_of($this->className, SingletonFactory::class)) {
+ $this->processor = call_user_func([$this->className, 'getInstance']);
}
else {
$this->processor = new $this->className($this);
return $this->processor;
}
+
+ /**
+ * Returns the object type definition of the object type.
+ *
+ * @return ObjectTypeDefinition
+ * @since 2.2
+ */
+ public function getDefinition() {
+ return ObjectTypeCache::getInstance()->getDefinition($this->definitionID);
+ }
}
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
abstract class AbstractBoxController implements IBoxController {
/**
protected $supportedPositions = [];
/**
- * @inheritDoc
+ * Creates a new instance of AbstractBoxController.
*/
- public function getTitle() {
- return '';
+ public function __construct() {
+ EventHandler::getInstance()->fireAction($this, '__construct');
}
/**
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\data\box\Box;
+use wcf\data\box\BoxAction;
+use wcf\data\DatabaseObjectList;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\condition\ConditionHandler;
+use wcf\system\condition\IObjectListCondition;
+use wcf\system\event\EventHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Default implementation of a box controller based on an object list.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ * @since 2.2
+ */
+abstract class AbstractDatabaseObjectListBoxController extends AbstractBoxController implements IConditionBoxController {
+ /**
+ * name of the object type definition for the box controller's condition object types
+ * @var string
+ */
+ protected $conditionDefinition = '';
+
+ /**
+ * condition objects types registered for the dynamic box controller
+ * @var ObjectType[]
+ */
+ protected $conditionObjectTypes = [];
+
+ /**
+ * default limit value for the maximum number of shown database objects
+ * if this property is null, setting a limit is disabled
+ * @var integer
+ */
+ public $defaultLimit;
+
+ /**
+ * default sort field
+ * @var string
+ */
+ public $defaultSortField;
+
+ /**
+ * limit value for the maximum number of shown database objects
+ * @var integer
+ */
+ public $limit;
+
+ /**
+ * maximum limit value, if `null` no maximum is set
+ * @var integer
+ */
+ public $maximumLimit;
+
+ /**
+ * minimum limit value
+ * @var integer
+ */
+ public $minimumLimit = 1;
+
+ /**
+ * database object list used to read the objects displayed in the box
+ * @var DatabaseObjectList
+ */
+ public $objectList;
+
+ /**
+ * name of the database table column used for sorting
+ * @var string
+ */
+ public $sortField;
+
+ /**
+ * prefix used for the titles of the sort fields
+ * @var string
+ */
+ protected $sortFieldLanguageItemPrefix;
+
+ /**
+ * order used for sorting the database objects
+ * @var string
+ */
+ public $sortOrder;
+
+ /**
+ * list of valid sort fields
+ * if this property is null, sorting is disabled
+ * @var string[]
+ */
+ public $validSortFields;
+
+ /**
+ * Creates a new instance of AbstractDynamicBoxController.
+ *
+ * @throws SystemException
+ */
+ public function __construct() {
+ if ($this->conditionDefinition) {
+ if (ObjectTypeCache::getInstance()->getDefinitionByName($this->conditionDefinition) === null) {
+ throw new SystemException("Unknown object type definition '" . $this->conditionDefinition . "'");
+ }
+
+ $this->conditionObjectTypes = ObjectTypeCache::getInstance()->getObjectTypes($this->conditionDefinition);
+ }
+
+ if (!empty($this->validSortFields)) {
+ $this->sortField = $this->defaultSortField;
+ }
+
+ if ($this->defaultLimit !== null) {
+ if ($this->defaultLimit <= 0) {
+ throw new SystemException("The default limit may has to be positive.");
+ }
+
+ $this->limit = $this->defaultLimit;
+ }
+
+ parent::__construct();
+ }
+
+ /**
+ * Returns the additional data saved with the box..
+ *
+ * @return array
+ */
+ protected function getAdditionalData() {
+ return [
+ 'limit' => $this->limit,
+ 'sortField' => $this->sortField,
+ 'sortOrder' => $this->sortOrder
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getConditionDefinition() {
+ return $this->conditionDefinition;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getConditionObjectTypes() {
+ return $this->conditionObjectTypes;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getConditionsTemplate() {
+ if ($this->defaultLimit !== null || !empty($this->validSortFields) || !empty($this->conditionObjectTypes)) {
+ return WCF::getTPL()->fetch('boxConditions', 'wcf', [
+ 'boxController' => $this,
+ 'conditionObjectTypes' => $this->conditionObjectTypes,
+ 'defaultLimit' => $this->defaultLimit,
+ 'limit' => $this->limit,
+ 'maximumLimit' => $this->maximumLimit,
+ 'minimumLimit' => $this->minimumLimit,
+ 'sortField' => $this->sortField,
+ 'sortFieldLanguageItemPrefix' => $this->sortFieldLanguageItemPrefix,
+ 'sortOrder' => $this->sortOrder,
+ 'validSortFields' => $this->validSortFields
+ ]);
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the database object list used to read the objects displayed in the box.
+ *
+ * @return DatabaseObjectList
+ */
+ abstract protected function getObjectList();
+
+ /**
+ * Returns the template to display the box.
+ *
+ * @return string
+ */
+ abstract protected function getTemplate();
+
+ /**
+ * @inheritDoc
+ */
+ public function hasContent() {
+ if ($this->objectList === null) {
+ $this->loadContent();
+ }
+
+ return count($this->objectList) > 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function loadContent() {
+ $this->objectList = $this->getObjectList();
+
+ if ($this->box->limit) {
+ $this->objectList->sqlLimit = $this->box->limit;
+ }
+
+ if ($this->box->sortOrder && $this->box->sortField) {
+ $alias = $this->objectList->getDatabaseTableAlias();
+ $this->objectList->sqlOrderBy = $this->box->sortField . ' ' . $this->box->sortOrder . ", " . ($alias ? $alias . "." : "") . $this->objectList->getDatabaseTableIndexName() . " " . $this->box->sortOrder;
+ }
+
+ if ($this->conditionDefinition) {
+ foreach ($this->box->getConditions() as $condition) {
+ /** @var IObjectListCondition $processor */
+ $processor = $condition->getObjectType()->getProcessor();
+ $processor->addObjectListCondition($this->objectList, $condition->conditionData);
+ }
+ }
+
+ $this->readObjects();
+
+ $this->content = $this->getTemplate();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readConditions() {
+ if (isset($_POST['limit'])) $this->limit = intval($_POST['limit']);
+ if (isset($_POST['sortField'])) $this->sortField = StringUtil::trim($_POST['sortField']);
+ if (isset($_POST['sortOrder'])) $this->sortOrder = StringUtil::trim($_POST['sortOrder']);
+
+ foreach ($this->conditionObjectTypes as $objectType) {
+ $objectType->getProcessor()->readFormParameters();
+ }
+ }
+
+ /**
+ * Reads the displayed database objects.
+ */
+ protected function readObjects() {
+ EventHandler::getInstance()->fireAction($this, 'readObjects');
+
+ $this->objectList->readObjects();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function saveConditions() {
+ if (($this->sortField && $this->sortOrder) || $this->limit) {
+ (new BoxAction([$this->box], 'update', [
+ 'data' => [
+ 'additionalData' => serialize(array_merge($this->box->additionalData, $this->getAdditionalData()))
+ ]
+ ]))->executeAction();
+ }
+
+ if ($this->conditionDefinition) {
+ // do not use Box::getConditions() here to avoid setting box data by internally calling
+ // Box::getController()
+ ConditionHandler::getInstance()->updateConditions($this->box->boxID, ConditionHandler::getInstance()->getConditions($this->conditionDefinition, $this->box->boxID), $this->conditionObjectTypes);
+ }
+ }
+
+ /**
+ * Sets the box the controller object belongs to and populates the condition object types
+ * with the box conditions.
+ *
+ * @param Box $box box object
+ * @param boolean $setConditionData if true, the condition object types are populated witht the box conditions' data
+ */
+ public function setBox(Box $box, $setConditionData = true) {
+ parent::setBox($box);
+
+ if ($setConditionData) {
+ $this->limit = $this->box->limit;
+ $this->sortOrder = $this->box->sortOrder;
+ $this->sortField = $this->box->sortField;
+
+ if ($this->conditionDefinition) {
+ $conditions = [];
+ foreach ($this->box->getConditions() as $condition) {
+ $conditions[$condition->objectTypeID] = $condition;
+ }
+
+ foreach ($this->conditionObjectTypes as $objectType) {
+ if (isset($conditions[$objectType->objectTypeID])) {
+ $objectType->getProcessor()->setData($conditions[$objectType->objectTypeID]);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateConditions() {
+ if ($this->defaultLimit !== null) {
+ if ($this->limit < $this->minimumLimit) {
+ throw new UserInputException('limit', 'greaterThan');
+ }
+ else if ($this->maximumLimit !== null && $this->limit > $this->maximumLimit) {
+ throw new UserInputException('limit', 'lessThan');
+ }
+ }
+
+ if (!empty($this->validSortFields)) {
+ if (!in_array($this->sortField, $this->validSortFields)) {
+ throw new UserInputException('sorting', 'sortFieldNotValid');
+ }
+
+ if ($this->sortOrder !== 'ASC' && $this->sortOrder !== 'DESC') {
+ throw new UserInputException('sorting', 'sortOrderNotValid');
+ }
+ }
+
+ foreach ($this->conditionObjectTypes as $objectType) {
+ $objectType->getProcessor()->validate();
+ }
+ }
+}
namespace wcf\system\box;
use wcf\data\box\Box;
use wcf\data\box\BoxList;
+use wcf\data\condition\ConditionAction;
+use wcf\system\exception\SystemException;
use wcf\system\request\RequestHandler;
use wcf\system\SingletonFactory;
+use wcf\system\WCF;
/**
* Handles boxes.
}
}
+ /**
+ * Creates a new condition for an existing box.
+ *
+ * Note: The primary use of this method is to be used during package installation.
+ *
+ * @param string $boxIdentifier
+ * @param string $conditionDefinition
+ * @param string $conditionObjectType
+ * @param array $conditionData
+ * @throws SystemException
+ */
+ public function createBoxCondition($boxIdentifier, $conditionDefinition, $conditionObjectType, array $conditionData) {
+ // do not rely on caches during package installation
+ $sql = "SELECT objectTypeID
+ FROM wcf".WCF_N."_object_type object_type
+ INNER JOIN wcf".WCF_N."_object_type_definition object_type_definition
+ ON (object_type.definitionID = object_type_definition.definitionID)
+ WHERE objectType = ?
+ AND definitionName = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$conditionObjectType, $conditionDefinition]);
+ $objectTypeID = $statement->fetchSingleColumn();
+
+ if (!$objectTypeID) {
+ throw new SystemException("Unknown box condition '{$conditionObjectType}' of condition definition '{$conditionDefinition}'");
+ }
+
+ $box = Box::getBoxByIdentifier($boxIdentifier);
+ if ($box === null) {
+ throw new SystemException("Unknown box with idenifier '{$boxIdentifier}'");
+ }
+
+ (new ConditionAction([], 'create', [
+ 'data' => [
+ 'conditionData' => serialize($conditionData),
+ 'objectID' => $box->boxID,
+ 'objectTypeID' => $objectTypeID
+ ]
+ ]))->executeAction();
+ }
+
/**
* Returns boxes for the given position.
*
/**
* Lists online users the active user is following.
- *
+ *
* @author Marcel Werk
* @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
-class FollowingsOnlineBoxController extends AbstractBoxController {
+class FollowingsOnlineBoxController extends AbstractDatabaseObjectListBoxController {
+ /**
+ * @inheritDoc
+ */
+ public $defaultLimit = 10;
+
/**
* @inheritDoc
*/
/**
* @inheritDoc
*/
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.user.followingsOnline'); // @todo
+ protected function getObjectList() {
+ $objectList = new UsersOnlineList();
+ $objectList->getConditionBuilder()->add('session.userID IN (?)', [WCF::getUserProfileHandler()->getFollowingUsers()]);
+
+ return $objectList;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getTemplate() {
+ return WCF::getTPL()->fetch('boxFollowingsOnline', 'wcf', ['usersOnlineList' => $this->objectList]);
}
/**
* @inheritDoc
*/
- protected function loadContent() {
- if (MODULE_USERS_ONLINE && WCF::getSession()->getPermission('user.profile.canViewUsersOnlineList') && count(WCF::getUserProfileHandler()->getFollowingUsers())) {
- $usersOnlineList = new UsersOnlineList();
- $usersOnlineList->getConditionBuilder()->add('session.userID IN (?)', array(WCF::getUserProfileHandler()->getFollowingUsers()));
- $usersOnlineList->sqlLimit = 10;
- $usersOnlineList->readObjects();
-
- if (count($usersOnlineList)) {
- WCF::getTPL()->assign([
- 'usersOnlineList' => $usersOnlineList
- ]);
-
- $this->content = WCF::getTPL()->fetch('boxFollowingsOnline');
- }
+ public function hasContent() {
+ if (!MODULE_USERS_ONLINE || !WCF::getSession()->getPermission('user.profile.canViewUsersOnlineList') || empty(WCF::getUserProfileHandler()->getFollowingUsers())) {
+ return false;
}
+
+ return parent::hasContent();
}
}
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
interface IBoxController {
- /**
- * Returns the title of this box.
- *
- * @return string
- */
- public function getTitle();
-
/**
* Returns the content of this box.
*
- * @return string
+ * @return string
*/
public function getContent();
/**
* Sets the database object of this box.
*
- * @param Box $box
+ * @param Box $box
*/
public function setBox(Box $box);
/**
* Returns a list of supported box positions.
*
- * @return string[]
+ * @return string[]
*/
public function getSupportedPositions();
}
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\data\object\type\ObjectType;
+
+/**
+ * Interface for dynamic box controller.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ * @since 2.2
+ */
+interface IConditionBoxController extends IBoxController {
+ /**
+ * Returns the name of the object type definition for the box controller's condition object types.
+ *
+ * @return string
+ */
+ public function getConditionDefinition();
+
+ /**
+ * Returns the condition objects types registered for the dynamic box controller.
+ *
+ * @return ObjectType[]
+ */
+ public function getConditionObjectTypes();
+
+ /**
+ * Returns the template containing the box conditions.
+ *
+ * @return string
+ */
+ public function getConditionsTemplate();
+
+ /**
+ * Reads the box conditions.
+ */
+ public function readConditions();
+
+ /**
+ * Saves the conditions for the box.
+ */
+ public function saveConditions();
+
+ /**
+ * Validates the read conditions for the box.
+ */
+ public function validateConditions();
+}
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\data\DatabaseObject;
-use wcf\system\cache\builder\MostActiveMembersCacheBuilder;
-use wcf\system\cache\runtime\UserProfileRuntimeCache;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-
-/**
- * Shows a list of the most active members.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class MostActiveMembersBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.mostActiveMembers'); // @todo
- }
-
- /**
- * @inheritDoc
- */
- public function hasLink() {
- if (MODULE_MEMBERS_LIST) {
- return true;
- }
-
- return false;
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- if (MODULE_MEMBERS_LIST) {
- return LinkHandler::getInstance()->getLink('MembersList', [], 'sortField=activityPoints&sortOrder=DESC');
- }
-
- return '';
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- // get ids
- $mostActiveMemberIDs = MostActiveMembersCacheBuilder::getInstance()->getData();
- if (!empty($mostActiveMemberIDs)) {
- UserProfileRuntimeCache::getInstance()->cacheObjectIDs($mostActiveMemberIDs);
-
- // get users
- $mostActiveMembers = UserProfileRuntimeCache::getInstance()->getObjects($mostActiveMemberIDs);
- DatabaseObject::sort($mostActiveMembers, 'activityPoints', 'DESC');
-
- WCF::getTPL()->assign([
- 'mostActiveMembers' => $mostActiveMembers
- ]);
- $this->content = WCF::getTPL()->fetch('boxMostActiveMembers');
- }
- }
-}
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\data\DatabaseObject;
-use wcf\system\cache\builder\MostLikedMembersCacheBuilder;
-use wcf\system\cache\runtime\UserProfileRuntimeCache;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-
-/**
- * Shows a list of the most liked members.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class MostLikedMembersBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.mostLikedMembers'); // @todo
- }
-
- /**
- * @inheritDoc
- */
- public function hasLink() {
- if (MODULE_MEMBERS_LIST) {
- return true;
- }
-
- return false;
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- if (MODULE_MEMBERS_LIST) {
- return LinkHandler::getInstance()->getLink('MembersList', [], 'sortField=likesReceived&sortOrder=DESC');
- }
-
- return '';
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- // get ids
- $mostLikedMemberIDs = MostLikedMembersCacheBuilder::getInstance()->getData();
- if (!empty($mostLikedMemberIDs)) {
- UserProfileRuntimeCache::getInstance()->cacheObjectIDs($mostLikedMemberIDs);
-
- // get users
- $mostLikedMembers = UserProfileRuntimeCache::getInstance()->getObjects($mostLikedMemberIDs);
- DatabaseObject::sort($mostLikedMembers, 'likesReceived', 'DESC');
-
- WCF::getTPL()->assign([
- 'mostLikedMembers' => $mostLikedMembers
- ]);
- $this->content = WCF::getTPL()->fetch('boxMostLikedMembers');
- }
- }
-}
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\data\DatabaseObject;
-use wcf\system\cache\builder\NewestMembersCacheBuilder;
-use wcf\system\cache\runtime\UserProfileRuntimeCache;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-
-/**
- * Shows a list of the newest members.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class NewestMembersBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.newestMembers'); // @todo
- }
-
- /**
- * @inheritDoc
- */
- public function hasLink() {
- if (MODULE_MEMBERS_LIST) {
- return true;
- }
-
- return false;
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- if (MODULE_MEMBERS_LIST) {
- return LinkHandler::getInstance()->getLink('MembersList', [], 'sortField=registrationDate&sortOrder=DESC');
- }
-
- return '';
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- // get ids
- $newestMemberIDs = NewestMembersCacheBuilder::getInstance()->getData();
- if (!empty($newestMemberIDs)) {
- UserProfileRuntimeCache::getInstance()->cacheObjectIDs($newestMemberIDs);
-
- // get users
- $newestMembers = UserProfileRuntimeCache::getInstance()->getObjects($newestMemberIDs);
- DatabaseObject::sort($newestMembers, 'registrationDate', 'DESC');
-
- WCF::getTPL()->assign([
- 'newestMembers' => $newestMembers
- ]);
- $this->content = WCF::getTPL()->fetch('boxNewestMembers');
- }
- }
-}
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\system\comment\CommentHandler;
+use wcf\system\request\RequestHandler;
+use wcf\system\WCF;
+
+/**
+ * Box for the comments of the active page.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ */
+class PageCommentListBoxController extends AbstractDatabaseObjectListBoxController {
+ /**
+ * @inheritDoc
+ */
+ protected $supportedPositions = ['contentTop', 'contentBottom'];
+
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList() {
+ $commentObjectTypeID = CommentHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.page');
+ $commentManager = CommentHandler::getInstance()->getObjectType($commentObjectTypeID)->getProcessor();
+
+ return CommentHandler::getInstance()->getCommentList($commentManager, $commentObjectTypeID, RequestHandler::getInstance()->getActiveRequest()->getPageID(), false);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getTemplate() {
+ return WCF::getTPL()->fetch('boxPageComments', 'wcf', [
+ 'commentCanAdd' => WCF::getSession()->getPermission('user.pageComment.canAddComment'),
+ 'commentList' => $this->objectList,
+ 'commentObjectTypeID' => CommentHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.page'),
+ 'lastCommentTime' => $this->objectList->getMinCommentTime(),
+ 'pageID' => RequestHandler::getInstance()->getActiveRequest()->getPageID()
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasContent() {
+ return WCF::getSession()->getPermission('user.pageComment.canAddComment') || parent::hasContent();
+ }
+}
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\system\comment\CommentHandler;
-use wcf\system\request\RequestHandler;
-use wcf\system\WCF;
-
-/**
- * Box for page comments.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class PageCommentsBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['contentTop', 'contentBottom'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.comments');
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- $commentObjectTypeID = CommentHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.page');
- $commentManager = CommentHandler::getInstance()->getObjectType($commentObjectTypeID)->getProcessor();
- $commentList = CommentHandler::getInstance()->getCommentList($commentManager, $commentObjectTypeID, RequestHandler::getInstance()->getActiveRequest()->getPageID());
-
- if (WCF::getSession()->getPermission('user.pageComment.canAddComment') || count($commentList)) {
- WCF::getTPL()->assign([
- 'pageID' => RequestHandler::getInstance()->getActiveRequest()->getPageID(),
- 'commentCanAdd' => WCF::getSession()->getPermission('user.pageComment.canAddComment'),
- 'commentList' => $commentList,
- 'commentObjectTypeID' => $commentObjectTypeID,
- 'lastCommentTime' => $commentList->getMinCommentTime()
- ]);
-
- $this->content = WCF::getTPL()->fetch('boxPageComments');
- }
- }
-}
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
class PaidSubscriptionsBoxController extends AbstractBoxController {
/**
*/
protected $supportedPositions = ['contentTop', 'contentBottom', 'sidebarLeft', 'sidebarRight'];
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.user.menu.settings.paidSubscription');
- }
-
/**
* @inheritDoc
*/
$this->content = WCF::getTPL()->fetch($templateName);
}
-
}
}
}
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\data\user\activity\event\ViewableUserActivityEventList;
-use wcf\system\request\LinkHandler;
-use wcf\system\user\activity\event\UserActivityEventHandler;
-use wcf\system\WCF;
-
-/**
- * Box for recent activities.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class RecentActivityBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['contentTop', 'contentBottom', 'sidebarLeft', 'sidebarRight'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.user.recentActivity');
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return LinkHandler::getInstance()->getLink('RecentActivityList');
- }
-
- /**
- * @inheritDoc
- */
- public function hasLink() {
- return true;
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- if ($this->getBox()->position == 'contentTop' || $this->getBox()->position == 'contentBottom') {
- $canFilterByFollowedUsers = $filteredByFollowedUsers = false;
- if (WCF::getUser()->userID && count(WCF::getUserProfileHandler()->getFollowingUsers())) {
- $canFilterByFollowedUsers = true;
- }
-
- $eventList = new ViewableUserActivityEventList();
- if ($canFilterByFollowedUsers && WCF::getUser()->recentActivitiesFilterByFollowing) {
- $filteredByFollowedUsers = true;
- $eventList->getConditionBuilder()->add('user_activity_event.userID IN (?)', [WCF::getUserProfileHandler()->getFollowingUsers()]);
- }
- $eventList->sqlLimit = RECENT_ACTIVITY_ITEMS;
- $eventList->readObjects();
- $lastEventTime = $eventList->getLastEventTime();
-
- // removes orphaned and non-accessable events
- UserActivityEventHandler::validateEvents($eventList);
-
- if (count($eventList) || $filteredByFollowedUsers) {
- WCF::getTPL()->assign([
- 'canFilterByFollowedUsers' => $canFilterByFollowedUsers,
- 'eventList' => $eventList, 'lastEventTime' => $lastEventTime,
- 'filteredByFollowedUsers' => $filteredByFollowedUsers
- ]);
-
- $this->content = WCF::getTPL()->fetch('boxRecentActivity');
- }
- }
- else {
- $eventList = new ViewableUserActivityEventList();
- $eventList->sqlLimit = RECENT_ACTIVITY_SIDEBAR_ITEMS;
- $eventList->readObjects();
-
- // removes orphaned and non-accessable events
- UserActivityEventHandler::validateEvents($eventList);
-
- if (count($eventList)) {
- WCF::getTPL()->assign([
- 'eventList' => $eventList
- ]);
-
- $this->content = WCF::getTPL()->fetch('boxRecentActivitySidebar');
- }
- }
- }
-}
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\data\user\activity\event\ViewableUserActivityEventList;
+use wcf\system\request\LinkHandler;
+use wcf\system\user\activity\event\UserActivityEventHandler;
+use wcf\system\WCF;
+
+/**
+ * Box controller for a list of recent activities.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ * @since 2.2
+ */
+class RecentActivityListBoxController extends AbstractDatabaseObjectListBoxController {
+ /**
+ * is true if the list of recent activity can be filtered to only include
+ * activities by followed users
+ * @var boolean
+ */
+ public $canFilterByFollowedUsers = false;
+
+ /**
+ * is true if the list of recent activity is filtered to only include
+ * activities by followed users
+ * @var boolean
+ */
+ public $filteredByFollowedUsers = false;
+
+ /**
+ * @inheritDoc
+ */
+ public $defaultLimit = 10;
+
+ /**
+ * @inheritDoc
+ */
+ public $maximumLimit = 50;
+
+ /**
+ * @inheritDoc
+ */
+ public $minimumLimit = 5;
+
+ /**
+ * @inheritDoc
+ */
+ protected $supportedPositions = ['contentTop', 'contentBottom', 'sidebarLeft', 'sidebarRight'];
+
+ /**
+ * @inheritDoc
+ */
+ public function __construct() {
+ if (WCF::getUser()->userID && count(WCF::getUserProfileHandler()->getFollowingUsers())) {
+ $this->canFilterByFollowedUsers = true;
+ }
+
+ if ($this->canFilterByFollowedUsers && WCF::getUser()->recentActivitiesFilterByFollowing) {
+ $this->filteredByFollowedUsers = true;
+ }
+
+ parent::__construct();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink() {
+ return LinkHandler::getInstance()->getLink('RecentActivityList');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList() {
+ return new ViewableUserActivityEventList();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTemplate() {
+ if ($this->getBox()->position == 'contentTop' || $this->getBox()->position == 'contentBottom') {
+ return WCF::getTPL()->fetch('boxRecentActivity', 'wcf', [
+ 'canFilterByFollowedUsers' => $this->canFilterByFollowedUsers,
+ 'eventList' => $this->objectList,
+ 'lastEventTime' => $this->objectList->getLastEventTime(),
+ 'filteredByFollowedUsers' => $this->filteredByFollowedUsers
+ ]);
+ }
+ else {
+ return WCF::getTPL()->fetch('boxRecentActivitySidebar', 'wcf', [
+ 'eventList' => $this->objectList
+ ]);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasLink() {
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function readObjects() {
+ // apply filter
+ if (($this->getBox()->position == 'contentTop' || $this->getBox()->position == 'contentBottom') && $this->filteredByFollowedUsers) {
+ $this->objectList->getConditionBuilder()->add('user_activity_event.userID IN (?)', [WCF::getUserProfileHandler()->getFollowingUsers()]);
+ }
+
+ parent::readObjects();
+
+ // removes orphaned and non-accessable events
+ UserActivityEventHandler::validateEvents($this->objectList);
+ }
+}
/**
* Box that shows the register button.
- *
+ *
* @author Marcel Werk
* @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
class RegisterButtonBoxController extends AbstractBoxController {
/**
*/
protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.user.register');
- }
-
/**
* @inheritDoc
*/
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
class SignedInAsBoxController extends AbstractBoxController {
/**
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\data\user\online\UsersOnlineList;
-use wcf\system\WCF;
-
-/**
- * Lists staff members who are online.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class StaffOnlineBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.user.staffOnline'); // @todo
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- if (MODULE_USERS_ONLINE && WCF::getSession()->getPermission('user.profile.canViewUsersOnlineList')) {
- $usersOnlineList = new UsersOnlineList();
- $usersOnlineList->getConditionBuilder()->add('session.userID IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID IN (SELECT groupID FROM wcf'.WCF_N.'_user_group WHERE showOnTeamPage = ?))', array(1));
- $usersOnlineList->readObjects();
-
- if (count($usersOnlineList)) {
- WCF::getTPL()->assign([
- 'usersOnlineList' => $usersOnlineList
- ]);
-
- $this->content = WCF::getTPL()->fetch('boxStaffOnline');
- }
- }
- }
-}
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\data\user\online\UsersOnlineList;
+use wcf\system\WCF;
+
+/**
+ * Box controller for a list of staff members who are currently online.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ * @since 2.2
+ */
+class StaffOnlineListBoxController extends AbstractDatabaseObjectListBoxController {
+ /**
+ * @inheritDoc
+ */
+ protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
+
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList() {
+ $objectList = new UsersOnlineList();
+ $objectList->getConditionBuilder()->add('session.userID IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID IN (SELECT groupID FROM wcf'.WCF_N.'_user_group WHERE showOnTeamPage = ?))', [1]);
+
+ return $objectList;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getTemplate() {
+ return WCF::getTPL()->fetch('boxStaffOnline', 'wcf', ['usersOnlineList' => $this->objectList]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasContent() {
+ if (!MODULE_USERS_ONLINE || WCF::getSession()->getPermission('user.profile.canViewUsersOnlineList')) {
+ return false;
+ }
+
+ return parent::hasContent();
+ }
+}
\ No newline at end of file
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
class StatisticsBoxController extends AbstractBoxController {
/**
*/
protected $supportedPositions = ['sidebarLeft', 'sidebarRight'];
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.statistics'); // @todo
- }
-
/**
* @inheritDoc
*/
*/
protected $neededPermission = '';
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.tagging.tags');
- }
-
/**
* @inheritDoc
*/
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
class TodaysBirthdaysBoxController extends AbstractBoxController {
/**
* @var string
*/
protected $templateName = 'boxTodaysBirthdays';
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.todaysBirthdays'); // @todo
- }
/**
* @inheritDoc
*
* @param integer[] $userIDs
*/
- protected function filterUserIDs(&$userIDs) {}
+ protected function filterUserIDs(&$userIDs) {
+ // does nothing, can be overwritten by child classes
+ }
}
* @package com.woltlab.wcf
* @subpackage system.box
* @category Community Framework
+ * @since 2.2
*/
class TodaysFollowingBirthdaysBoxController extends TodaysBirthdaysBoxController {
/**
*/
protected $templateName = 'boxTodaysFollowingBirthdays';
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.page.todaysFollowingBirthdays'); // @todo
- }
-
/**
* @inheritDoc
*/
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\data\DatabaseObject;
+use wcf\data\user\UserProfileList;
+use wcf\system\cache\builder\MostActiveMembersCacheBuilder;
+use wcf\system\cache\builder\MostLikedMembersCacheBuilder;
+use wcf\system\cache\builder\NewestMembersCacheBuilder;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
+use wcf\system\event\EventHandler;
+use wcf\system\request\LinkHandler;
+use wcf\system\WCF;
+
+/**
+ * Box controller for a list of users.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ * @since 2.2
+ */
+class UserListBoxController extends AbstractDatabaseObjectListBoxController {
+ /**
+ * maps special sort fields to cache builders
+ * @var string[]
+ */
+ public $cacheBuilders = [
+ 'activityPoints' => MostActiveMembersCacheBuilder::class,
+ 'likesReceived' => MostLikedMembersCacheBuilder::class,
+ 'registrationDate' => NewestMembersCacheBuilder::class
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ protected $sortFieldLanguageItemPrefix = 'wcf.user';
+
+ /**
+ * ids of the shown users loaded from cache
+ * @var integer[]|null
+ */
+ public $userIDs;
+
+ /**
+ * @inheritDoc
+ */
+ public $validSortFields = [
+ 'username',
+ 'activityPoints',
+ 'registrationDate'
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ public function __construct() {
+ if (!empty($this->validSortFields) && MODULE_LIKE) {
+ $this->validSortFields[] = 'likesReceived';
+ }
+
+ parent::__construct();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink() {
+ if (MODULE_MEMBERS_LIST) {
+ $parameters = '';
+ if ($this->box->sortField) {
+ $parameters = 'sortField='.$this->box->sortField.'&sortOrder='.$this->box->sortOrder;
+ }
+
+ return LinkHandler::getInstance()->getLink('MembersList', [], $parameters);
+ }
+
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList() {
+ // use specialized cache builders
+ if ($this->box->sortOrder && $this->box->sortField && isset($this->cacheBuilders[$this->box->sortField])) {
+ $this->userIDs = $this->cacheBuilders[$this->box->sortField]::getInstance()->getData([
+ 'limit' => $this->box->limit,
+ 'sortOrder' => $this->sortOrder
+ ]);
+ }
+
+ if ($this->userIDs !== null) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($this->userIDs);
+ }
+
+ return new UserProfileList();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getTemplate() {
+ if ($this->userIDs !== null) {
+ $userProfiles = UserProfileRuntimeCache::getInstance()->getObjects($this->userIDs);
+
+ DatabaseObject::sort($userProfiles, $this->sortField, $this->sortOrder);
+ }
+
+ return WCF::getTPL()->fetch('boxUserList', 'wcf', [
+ 'boxUsers' => $this->userIDs !== null ? $userProfiles : $this->objectList->getObjects(),
+ 'boxSortField' => $this->box->sortField
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasContent() {
+ $hasContent = parent::hasContent();
+
+ if ($this->userIDs !== null) {
+ return !empty($this->userIDs);
+ }
+
+ return $hasContent;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasLink() {
+ return MODULE_MEMBERS_LIST == 1;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjects() {
+ if ($this->userIDs === null) {
+ parent::readObjects();
+ }
+ else {
+ EventHandler::getInstance()->fireAction($this, 'readObjects');
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\box;
+use wcf\data\user\online\UsersOnlineList;
+use wcf\system\WCF;
+
+/**
+ * Box controller for a list of registered users who are currently online.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.box
+ * @category Community Framework
+ * @since 2.2
+ */
+class UserOnlineListBoxController extends AbstractDatabaseObjectListBoxController {
+ /**
+ * @inheritDoc
+ */
+ protected $supportedPositions = ['footerBoxes', 'sidebarLeft', 'sidebarRight'];
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink() {
+ return LinkHandler::getInstance()->getLink('UsersOnlineList');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList() {
+ $objectList = new UsersOnlineList();
+ $objectList->readStats();
+ $objectList->checkRecord();
+ $objectList->getConditionBuilder()->add('session.userID IS NOT NULL');
+
+ return $objectList;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getTemplate() {
+ $templateName = 'boxUsersOnlineSidebar';
+ if ($this->getBox()->position == 'footerBoxes') {
+ $templateName = 'boxUsersOnline';
+ }
+
+ return WCF::getTPL()->fetch($templateName, 'wcf', ['usersOnlineList' => $this->objectList]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasContent() {
+ if (!MODULE_USERS_ONLINE || WCF::getSession()->getPermission('user.profile.canViewUsersOnlineList')) {
+ return false;
+ }
+
+ return parent::hasContent();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasLink() {
+ return true;
+ }
+}
\ No newline at end of file
+++ /dev/null
-<?php
-namespace wcf\system\box;
-use wcf\data\user\online\UsersOnlineList;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-
-/**
- * Lists all users who are online.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.box
- * @category Community Framework
- */
-class UsersOnlineBoxController extends AbstractBoxController {
- /**
- * @inheritDoc
- */
- protected $supportedPositions = ['footerBoxes', 'sidebarLeft', 'sidebarRight'];
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return WCF::getLanguage()->get('wcf.user.usersOnline'); // @todo
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return LinkHandler::getInstance()->getLink('UsersOnlineList');
- }
-
- /**
- * @inheritDoc
- */
- public function hasLink() {
- return true;
- }
-
- /**
- * @inheritDoc
- */
- protected function loadContent() {
- if (MODULE_USERS_ONLINE && WCF::getSession()->getPermission('user.profile.canViewUsersOnlineList')) {
- $usersOnlineList = new UsersOnlineList();
- $usersOnlineList->readStats();
- $usersOnlineList->checkRecord();
- $usersOnlineList->getConditionBuilder()->add('session.userID IS NOT NULL');
- $usersOnlineList->readObjects();
-
- if (count($usersOnlineList)) {
- if ($this->getBox()->position == 'footerBoxes') {
- $templateName = 'boxUsersOnline';
- }
- else {
- $templateName = 'boxUsersOnlineSidebar';
- }
-
- WCF::getTPL()->assign([
- 'usersOnlineList' => $usersOnlineList
- ]);
-
- $this->content = WCF::getTPL()->fetch($templateName);
- }
- }
- }
-}
--- /dev/null
+<?php
+namespace wcf\system\cache\builder;
+use wcf\data\user\UserList;
+
+/**
+ * Caches a list of the newest members.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.cache.builder
+ * @category Community Framework
+ * @since 2.2
+ */
+abstract class AbstractSortedUserCacheBuilder extends AbstractCacheBuilder {
+ /**
+ * default limit value if no limit parameter is provided
+ * @var integer
+ */
+ protected $defaultLimit = 5;
+
+ /**
+ * default sort order if no sort order parameter is provided
+ * @var string
+ */
+ protected $defaultSortOrder = 'DESC';
+
+ /**
+ * @inheritDoc
+ */
+ protected $maxLifetime = 300;
+
+ /**
+ * if `true`, only positive values of the database column will be considered
+ * @var boolean
+ */
+ protected $positiveValuesOnly = false;
+
+ /**
+ * database table column used for sorting
+ * @var string
+ */
+ protected $sortField;
+
+ /**
+ * @inheritDoc
+ */
+ protected function rebuild(array $parameters) {
+ $sortOrder = $this->defaultSortOrder;
+ if (!empty($parameters['sortOrder'])) {
+ $sortOrder = $parameters['sortOrder'];
+ }
+
+ $userProfileList = new UserList();
+ if ($this->positiveValuesOnly) {
+ $userProfileList->getConditionBuilder()->add('user_table.'.$this->sortField.' > ?', [0]);
+ }
+ $userProfileList->sqlOrderBy = 'user_table.'.$this->sortField.' '.$sortOrder;
+ $userProfileList->sqlLimit = !empty($parameters['limit']) ? $parameters['limit'] : $this->defaultLimit;
+ $userProfileList->readObjectIDs();
+
+ return $userProfileList->getObjectIDs();
+ }
+}
* Caches a list of the most active members.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage system.cache.builder
* @category Community Framework
*/
-class MostActiveMembersCacheBuilder extends AbstractCacheBuilder {
+class MostActiveMembersCacheBuilder extends AbstractSortedUserCacheBuilder {
/**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::$maxLifetime
+ * @inheritDoc
*/
protected $maxLifetime = 600;
/**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
+ * @inheritDoc
*/
- protected function rebuild(array $parameters) {
- $userProfileList = new UserList();
- $userProfileList->getConditionBuilder()->add('user_table.activityPoints > 0');
- $userProfileList->sqlOrderBy = 'user_table.activityPoints DESC';
- $userProfileList->sqlLimit = 5;
- $userProfileList->readObjectIDs();
-
- return $userProfileList->getObjectIDs();
- }
+ protected $positiveValuesOnly = true;
+
+ /**
+ * @inheritDoc
+ */
+ protected $sortField = 'activityPoints';
}
<?php
namespace wcf\system\cache\builder;
-use wcf\data\user\UserList;
/**
* Caches a list of the most liked members.
*
- * @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage system.cache.builder
* @category Community Framework
*/
-class MostLikedMembersCacheBuilder extends AbstractCacheBuilder {
+class MostLikedMembersCacheBuilder extends AbstractSortedUserCacheBuilder {
/**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::$maxLifetime
+ * @inheritDoc
*/
protected $maxLifetime = 600;
/**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
+ * @inheritDoc
*/
- protected function rebuild(array $parameters) {
- $userProfileList = new UserList();
- $userProfileList->getConditionBuilder()->add('user_table.likesReceived > 0');
- $userProfileList->sqlOrderBy = 'user_table.likesReceived DESC';
- $userProfileList->sqlLimit = 5;
- $userProfileList->readObjectIDs();
-
- return $userProfileList->getObjectIDs();
- }
+ protected $positiveValuesOnly = true;
+
+ /**
+ * @inheritDoc
+ */
+ protected $sortField = 'likesReceived';
}
<?php
namespace wcf\system\cache\builder;
-use wcf\data\user\UserList;
/**
* Caches a list of the newest members.
*
- * @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage system.cache.builder
* @category Community Framework
*/
-class NewestMembersCacheBuilder extends AbstractCacheBuilder {
+class NewestMembersCacheBuilder extends AbstractSortedUserCacheBuilder {
/**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::$maxLifetime
+ * @inheritDoc
*/
- protected $maxLifetime = 300;
-
- /**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
- */
- protected function rebuild(array $parameters) {
- $userProfileList = new UserList();
- $userProfileList->sqlOrderBy = 'user_table.registrationDate DESC';
- $userProfileList->sqlLimit = 5;
- $userProfileList->readObjectIDs();
-
- return $userProfileList->getObjectIDs();
- }
+ protected $sortField = 'registrationDate';
}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\DatabaseObject;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a condition realized by a checkbox.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ * @since 2.2
+ */
+abstract class AbstractCheckboxCondition extends AbstractSingleFieldCondition {
+ /**
+ * name of the checkbox
+ * @var string
+ */
+ protected $fieldName;
+
+ /**
+ * is `1` if the checkbox is checked
+ * @var integer
+ */
+ protected $fieldValue = 0;
+
+ /**
+ * @inheritDoc
+ * @throws SystemException
+ */
+ public function __construct(DatabaseObject $object) {
+ parent::__construct($object);
+
+ if ($this->fieldName === null) {
+ throw new SystemException("Field name has not been set.");
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getData() {
+ if ($this->fieldValue) {
+ return [$this->fieldName => $this->fieldValue];
+ }
+
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getFieldElement() {
+ return '<label><input type="checkbox" name="' . $this->fieldName . '" id="' . $this->fieldName . '"'.($this->fieldValue ? ' checked="checked"' : '').' /> '.WCF::getLanguage()->get($this->label).'</label>';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getLabel() {
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readFormParameters() {
+ if (!empty($_POST[$this->fieldName])) $this->fieldValue = 1;
+ else $this->fieldValue = 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function reset() {
+ $this->fieldValue = 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function setData(Condition $condition) {
+ $this->fieldValue = $condition->{$this->fieldName};
+ }
+}
\ No newline at end of file
* Returns the data saved with the condition used to check if the condition
* is fulfilled. If null is returned, there is no condition to be created.
*
- * @return mixed
+ * @return array|null
*/
public function getData();
namespace wcf\system\package\plugin;
use wcf\data\box\Box;
use wcf\data\box\BoxEditor;
+use wcf\data\object\type\ObjectType;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\SystemException;
use wcf\system\language\LanguageFactory;
*/
protected $content = [];
+ /**
+ * list of element names which are not considered as additional data
+ * @var string[]
+ */
+ public static $reservedTags = ['boxType', 'content', 'cssClassName', 'name', 'objectType', 'position', 'showHeader', 'visibilityExceptions', 'visibleEverywhere'];
+
/**
* @inheritDoc
*/
protected function getElement(\DOMXPath $xpath, array &$elements, \DOMElement $element) {
$nodeValue = $element->nodeValue;
- if ($element->tagName === 'name' || $element->tagName === 'title') {
+ if ($element->tagName === 'name') {
if (empty($element->getAttribute('language'))) {
throw new SystemException("Missing required attribute 'language' for '" . $element->tagName . "' element (box '" . $element->parentNode->getAttribute('identifier') . "')");
}
if (empty($children['title'])) {
throw new SystemException("Expected non-empty child element 'title' for 'content' element (box '" . $element->parentNode->getAttribute('identifier') . "')");
}
- if (empty($children['content'])) {
- throw new SystemException("Expected non-empty child element 'content' for 'content' element (box '" . $element->parentNode->getAttribute('identifier') . "')");
- }
$elements['content'][$element->getAttribute('language')] = [
- 'content' => $children['content'],
+ 'content' => isset($children['content']) ? $children['content'] : '',
'title' => $children['title']
];
}
protected function prepareImport(array $data) {
$content = [];
$boxType = $data['elements']['boxType'];
- $controller = '';
+ $objectTypeID = null;
$identifier = $data['attributes']['identifier'];
$isMultilingual = false;
$position = $data['elements']['position'];
throw new SystemException("Unknown box position '{$position}' for box '{$identifier}'");
}
+ $ignoreMissingContent = false;
switch ($boxType) {
case 'system':
- if (empty($data['elements']['controller'])) {
- throw new SystemException("Missing required element 'controller' for 'system'-type box '{$identifier}'");
+ if (empty($data['elements']['objectType'])) {
+ throw new SystemException("Missing required element 'objectType' for 'system'-type box '{$identifier}'");
}
- $controller = $data['elements']['controller'];
- break;
+ $sql = "SELECT objectTypeID
+ FROM wcf".WCF_N."_object_type object_type
+ LEFT JOIN wcf".WCF_N."_object_type_definition object_type_definition
+ ON (object_type_definition.definitionID = object_type.definitionID)
+ WHERE objectType = ?
+ AND definitionName = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$data['elements']['objectType'], 'com.woltlab.wcf.boxController']);
+ $objectTypeID = $statement->fetchSingleColumn();
+ if (!$objectTypeID) {
+ throw new SystemException("Unknown object type '{$data['elements']['objectType']}' for 'system'-type box '{$identifier}'");
+ }
+
+ $ignoreMissingContent = true;
+
+ // fallthrough
case 'html':
case 'text':
case 'tpl':
if (empty($data['elements']['content'])) {
+ if ($ignoreMissingContent) {
+ break;
+ }
+
throw new SystemException("Missing required 'content' element(s) for box '{$identifier}'");
}
$this->visibilityExceptions[$identifier] = $data['elements']['visibilityExceptions'];
}
+ $additionalData = [];
+ foreach ($data['elements'] as $tagName => $nodeValue) {
+ if (!in_array($tagName, self::$reservedTags)) {
+ $additionalData[$tagName] = $nodeValue;
+ }
+ }
+
return [
'identifier' => $identifier,
'content' => $content,
'cssClassName' => (!empty($data['elements']['cssClassName'])) ? $data['elements']['cssClassName'] : '',
'showHeader' => (!empty($data['elements']['showHeader'])) ? 1 : 0,
'originIsSystem' => 1,
- 'controller' => $controller
+ 'objectTypeID' => $objectTypeID,
+ 'additionalData' => serialize($additionalData)
];
}
FROM wcf".WCF_N."_box
WHERE identifier = ?
AND packageID = ?";
- $parameters = array(
+ $parameters = [
$data['identifier'],
$this->installation->getPackageID()
- );
+ ];
- return array(
+ return [
'sql' => $sql,
'parameters' => $parameters
- );
+ ];
}
/**
$deleteStatement = WCF::getDB()->prepareStatement($sql);
$sql = "INSERT IGNORE wcf".WCF_N."_box_to_page
(boxID, pageID, visible)
- VALUES (?, ?, ?)";
+ VALUES (?, ?, ?)";
$insertStatement = WCF::getDB()->prepareStatement($sql);
foreach ($this->visibilityExceptions as $boxIdentifier => $pages) {
// delete old visibility exceptions
// get page ids
$conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('identifier IN (?)', array($pages));
+ $conditionBuilder->add('identifier IN (?)', [$pages]);
$sql = "SELECT pageID
FROM wcf".WCF_N."_page
".$conditionBuilder;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
$pageIDs = [];
- while ($row = $statement->fetchArray()) {
- $pageIDs[] = $row['pageID'];
+ while ($pageID = $statement->fetchColumn()) {
+ $pageIDs[] = $pageID;
}
// save page ids
<item name="wcf.acp.option.category.dashboard"><![CDATA[Dashboard]]></item>
<item name="wcf.acp.option.category.dashboard.content"><![CDATA[Inhaltsbereich]]></item>
<item name="wcf.acp.option.category.dashboard.sidebar"><![CDATA[Seitenleiste]]></item>
- <item name="wcf.acp.option.category.dashboard.content.recentActivities"><![CDATA[Letzte Aktivität]]></item>
- <item name="wcf.acp.option.category.dashboard.sidebar.recentActivities"><![CDATA[Letzte Aktivität]]></item>
<item name="wcf.acp.option.category.user.profile"><![CDATA[Profil]]></item>
<item name="wcf.acp.option.category.user.avatar"><![CDATA[Avatar]]></item>
<item name="wcf.acp.option.category.user.signature"><![CDATA[Signatur]]></item>
<item name="wcf.acp.option.user_cleanup_activity_event_lifetime.description"><![CDATA[Zeitraum nach dem letzte Aktivitäten automatisch verworfen werden.]]></item>
<item name="wcf.acp.option.user_cleanup_profile_visitor_lifetime"><![CDATA[Profil-Besucher]]></item>
<item name="wcf.acp.option.user_cleanup_profile_visitor_lifetime.description"><![CDATA[Zeitraum nach dem Profil-Besucher automatisch verworfen werden.]]></item>
- <item name="wcf.acp.option.recent_activity_items"><![CDATA[Anzahl Einträge]]></item>
- <item name="wcf.acp.option.recent_activity_sidebar_items"><![CDATA[Anzahl Einträge]]></item>
<item name="wcf.acp.option.category.message.general.likes"><![CDATA[Like-System]]></item>
<item name="wcf.acp.option.module_like"><![CDATA[Like-System]]></item>
<item name="wcf.acp.option.like_allow_for_own_content"><![CDATA[Benutzer können eigene Inhalte liken]]></item>
<item name="wcf.condition.timestamp.error.startNotValid"><![CDATA[Das Enddatum ist ungültig.]]></item>
</category>
- <category name="wcf.dashboard">
- <item name="wcf.dashboard.box.mostActiveMembers.points"><![CDATA[todo{#$activeMember->activityPoints} Punkt{if $activeMember->activityPoints != 1}e{/if}]]></item>
- <item name="wcf.dashboard.box.mostLikedMembers.likes"><![CDATA[todo{#$likedMember->likesReceived} Like{if $likedMember->likesReceived != 1}s{/if}]]></item>
- </category>
-
<category name="wcf.date">
<item name="wcf.date.dateFormat"><![CDATA[j. F Y]]></item>
<item name="wcf.date.timeFormat"><![CDATA[H:i]]></item>
<item name="wcf.user.panel.markAsRead"><![CDATA[Als gelesen markieren]]></item>
<item name="wcf.user.panel.settings"><![CDATA[Einstellungen]]></item>
<item name="wcf.user.panel.showAll"><![CDATA[Alle anzeigen]]></item>
+ <item name="wcf.user.boxList.description.activityPoints"><![CDATA[{#$boxUser->activityPoints} Punkt{if $boxUser->activityPoints != 1}e{/if}]]></item>
+ <item name="wcf.user.boxList.description.likesReceived"><![CDATA[{#$boxUser->likesReceived} Like{if $boxUser->likesReceived != 1}s{/if}]]></item>
+ <item name="wcf.user.boxList.description.registrationDate"><![CDATA[{@$boxUser->registrationDate|time}]]></item>
</category>
<category name="wcf.user.menu">
<item name="wcf.acp.option.category.dashboard"><![CDATA[Dashboard]]></item>
<item name="wcf.acp.option.category.dashboard.content"><![CDATA[Content Area]]></item>
<item name="wcf.acp.option.category.dashboard.sidebar"><![CDATA[Sidebar]]></item>
- <item name="wcf.acp.option.category.dashboard.content.recentActivities"><![CDATA[Recent Activities]]></item>
- <item name="wcf.acp.option.category.dashboard.sidebar.recentActivities"><![CDATA[Recent Activities]]></item>
<item name="wcf.acp.option.category.user.profile"><![CDATA[Profile]]></item>
<item name="wcf.acp.option.category.user.avatar"><![CDATA[Avatar]]></item>
<item name="wcf.acp.option.category.user.signature"><![CDATA[Signature]]></item>
<item name="wcf.acp.option.user_cleanup_activity_event_lifetime.description"><![CDATA[Recent Activities will be removed after the selected days.]]></item>
<item name="wcf.acp.option.user_cleanup_profile_visitor_lifetime"><![CDATA[Profile Visitors]]></item>
<item name="wcf.acp.option.user_cleanup_profile_visitor_lifetime.description"><![CDATA[Profile Visitors will be removed after the selected days.]]></item>
- <item name="wcf.acp.option.recent_activity_items"><![CDATA[Number of Entries]]></item>
- <item name="wcf.acp.option.recent_activity_sidebar_items"><![CDATA[Number of Entries]]></item>
<item name="wcf.acp.option.category.message.general.likes"><![CDATA[Likes System]]></item>
<item name="wcf.acp.option.module_like"><![CDATA[Likes System]]></item>
<item name="wcf.acp.option.like_allow_for_own_content"><![CDATA[Users can like their own content]]></item>
<item name="wcf.condition.timestamp.error.startNotValid"><![CDATA[The end date is not valid.]]></item>
</category>
- <category name="wcf.dashboard">
- <item name="wcf.dashboard.box.mostActiveMembers.points"><![CDATA[todo{#$activeMember->activityPoints} Point{if $activeMember->activityPoints != 1}s{/if}]]></item>
- <item name="wcf.dashboard.box.mostLikedMembers.likes"><![CDATA[todo{#$likedMember->likesReceived} Like{if $likedMember->likesReceived != 1}s{/if}]]></item>
- </category>
-
<category name="wcf.date">
<item name="wcf.date.dateFormat"><![CDATA[M jS Y]]></item>
<item name="wcf.date.timeFormat"><![CDATA[g:ia]]></item>
<item name="wcf.user.panel.markAsRead"><![CDATA[Mark as Read]]></item>
<item name="wcf.user.panel.settings"><![CDATA[Settings]]></item>
<item name="wcf.user.panel.showAll"><![CDATA[Show All]]></item>
+ <item name="wcf.user.boxList.description.activityPoints"><![CDATA[{#$boxUser->activityPoints} Point{if $boxUser->activityPoints != 1}s{/if}]]></item>
+ <item name="wcf.user.boxList.description.likesReceived"><![CDATA[{#$boxUser->likesReceived} Like{if $boxUser->likesReceived != 1}s{/if}]]></item>
+ <item name="wcf.user.boxList.description.registrationDate"><![CDATA[{@$boxUser->registrationDate|time}]]></item>
</category>
<category name="wcf.user.menu">
DROP TABLE IF EXISTS wcf1_box;
CREATE TABLE wcf1_box (
boxID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ objectTypeID INT(10),
identifier VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
boxType VARCHAR(255) NOT NULL,
showHeader TINYINT(1) NOT NULL DEFAULT 1,
originIsSystem TINYINT(1) NOT NULL DEFAULT 0,
packageID INT(10) NOT NULL,
- controller VARCHAR(255) NOT NULL DEFAULT '',
- menuID INT(10),
+ menuID INT(10) NULL,
linkPageID INT(10),
linkPageObjectID INT(10) NOT NULL DEFAULT 0,
- externalURL VARCHAR(255) NOT NULL DEFAULT ''
+ externalURL VARCHAR(255) NOT NULL DEFAULT '',
+ additionalData TEXT
);
DROP TABLE IF EXISTS wcf1_box_content;
ALTER TABLE wcf1_bbcode_attribute ADD FOREIGN KEY (bbcodeID) REFERENCES wcf1_bbcode (bbcodeID) ON DELETE CASCADE;
+ALTER TABLE wcf1_box ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
ALTER TABLE wcf1_box ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
ALTER TABLE wcf1_box ADD FOREIGN KEY (menuID) REFERENCES wcf1_menu (menuID) ON DELETE CASCADE;
ALTER TABLE wcf1_box ADD FOREIGN KEY (linkPageID) REFERENCES wcf1_page (pageID) ON DELETE SET NULL;