/**
* Executes watched object-related actions.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\User\Object\Watch
- *
- * @method UserObjectWatch create()
- * @method UserObjectWatchEditor[] getObjects()
- * @method UserObjectWatchEditor getSingleObject()
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\User\Object\Watch
+ *
+ * @method UserObjectWatch create()
+ * @method UserObjectWatchEditor[] getObjects()
+ * @method UserObjectWatchEditor getSingleObject()
*/
-class UserObjectWatchAction extends AbstractDatabaseObjectAction {
- /**
- * object type object
- * @var \wcf\data\object\type\ObjectType
- */
- protected $objectType = null;
-
- /**
- * user object watch object
- * @var UserObjectWatch
- */
- protected $userObjectWatch = null;
-
- /**
- * Validates parameters to manage a subscription.
- */
- public function validateManageSubscription() {
- $this->readInteger('objectID');
- $this->readString('objectType');
-
- // validate object type
- $this->objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.user.objectWatch', $this->parameters['objectType']);
- if ($this->objectType === null) {
- throw new UserInputException('objectType');
- }
-
- // validate object id
- $this->objectType->getProcessor()->validateObjectID($this->parameters['objectID']);
-
- // get existing subscription
- $this->userObjectWatch = UserObjectWatch::getUserObjectWatch($this->objectType->objectTypeID, WCF::getUser()->userID, $this->parameters['objectID']);
- }
-
- /**
- * Returns a form to manage a subscription.
- *
- * @return array
- */
- public function manageSubscription() {
- WCF::getTPL()->assign([
- 'objectType' => $this->objectType,
- 'userObjectWatch' => $this->userObjectWatch
- ]);
-
- return [
- 'objectID' => $this->parameters['objectID'],
- 'objectType' => $this->parameters['objectType'],
- 'template' => WCF::getTPL()->fetch('manageSubscription')
- ];
- }
-
- /**
- * Validates parameters to save subscription state.
- */
- public function validateSaveSubscription() {
- $this->readBoolean('enableNotification');
- $this->readBoolean('subscribe');
-
- $this->validateManageSubscription();
- }
-
- /**
- * Saves subscription state.
- */
- public function saveSubscription() {
- // subscribe
- if ($this->parameters['subscribe']) {
- // newly subscribed
- if ($this->userObjectWatch === null) {
- UserObjectWatchEditor::createOrIgnore([
- 'notification' => $this->parameters['enableNotification'] ? 1 : 0,
- 'objectID' => $this->parameters['objectID'],
- 'objectTypeID' => $this->objectType->objectTypeID,
- 'userID' => WCF::getUser()->userID
- ]);
- }
- else if ($this->userObjectWatch->notification != $this->parameters['enableNotification']) {
- // update notification type
- $editor = new UserObjectWatchEditor($this->userObjectWatch);
- $editor->update([
- 'notification' => $this->parameters['enableNotification'] ? 1 : 0
- ]);
- }
-
- // reset user storage
- $this->objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
- }
- else if ($this->userObjectWatch !== null) {
- // unsubscribe
- $editor = new UserObjectWatchEditor($this->userObjectWatch);
- $editor->delete();
-
- // reset user storage
- $this->objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
- }
-
- return [
- 'objectID' => $this->parameters['objectID'],
- 'objectType' => $this->parameters['objectType'],
- 'subscribe' => $this->parameters['subscribe']
- ];
- }
-
- /**
- * Adds a subscription.
- */
- public function subscribe() {
- $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.user.objectWatch', $this->parameters['data']['objectType']);
-
- UserObjectWatchEditor::create([
- 'userID' => WCF::getUser()->userID,
- 'objectID' => intval($this->parameters['data']['objectID']),
- 'objectTypeID' => $objectType->objectTypeID,
- 'notification' => !empty($this->parameters['enableNotification']) ? 1 : 0
- ]);
-
- // reset user storage
- $objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
- }
-
- /**
- * Removes a subscription.
- */
- public function unsubscribe() {
- $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.user.objectWatch', $this->parameters['data']['objectType']);
-
- if ($this->userObjectWatch !== null) $userObjectWatch = $this->userObjectWatch;
- else {
- $userObjectWatch = UserObjectWatch::getUserObjectWatch($objectType->objectTypeID, WCF::getUser()->userID, intval($this->parameters['data']['objectID']));
- }
- $editor = new UserObjectWatchEditor($userObjectWatch);
- $editor->delete();
-
- // reset user storage
- $objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
- }
-
- /**
- * Validates the subscribe action.
- */
- protected function __validateSubscribe() {
- $this->readInteger('objectID', false, 'data');
- $this->readString('objectType', false, 'data');
-
- // validate object type
- $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.user.objectWatch', $this->parameters['data']['objectType']);
- if ($objectType === null) {
- throw new UserInputException('objectType');
- }
-
- // validate object id
- $objectType->getProcessor()->validateObjectID(intval($this->parameters['data']['objectID']));
-
- // get existing subscription
- $this->userObjectWatch = UserObjectWatch::getUserObjectWatch($objectType->objectTypeID, WCF::getUser()->userID, intval($this->parameters['data']['objectID']));
- }
-
- /**
- * Validates the subscribe action.
- */
- public function validateSubscribe() {
- $this->__validateSubscribe();
-
- if ($this->userObjectWatch !== null) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Validates the unsubscribe action.
- */
- public function validateUnsubscribe() {
- $this->__validateSubscribe();
-
- if ($this->userObjectWatch === null) {
- throw new PermissionDeniedException();
- }
- }
+class UserObjectWatchAction extends AbstractDatabaseObjectAction
+{
+ /**
+ * object type object
+ * @var \wcf\data\object\type\ObjectType
+ */
+ protected $objectType;
+
+ /**
+ * user object watch object
+ * @var UserObjectWatch
+ */
+ protected $userObjectWatch;
+
+ /**
+ * Validates parameters to manage a subscription.
+ */
+ public function validateManageSubscription()
+ {
+ $this->readInteger('objectID');
+ $this->readString('objectType');
+
+ // validate object type
+ $this->objectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
+ 'com.woltlab.wcf.user.objectWatch',
+ $this->parameters['objectType']
+ );
+ if ($this->objectType === null) {
+ throw new UserInputException('objectType');
+ }
+
+ // validate object id
+ $this->objectType->getProcessor()->validateObjectID($this->parameters['objectID']);
+
+ // get existing subscription
+ $this->userObjectWatch = UserObjectWatch::getUserObjectWatch(
+ $this->objectType->objectTypeID,
+ WCF::getUser()->userID,
+ $this->parameters['objectID']
+ );
+ }
+
+ /**
+ * Returns a form to manage a subscription.
+ *
+ * @return array
+ */
+ public function manageSubscription()
+ {
+ WCF::getTPL()->assign([
+ 'objectType' => $this->objectType,
+ 'userObjectWatch' => $this->userObjectWatch,
+ ]);
+
+ return [
+ 'objectID' => $this->parameters['objectID'],
+ 'objectType' => $this->parameters['objectType'],
+ 'template' => WCF::getTPL()->fetch('manageSubscription'),
+ ];
+ }
+
+ /**
+ * Validates parameters to save subscription state.
+ */
+ public function validateSaveSubscription()
+ {
+ $this->readBoolean('enableNotification');
+ $this->readBoolean('subscribe');
+
+ $this->validateManageSubscription();
+ }
+
+ /**
+ * Saves subscription state.
+ */
+ public function saveSubscription()
+ {
+ // subscribe
+ if ($this->parameters['subscribe']) {
+ // newly subscribed
+ if ($this->userObjectWatch === null) {
- UserObjectWatchEditor::create([
++ UserObjectWatchEditor::createOrIgnore([
+ 'notification' => $this->parameters['enableNotification'] ? 1 : 0,
+ 'objectID' => $this->parameters['objectID'],
+ 'objectTypeID' => $this->objectType->objectTypeID,
+ 'userID' => WCF::getUser()->userID,
+ ]);
+ } elseif ($this->userObjectWatch->notification != $this->parameters['enableNotification']) {
+ // update notification type
+ $editor = new UserObjectWatchEditor($this->userObjectWatch);
+ $editor->update([
+ 'notification' => $this->parameters['enableNotification'] ? 1 : 0,
+ ]);
+ }
+
+ // reset user storage
+ $this->objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
+ } elseif ($this->userObjectWatch !== null) {
+ // unsubscribe
+ $editor = new UserObjectWatchEditor($this->userObjectWatch);
+ $editor->delete();
+
+ // reset user storage
+ $this->objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
+ }
+
+ return [
+ 'objectID' => $this->parameters['objectID'],
+ 'objectType' => $this->parameters['objectType'],
+ 'subscribe' => $this->parameters['subscribe'],
+ ];
+ }
+
+ /**
+ * Adds a subscription.
+ */
+ public function subscribe()
+ {
+ $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
+ 'com.woltlab.wcf.user.objectWatch',
+ $this->parameters['data']['objectType']
+ );
+
+ UserObjectWatchEditor::create([
+ 'userID' => WCF::getUser()->userID,
+ 'objectID' => \intval($this->parameters['data']['objectID']),
+ 'objectTypeID' => $objectType->objectTypeID,
+ 'notification' => !empty($this->parameters['enableNotification']) ? 1 : 0,
+ ]);
+
+ // reset user storage
+ $objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
+ }
+
+ /**
+ * Removes a subscription.
+ */
+ public function unsubscribe()
+ {
+ $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
+ 'com.woltlab.wcf.user.objectWatch',
+ $this->parameters['data']['objectType']
+ );
+
+ if ($this->userObjectWatch !== null) {
+ $userObjectWatch = $this->userObjectWatch;
+ } else {
+ $userObjectWatch = UserObjectWatch::getUserObjectWatch(
+ $objectType->objectTypeID,
+ WCF::getUser()->userID,
+ \intval($this->parameters['data']['objectID'])
+ );
+ }
+ $editor = new UserObjectWatchEditor($userObjectWatch);
+ $editor->delete();
+
+ // reset user storage
+ $objectType->getProcessor()->resetUserStorage([WCF::getUser()->userID]);
+ }
+
+ /**
+ * Validates the subscribe action.
+ */
+ protected function __validateSubscribe()
+ {
+ $this->readInteger('objectID', false, 'data');
+ $this->readString('objectType', false, 'data');
+
+ // validate object type
+ $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
+ 'com.woltlab.wcf.user.objectWatch',
+ $this->parameters['data']['objectType']
+ );
+ if ($objectType === null) {
+ throw new UserInputException('objectType');
+ }
+
+ // validate object id
+ $objectType->getProcessor()->validateObjectID(\intval($this->parameters['data']['objectID']));
+
+ // get existing subscription
+ $this->userObjectWatch = UserObjectWatch::getUserObjectWatch(
+ $objectType->objectTypeID,
+ WCF::getUser()->userID,
+ \intval($this->parameters['data']['objectID'])
+ );
+ }
+
+ /**
+ * Validates the subscribe action.
+ */
+ public function validateSubscribe()
+ {
+ $this->__validateSubscribe();
+
+ if ($this->userObjectWatch !== null) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Validates the unsubscribe action.
+ */
+ public function validateUnsubscribe()
+ {
+ $this->__validateSubscribe();
+
+ if ($this->userObjectWatch === null) {
+ throw new PermissionDeniedException();
+ }
+ }
}
/**
* Contains helper functions to process the Exception log.
- *
- * @author Tim Duesterhus
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Util
- * @since 5.2
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Util
+ * @since 5.2
*/
-final class ExceptionLogUtil {
- /**
- * Splits the given string of Exceptions into an array.
- *
- * @param string $contents
- * @return string[]
- */
- public static function splitLog($contents) {
- // unify newlines
- $contents = StringUtil::unifyNewlines($contents);
-
- // split contents
- $split = new Regex('(?:^|\n<<<<\n\n)(?:<<<<<<<<([a-f0-9]{40})<<<<\n|$)');
- $contents = $split->split($contents, Regex::SPLIT_NON_EMPTY_ONLY | Regex::CAPTURE_SPLIT_DELIMITER);
-
- if (empty($contents)) {
- return [];
- }
-
- // even items become keys, odd items become values
- return array_merge(...array_map(
- function($v) {
- return [$v[0] => $v[1]];
- },
- array_chunk($contents, 2)
- ));
- }
-
- /**
- * Parses the given log entry.
- *
- * @param string $entry
- * @return mixed[]
- */
- public static function parseException($entry) {
- static $regex = null;
- static $chainRegex = null;
- if ($regex === null || $chainRegex === null) {
- $regex = new Regex("(?P<date>[MTWFS][a-z]{2}, \d{1,2} [JFMASOND][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} [+-]\d{4})\s*\n".
- "Message: (?P<message>.*?)\s*\n".
- "PHP version: (?P<phpVersion>.*?)\s*\n".
- "WoltLab Suite version: (?P<wcfVersion>.*?)\s*\n".
- "Request URI: (?P<requestURI>.*?)\s*\n".
- "Referrer: (?P<referrer>.*?)\s*\n".
- "User Agent: (?P<userAgent>.*?)\s*\n".
- "Peak Memory Usage: (?<peakMemory>\d+)/(?<maxMemory>(?:\d+|-1))\s*\n".
- "(?<chain>======\n".
- ".*)", Regex::DOT_ALL);
- $chainRegex = new Regex("======\n".
- "Error Class: (?P<class>.*?)\s*\n".
- "Error Message: (?P<message>.*?)\s*\n".
- "Error Code: (?P<code>[a-zA-Z0-9]+)\s*\n".
- "File: (?P<file>.*?) \((?P<line>\d+)\)\s*\n".
- "Extra Information: (?P<information>(?:-|[a-zA-Z0-9+/]+={0,2}))\s*\n".
- "Stack Trace: (?P<stack>\[[^\n]+\])", Regex::DOT_ALL);
- }
-
- if (!$regex->match($entry)) {
- throw new \InvalidArgumentException('The given entry is malformed.');
- }
- $matches = $regex->getMatches();
- $chainRegex->match($matches['chain'], true, Regex::ORDER_MATCH_BY_SET);
-
- $chainMatches = array_map(function ($item) {
- if ($item['information'] === '-') {
- $item['information'] = null;
- }
- else {
- try {
- $item['information'] = unserialize(base64_decode($item['information']), ['allowed_classes' => false]);
- }
- catch (SystemException $e) {
- throw new \InvalidArgumentException('The additional information section of the given entry is malformed.', 0, $e);
- }
- }
-
- try {
- $item['stack'] = JSON::decode($item['stack']);
- }
- catch (SystemException $e) {
- throw new \InvalidArgumentException('The stack trace of the given entry is malformed.', 0, $e);
- }
-
- return $item;
- }, $chainRegex->getMatches());
-
- $matches['stackHash'] = sha1(implode("\0", array_map(function ($item) {
- $result = "";
- foreach ($item['stack'] as $stack) {
- $result .= $stack['file']."\t".$stack['line']."\t".$stack['class'].$stack['type'].$stack['function']."\n";
- }
- return $result;
- }, $chainMatches)));
-
- $matches['date'] = strtotime($matches['date']);
- $matches['chain'] = $chainMatches;
-
- return $matches;
- }
-
- /**
- * Forbid creation of ExceptionLogUtil objects.
- */
- private function __construct() {
- // does nothing
- }
+final class ExceptionLogUtil
+{
+ /**
+ * Splits the given string of Exceptions into an array.
+ *
+ * @param string $contents
+ * @return string[]
+ */
+ public static function splitLog($contents)
+ {
+ // unify newlines
+ $contents = StringUtil::unifyNewlines($contents);
+
+ // split contents
+ $split = new Regex('(?:^|\n<<<<\n\n)(?:<<<<<<<<([a-f0-9]{40})<<<<\n|$)');
+ $contents = $split->split($contents, Regex::SPLIT_NON_EMPTY_ONLY | Regex::CAPTURE_SPLIT_DELIMITER);
+
++ if (empty($contents)) {
++ return [];
++ }
++
+ // even items become keys, odd items become values
+ return \array_merge(...\array_map(
+ static function ($v) {
+ return [$v[0] => $v[1]];
+ },
+ \array_chunk($contents, 2)
+ ));
+ }
+
+ /**
+ * Parses the given log entry.
+ *
+ * @param string $entry
+ * @return mixed[]
+ */
+ public static function parseException($entry)
+ {
+ static $regex = null;
+ static $chainRegex = null;
+ if ($regex === null || $chainRegex === null) {
+ $regex = new Regex("(?P<date>[MTWFS][a-z]{2}, \\d{1,2} [JFMASOND][a-z]{2} \\d{4} \\d{2}:\\d{2}:\\d{2} [+-]\\d{4})\\s*\n"
+ . "Message: (?P<message>.*?)\\s*\n"
+ . "PHP version: (?P<phpVersion>.*?)\\s*\n"
+ . "WoltLab Suite version: (?P<wcfVersion>.*?)\\s*\n"
+ . "Request URI: (?P<requestURI>.*?)\\s*\n"
+ . "Referrer: (?P<referrer>.*?)\\s*\n"
+ . "User Agent: (?P<userAgent>.*?)\\s*\n"
+ . "Peak Memory Usage: (?<peakMemory>\\d+)/(?<maxMemory>(?:\\d+|-1))\\s*\n"
+ . "(?<chain>======\n"
+ . ".*)", Regex::DOT_ALL);
+ $chainRegex = new Regex("======\n"
+ . "Error Class: (?P<class>.*?)\\s*\n"
+ . "Error Message: (?P<message>.*?)\\s*\n"
+ . "Error Code: (?P<code>[a-zA-Z0-9]+)\\s*\n"
+ . "File: (?P<file>.*?) \\((?P<line>\\d+)\\)\\s*\n"
+ . "Extra Information: (?P<information>(?:-|[a-zA-Z0-9+/]+={0,2}))\\s*\n"
+ . "Stack Trace: (?P<stack>\\[[^\n]+\\])", Regex::DOT_ALL);
+ }
+
+ if (!$regex->match($entry)) {
+ throw new \InvalidArgumentException('The given entry is malformed.');
+ }
+ $matches = $regex->getMatches();
+ $chainRegex->match($matches['chain'], true, Regex::ORDER_MATCH_BY_SET);
+
+ $chainMatches = \array_map(static function ($item) {
+ if ($item['information'] === '-') {
+ $item['information'] = null;
+ } else {
+ try {
+ $item['information'] = \unserialize(
+ \base64_decode($item['information']),
+ ['allowed_classes' => false]
+ );
+ } catch (SystemException $e) {
+ throw new \InvalidArgumentException(
+ 'The additional information section of the given entry is malformed.',
+ 0,
+ $e
+ );
+ }
+ }
+
+ try {
+ $item['stack'] = JSON::decode($item['stack']);
+ } catch (SystemException $e) {
+ throw new \InvalidArgumentException('The stack trace of the given entry is malformed.', 0, $e);
+ }
+
+ return $item;
+ }, $chainRegex->getMatches());
+
+ $matches['stackHash'] = \sha1(\implode("\0", \array_map(static function ($item) {
+ $result = "";
+ foreach ($item['stack'] as $stack) {
+ $result .= $stack['file'] . "\t" . $stack['line'] . "\t" . $stack['class'] . $stack['type'] . $stack['function'] . "\n";
+ }
+
+ return $result;
+ }, $chainMatches)));
+
+ $matches['date'] = \strtotime($matches['date']);
+ $matches['chain'] = $chainMatches;
+
+ return $matches;
+ }
+
+ /**
+ * Forbid creation of ExceptionLogUtil objects.
+ */
+ private function __construct()
+ {
+ // does nothing
+ }
}