diff --git a/public-legacy/profile.php b/public-legacy/profile.php index 1235e26..2285235 100644 --- a/public-legacy/profile.php +++ b/public-legacy/profile.php @@ -4,6 +4,7 @@ namespace Misuzu; use InvalidArgumentException; use Index\ByteFormat; use Misuzu\Parsers\Parser; +use Misuzu\Profile\ProfileFields; use Misuzu\Users\User; use Misuzu\Users\UserNotFoundException; use Misuzu\Users\UserSession; @@ -34,6 +35,7 @@ if($profileUser->isDeleted()) { $notices = []; +$profileFields = new ProfileFields($db); $currentUser = User::getCurrent(); $viewingAsGuest = $currentUser === null; $currentUserId = $viewingAsGuest ? 0 : $currentUser->getId(); @@ -72,19 +74,37 @@ if($isEditing) { if(!CSRF::validateRequest()) { $notices[] = 'Couldn\'t verify you, please refresh the page and retry.'; } else { - if(!empty($_POST['profile']) && is_array($_POST['profile'])) { + $profileFieldsSubmit = filter_input(INPUT_POST, 'profile', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY); + + if(!empty($profileFieldsSubmit)) { if(!$perms['edit_profile']) { $notices[] = 'You\'re not allowed to edit your profile'; } else { - $profileFields = $profileUser->profileFields(false); + $profileFieldInfos = $profileFields->getFields(); + $profileFieldsSetInfos = []; + $profileFieldsSetValues = []; + $profileFieldsRemove = []; - foreach($profileFields as $profileField) { - if(isset($_POST['profile'][$profileField->field_key]) - && $profileField->field_value !== $_POST['profile'][$profileField->field_key] - && !$profileField->setFieldValue($_POST['profile'][$profileField->field_key])) { - $notices[] = sprintf('%s was formatted incorrectly!', $profileField->field_title); + foreach($profileFieldInfos as $fieldInfo) { + $fieldName = $fieldInfo->getName(); + $fieldValue = empty($profileFieldsSubmit[$fieldName]) ? '' : (string)filter_var($profileFieldsSubmit[$fieldName]); + + if(empty($profileFieldsSubmit[$fieldName])) { + $profileFieldsRemove[] = $fieldInfo; + continue; } + + if($fieldInfo->checkValue($fieldValue)) { + $profileFieldsSetInfos[] = $fieldInfo; + $profileFieldsSetValues[] = $fieldValue; + } else + $notices[] = sprintf('%s isn\'t properly formatted.', $fieldInfo->getTitle()); } + + if(!empty($profileFieldsRemove)) + $profileFields->removeFieldValues($profileUser, $profileFieldsRemove); + if(!empty($profileFieldsSetInfos)) + $profileFields->setFieldValues($profileUser, $profileFieldsSetInfos, $profileFieldsSetValues); } } @@ -97,7 +117,7 @@ if($isEditing) { $aboutValid = User::validateProfileAbout($aboutParse, $aboutText); if($aboutValid === '') - $currentUser->setProfileAboutText($aboutText)->setProfileAboutParser($aboutParse); + $profileUser->setProfileAboutText($aboutText)->setProfileAboutParser($aboutParse); else switch($aboutValid) { case 'parser': $notices[] = 'The selected about section parser is invalid.'; @@ -121,7 +141,7 @@ if($isEditing) { $sigValid = User::validateForumSignature($sigParse, $sigText); if($sigValid === '') - $currentUser->setForumSignatureText($sigText)->setForumSignatureParser($sigParse); + $profileUser->setForumSignatureText($sigText)->setForumSignatureParser($sigParse); else switch($sigValid) { case 'parser': $notices[] = 'The selected forum signature parser is invalid.'; @@ -146,7 +166,7 @@ if($isEditing) { $birthValid = User::validateBirthdate($birthYear, $birthMonth, $birthDay); if($birthValid === '') - $currentUser->setBirthdate($birthYear, $birthMonth, $birthDay); + $profileUser->setBirthdate($birthYear, $birthMonth, $birthDay); else switch($birthValid) { case 'year': $notices[] = 'The given birth year is invalid.'; @@ -352,21 +372,64 @@ switch($profileMode) { $template = 'profile.index'; $warnings = $profileUser->getProfileWarnings($currentUser); - $activeCategoryStats = $viewingAsGuest ? null : forum_get_user_most_active_category_info($profileUser->getId()); - $activeCategoryInfo = empty($activeCategoryStats->forum_id) ? null : forum_get($activeCategoryStats->forum_id); - - $activeTopicStats = $viewingAsGuest ? null : forum_get_user_most_active_topic_info($profileUser->getId()); - $activeTopicInfo = empty($activeTopicStats->topic_id) ? null : forum_topic_get($activeTopicStats->topic_id); - Template::set([ 'profile_warnings' => $warnings, 'profile_warnings_view_private' => $canManageWarnings, 'profile_warnings_can_manage' => $canManageWarnings, - 'profile_active_category_stats' => $activeCategoryStats, - 'profile_active_category_info' => $activeCategoryInfo, - 'profile_active_topic_stats' => $activeTopicStats, - 'profile_active_topic_info' => $activeTopicInfo, ]); + + if(!$viewingAsGuest) { + $activeCategoryStats = forum_get_user_most_active_category_info($profileUser->getId()); + $activeCategoryInfo = empty($activeCategoryStats->forum_id) ? null : forum_get($activeCategoryStats->forum_id); + + $activeTopicStats = forum_get_user_most_active_topic_info($profileUser->getId()); + $activeTopicInfo = empty($activeTopicStats->topic_id) ? null : forum_topic_get($activeTopicStats->topic_id); + + $profileFieldValues = $profileFields->getFieldValues($profileUser); + $profileFieldInfos = $profileFieldInfos ?? $profileFields->getFields(fieldValueInfos: $isEditing ? null : $profileFieldValues); + $profileFieldFormats = $profileFields->getFieldFormats(fieldValueInfos: $profileFieldValues); + + $profileFieldRawValues = []; + $profileFieldLinkValues = []; + $profileFieldDisplayValues = []; + + // using field infos as the basis for now, uses the correct ordering + foreach($profileFieldInfos as $fieldInfo) { + foreach($profileFieldValues as $fieldValueTest) + if($fieldValueTest->getFieldId() === $fieldInfo->getId()) { + $fieldValue = $fieldValueTest; + break; + } + + $fieldName = $fieldInfo->getName(); + + if(isset($fieldValue)) { + foreach($profileFieldFormats as $fieldFormatTest) + if($fieldFormatTest->getId() === $fieldValue->getFormatId()) { + $fieldFormat = $fieldFormatTest; + break; + } + + $profileFieldRawValues[$fieldName] = $fieldValue->getValue(); + $profileFieldDisplayValues[$fieldName] = $fieldFormat->formatDisplay($fieldValue->getValue()); + if($fieldFormat->hasLinkFormat()) + $profileFieldLinkValues[$fieldName] = $fieldFormat->formatLink($fieldValue->getValue()); + } + + unset($fieldValue); + } + + Template::set([ + 'profile_active_category_stats' => $activeCategoryStats, + 'profile_active_category_info' => $activeCategoryInfo, + 'profile_active_topic_stats' => $activeTopicStats, + 'profile_active_topic_info' => $activeTopicInfo, + 'profile_fields_infos' => $profileFieldInfos, + 'profile_fields_raw_values' => $profileFieldRawValues, + 'profile_fields_display_values' => $profileFieldDisplayValues, + 'profile_fields_link_values' => $profileFieldLinkValues, + ]); + } break; } @@ -380,5 +443,6 @@ if(!empty($template)) { 'profile_can_edit' => $canEdit, 'profile_is_editing' => $isEditing, 'profile_is_banned' => $isBanned, + 'profile_is_guest' => $viewingAsGuest, ]); } diff --git a/src/Changelog/Changelog.php b/src/Changelog/Changelog.php index ad6965c..8322f0d 100644 --- a/src/Changelog/Changelog.php +++ b/src/Changelog/Changelog.php @@ -122,7 +122,7 @@ class Changelog { $query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= sprintf( ' change_id IN (SELECT change_id FROM msz_changelog_change_tags WHERE tag_id IN (%s))', - implode(', ', array_fill(0, count($tags), '?')) + msz_where_in_list($tags) ); } $stmt = $this->cache->get($query); @@ -177,7 +177,7 @@ class Changelog { $query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= sprintf( ' change_id IN (SELECT change_id FROM msz_changelog_change_tags WHERE tag_id IN (%s))', - implode(', ', array_fill(0, count($tags), '?')) + msz_where_in_list($tags) ); } $query .= ' GROUP BY change_created, change_id ORDER BY change_created DESC, change_id DESC'; diff --git a/src/Config/DbConfig.php b/src/Config/DbConfig.php index d312218..5925d78 100644 --- a/src/Config/DbConfig.php +++ b/src/Config/DbConfig.php @@ -23,10 +23,6 @@ class DbConfig implements IConfig { return preg_match('#^([a-z][a-zA-Z0-9._]+)$#', $name) === 1; } - private static function whereInList(int $count): string { - return implode(', ', array_fill(0, $count, '?')); - } - public function reset(): void { $this->values = []; } @@ -61,7 +57,7 @@ class DbConfig implements IConfig { $stmt = $this->cache->get(sprintf( 'SELECT COUNT(*) FROM msz_config WHERE config_name IN (%s)', - self::whereInList($nameCount) + msz_where_in_list($nameCount) )); for($i = 0; $i < $nameCount; ++$i) $stmt->addParameter($i + 1, $names[$i]); @@ -87,7 +83,7 @@ class DbConfig implements IConfig { $nameCount = count($names); $stmt = $this->cache->get(sprintf( 'DELETE FROM msz_config WHERE config_name IN (%s)', - self::whereInList($nameCount) + msz_where_in_list($nameCount) )); for($i = 0; $i < $nameCount; ++$i) @@ -147,7 +143,7 @@ class DbConfig implements IConfig { $stmt = $this->cache->get(sprintf( 'SELECT config_name, config_value FROM msz_config WHERE config_name IN (%s)', - self::whereInList($nameCount) + msz_where_in_list($nameCount) )); for($i = 0; $i < $nameCount; ++$i) $stmt->addParameter($i + 1, $names[$i]); @@ -271,7 +267,7 @@ class DbConfig implements IConfig { $stmt = $this->cache->get(sprintf( 'REPLACE INTO msz_config (config_name, config_value) VALUES %s', - implode(', ', array_fill(0, $valueCount, '(?, ?)')) + msz_where_in_list($valueCount, '(?, ?)') )); $args = 0; diff --git a/src/Profile/ProfileFieldFormatInfo.php b/src/Profile/ProfileFieldFormatInfo.php new file mode 100644 index 0000000..ba0ffdf --- /dev/null +++ b/src/Profile/ProfileFieldFormatInfo.php @@ -0,0 +1,56 @@ +id = (string)$result->getInteger(0); + $this->fieldId = (string)$result->getInteger(1); + $this->regex = $result->isNull(2) ? null : $result->getString(2); + $this->linkFormat = $result->isNull(3) ? null : $result->getString(3); + $this->displayFormat = $result->getString(4); + } + + public function getId(): string { + return $this->id; + } + + public function getFieldId(): string { + return $this->fieldId; + } + + public function hasRegEx(): bool { + return $this->regex !== null; + } + + public function getRegEx(): ?string { + return $this->regex; + } + + public function hasLinkFormat(): bool { + return $this->linkFormat !== null; + } + + public function getLinkFormat(): ?string { + return $this->linkFormat; + } + + public function formatLink(string $value): ?string { + return $this->linkFormat === null ? null : sprintf($this->linkFormat, $value); + } + + public function getDisplayFormat(): string { + return $this->displayFormat; + } + + public function formatDisplay(string $value): string { + return sprintf($this->displayFormat, $value); + } +} diff --git a/src/Profile/ProfileFieldInfo.php b/src/Profile/ProfileFieldInfo.php new file mode 100644 index 0000000..c482baa --- /dev/null +++ b/src/Profile/ProfileFieldInfo.php @@ -0,0 +1,48 @@ +id = (string)$result->getInteger(0); + $this->order = $result->getInteger(1); + $this->name = $result->getString(2); + $this->title = $result->getString(3); + $this->regex = $result->getString(4); + } + + public function getId(): string { + return $this->id; + } + + public function getOrder(): int { + return $this->order; + } + + public function getName(): string { + return $this->name; + } + + public function getTitle(): string { + return $this->title; + } + + public function getRegEx(): string { + return $this->regex; + } + + public function checkValue(string $value): bool { + return preg_match($this->regex, $value) === 1; + } + + public function matchValue(string $value): string|false { + return preg_match($this->regex, $value, $matches) === 1 ? $matches[1] : false; + } +} diff --git a/src/Profile/ProfileFieldValueInfo.php b/src/Profile/ProfileFieldValueInfo.php new file mode 100644 index 0000000..e0fa266 --- /dev/null +++ b/src/Profile/ProfileFieldValueInfo.php @@ -0,0 +1,34 @@ +fieldId = (string)$result->getInteger(0); + $this->userId = (string)$result->getInteger(1); + $this->formatId = (string)$result->getInteger(2); + $this->value = $result->getString(3); + } + + public function getFieldId(): string { + return $this->fieldId; + } + + public function getUserId(): string { + return $this->userId; + } + + public function getFormatId(): string { + return $this->formatId; + } + + public function getValue(): string { + return $this->value; + } +} diff --git a/src/Profile/ProfileFields.php b/src/Profile/ProfileFields.php new file mode 100644 index 0000000..aba1d5f --- /dev/null +++ b/src/Profile/ProfileFields.php @@ -0,0 +1,273 @@ +dbConn = $dbConn; + $this->cache = new DbStatementCache($dbConn); + } + + public function getFields(?array $fieldValueInfos = null): array { + $hasFieldValueInfos = $fieldValueInfos !== null; + if($hasFieldValueInfos && empty($fieldValueInfos)) + return []; + + $query = 'SELECT field_id, field_order, field_key, field_title, field_regex FROM msz_profile_fields'; + if($hasFieldValueInfos) + $query .= sprintf(' WHERE field_id IN (%s)', msz_where_in_list($fieldValueInfos)); + $query .= ' ORDER BY field_order ASC'; + + $stmt = $this->cache->get($query); + $args = 0; + + if($hasFieldValueInfos) + foreach($fieldValueInfos as $fieldValueInfo) { + if(!($fieldValueInfo instanceof ProfileFieldValueInfo)) + throw new InvalidArgumentException('All values in $fieldValueInfos must be of ProfileFieldValueInfo type.'); + $stmt->addParameter(++$args, $fieldValueInfo->getFieldId()); + } + + $stmt->execute(); + $result = $stmt->getResult(); + $fields = []; + + while($result->next()) + $fields[] = new ProfileFieldInfo($result); + + return $fields; + } + + public function getField(string $fieldId): ProfileFieldInfo { + $stmt = $this->cache->get('SELECT field_id, field_order, field_key, field_title, field_regex FROM msz_profile_fields WHERE field_id = ?'); + $stmt->addParameter(1, $fieldId); + $stmt->execute(); + + $result = $stmt->getResult(); + if(!$result->next()) + throw new RuntimeException('No field found with the provided field id.'); + + return new ProfileFieldInfo($result); + } + + public function getFieldFormats( + ?array $fieldInfos = null, + ?array $fieldValueInfos = null + ): array { + $hasFieldInfos = $fieldInfos !== null; + $hasFieldValueInfos = $fieldValueInfos !== null; + + if($hasFieldInfos && empty($fieldInfos)) + return []; + if($hasFieldValueInfos && empty($fieldValueInfos)) + return []; + + $args = 0; + $query = 'SELECT format_id, field_id, format_regex, format_link, format_display FROM msz_profile_fields_formats'; + + if($hasFieldInfos) { + ++$args; + $query .= sprintf(' WHERE field_id IN (%s)', msz_where_in_list($fieldInfos)); + } + if($hasFieldValueInfos) + $query .= sprintf(' %s format_id IN (%s)', + (++$args > 1 ? 'AND' : 'WHERE'), + msz_where_in_list($fieldValueInfos) + ); + + $stmt = $this->cache->get($query); + $args = 0; + + if($hasFieldInfos) + foreach($fieldInfos as $fieldInfo) { + if(!($fieldInfo instanceof ProfileFieldInfo)) + throw new InvalidArgumentException('All values in $fieldInfos must be of ProfileFieldInfo type.'); + $stmt->addParameter(++$args, $fieldInfo->getId()); + } + + if($hasFieldValueInfos) + foreach($fieldValueInfos as $fieldValueInfo) { + if(!($fieldValueInfo instanceof ProfileFieldValueInfo)) + throw new InvalidArgumentException('All values in $fieldValueInfos must be of ProfileFieldValueInfo type.'); + $stmt->addParameter(++$args, $fieldValueInfo->getFormatId()); + } + + $stmt->execute(); + $result = $stmt->getResult(); + $formats = []; + + while($result->next()) + $formats[] = new ProfileFieldFormatInfo($result); + + return $formats; + } + + public function getFieldFormat(string $formatId): ProfileFieldFormatInfo { + $stmt = $this->cache->get('SELECT format_id, field_id, format_regex, format_link, format_display FROM msz_profile_fields_formats WHERE format_id = ?'); + $stmt->addParameter(1, $formatId); + $stmt->execute(); + + $result = $stmt->getResult(); + if(!$result->next()) + throw new RuntimeException('No format found with the provided format id.'); + + return new ProfileFieldFormatInfo($result); + } + + public function selectFieldFormat( + ProfileFieldInfo|string $fieldInfo, + string $value + ): ProfileFieldFormatInfo { + if($fieldInfo instanceof ProfileFieldInfo) + $fieldInfo = $fieldInfo->getId(); + + $stmt = $this->cache->get('SELECT format_id, field_id, format_regex, format_link, format_display FROM msz_profile_fields_formats WHERE field_id = ? AND (format_regex IS NULL OR ? REGEXP format_regex) ORDER BY format_regex IS NULL ASC'); + $stmt->addParameter(1, $fieldInfo); + $stmt->addParameter(2, $value); + $stmt->execute(); + + $result = $stmt->getResult(); + if(!$result->next()) + throw new RuntimeException('Could not determine an appropriate format for this field (missing default formatting)'); + + return new ProfileFieldFormatInfo($result); + } + + public function getFieldValues(User|string $userInfo): array { + if($userInfo instanceof User) + $userInfo = $userInfo->getId(); + + // i don't really want to bother with the join for the ordering so i'll just do that somewhere in PHP for now + // will probably add the ability for people to order them in whatever way they want, as well as visibility controls + $stmt = $this->cache->get('SELECT field_id, user_id, format_id, field_value FROM msz_profile_fields_values WHERE user_id = ?'); + $stmt->addParameter(1, $userInfo); + $stmt->execute(); + + $result = $stmt->getResult(); + $values = []; + + while($result->next()) + $values[] = new ProfileFieldValueInfo($result); + + return $values; + } + + public function getFieldValue( + ProfileFieldInfo|string $fieldInfo, + User|string $userInfo + ): ProfileFieldValueInfo { + if($fieldInfo instanceof ProfileFieldInfo) + $fieldInfo = $fieldInfo->getId(); + if($userInfo instanceof User) + $userInfo = $userInfo->getId(); + + $stmt = $this->cache->get('SELECT field_id, user_id, format_id, field_value FROM msz_profile_fields_values WHERE field_id = ? AND user_id = ?'); + $stmt->addParameter(1, $fieldInfo); + $stmt->addParameter(2, $userInfo); + $stmt->execute(); + + $result = $stmt->getResult(); + + if(!$result->next()) + throw new RuntimeException('No value for this field and user combination found.'); + + return new ProfileFieldValueInfo($result); + } + + public function setFieldValues( + User|string $userInfo, + ProfileFieldInfo|string|array $fieldInfos, + string|array $values + ): void { + if(empty($fieldInfos)) + return; + + if(!is_array($fieldInfos)) { + if(is_array($values)) + throw new InvalidArgumentException('If $fieldInfos is not an array, $values may not be either'); + $fieldInfos = [$fieldInfos]; + $values = [$values]; + } elseif(!is_array($values)) + throw new InvalidArgumentException('If $fieldInfos is an array, $values must be as well.'); + + $fieldsCount = count($fieldInfos); + if($fieldsCount !== count($values)) + throw new InvalidArgumentException('$fieldsInfos and $values have the same amount of values and be in the same order.'); + + if($userInfo instanceof User) + $userInfo = $userInfo->getId(); + + $rows = []; + + foreach($fieldInfos as $key => $fieldInfo) { + if(is_string($fieldInfo)) + $fieldInfo = $this->getField($fieldId); + elseif(!($fieldInfo instanceof ProfileFieldInfo)) + throw new InvalidArgumentException('Entries of $fieldInfos must either be field IDs or instances of ProfileFieldInfo.'); + + $value = $fieldInfo->matchValue($values[$key]); + if($value === false) + throw new InvalidArgumentException('One of the values in $values is not correct formatted.'); + + $rows[] = [ + $fieldInfo->getId(), + $this->selectFieldFormat($fieldInfo, $value)->getId(), + $value, + ]; + } + + $args = 0; + $stmt = $this->cache->get( + 'REPLACE INTO msz_profile_fields_values (field_id, user_id, format_id, field_value) VALUES ' + . msz_where_in_list($rows, '(?, ?, ?, ?)') + ); + + foreach($rows as $row) { + $stmt->addParameter(++$args, $row[0]); + $stmt->addParameter(++$args, $userInfo); + $stmt->addParameter(++$args, $row[1]); + $stmt->addParameter(++$args, $row[2]); + } + + $stmt->execute(); + } + + public function removeFieldValues( + User|string $userInfo, + ProfileFieldInfo|string|array $fieldInfos + ): void { + if(empty($fieldInfos)) + return; + if($userInfo instanceof User) + $userInfo = $userInfo->getId(); + + if(!is_array($fieldInfos)) + $fieldInfos = [$fieldInfos]; + + foreach($fieldInfos as $key => $value) { + if($value instanceof ProfileFieldInfo) + $fieldInfos[$key] = $value->getId(); + elseif(is_string($value)) + throw new InvalidArgumentException('$fieldInfos array may only contain string IDs or instances of ProfileFieldInfo'); + } + + $args = 0; + $stmt = $this->cache->get(sprintf( + 'DELETE FROM msz_profile_fields_values WHERE user_id = ? AND field_id IN (%s)', + msz_where_in_list($fieldInfos) + )); + $stmt->addParameter(++$args, $userInfo); + foreach($fieldInfos as $value) + $stmt->addParameter(++$args, $value); + $stmt->execute(); + } +} diff --git a/src/Users/ProfileField.php b/src/Users/ProfileField.php deleted file mode 100644 index f99c28a..0000000 --- a/src/Users/ProfileField.php +++ /dev/null @@ -1,164 +0,0 @@ -bind('order', $fieldOrder)->bind('key', $fieldKey) - ->bind('title', $fieldTitle)->bind('regex', $fieldRegex) - ->executeGetId(); - - if($createField < 1) - return null; - - return static::get($createField); - } - public static function createFormat( - int $fieldId, - string $formatDisplay = '%s', - ?string $formatLink = null, - ?string $formatRegex = null - ): ?ProfileField { - $createFormat = DB::prepare(' - INSERT INTO `msz_profile_fields_formats` ( - `field_id`, `format_regex`, `format_link`, `format_display` - ) VALUES (:field, :regex, :link, :display) - ')->bind('field', $fieldId) ->bind('regex', $formatRegex) - ->bind('link', $formatLink)->bind('display', $formatDisplay) - ->executeGetId(); - - if($createFormat < 1) - return null; - - return static::get($createFormat); - } - - public static function get(int $fieldId): ?ProfileField { - return DB::prepare( - 'SELECT `field_id`, `field_order`, `field_key`, `field_title`, `field_regex`' - . ' FROM `msz_profile_fields`' - . ' WHERE `field_id` = :field_id' - )->bind('field_id', $fieldId)->fetchObject(ProfileField::class); - } - - public static function user(int $userId, bool $filterEmpty = true): array { - $fields = DB::prepare( - 'SELECT pf.`field_id`, pf.`field_order`, pf.`field_key`, pf.`field_title`, pf.`field_regex`' - . ', pff.`format_id`, pff.`format_regex`, pff.`format_link`, pff.`format_display`' - . ', COALESCE(pfv.`user_id`, :user2) AS `user_id`, pfv.`field_value`' - . ' FROM `msz_profile_fields` AS pf' - . ' LEFT JOIN `msz_profile_fields_values` AS pfv ON pfv.`field_id` = pf.`field_id` AND pfv.`user_id` = :user1' - . ' LEFT JOIN `msz_profile_fields_formats` AS pff ON pff.`field_id` = pf.`field_id` AND pff.`format_id` = pfv.`format_id`' - . ' ORDER BY pf.`field_order`' - )->bind('user1', $userId)->bind('user2', $userId)->fetchObjects(ProfileField::class); - - if($filterEmpty) { - $newFields = []; - - foreach($fields as $field) { - if(!empty($field->field_value)) - $newFields[] = $field; - } - - $fields = $newFields; - } - - return $fields; - } - - public function findDisplayFormat(string $value): int { - if(!isset($this->field_id)) - return 0; - - $format = DB::prepare(' - SELECT `format_id` - FROM `msz_profile_fields_formats` - WHERE `field_id` = :field - AND `format_regex` IS NOT NULL - AND :value REGEXP `format_regex` - ')->bind('field', $this->field_id) - ->bind('value', $value) - ->fetchColumn(); - - if($format < 1) { - $format = DB::prepare(' - SELECT `format_id` - FROM `msz_profile_fields_formats` - WHERE `field_id` = :field - AND `format_regex` IS NULL - ')->bind('field', $this->field_id) - ->fetchColumn(0, 0); - } - - return $format; - } - - // todo: use exceptions - public function setFieldValue(string $value): bool { - if(!isset($this->user_id, $this->field_id, $this->field_regex)) - return false; - - if(empty($value)) { - DB::prepare(' - DELETE FROM `msz_profile_fields_values` - WHERE `user_id` = :user - AND `field_id` = :field - ')->bind('user', $this->user_id) - ->bind('field', $this->field_id) - ->execute(); - $this->field_value = ''; - return true; - } - - if(preg_match($this->field_regex, $value, $matches)) { - $value = $matches[1]; - } else { - return false; - } - - $displayFormat = $this->findDisplayFormat($value); - - if($displayFormat < 1) - return false; - - $updateField = DB::prepare(' - REPLACE INTO `msz_profile_fields_values` - (`field_id`, `user_id`, `format_id`, `field_value`) - VALUES - (:field, :user, :format, :value) - ')->bind('field', $this->field_id) - ->bind('user', $this->user_id) - ->bind('format', $displayFormat) - ->bind('value', $value) - ->execute(); - - if(!$updateField) - return false; - - $this->field_value = $value; - return true; - } -} diff --git a/src/Users/User.php b/src/Users/User.php index c3c206c..133fecb 100644 --- a/src/Users/User.php +++ b/src/Users/User.php @@ -335,12 +335,6 @@ class User implements HasRankInterface { return (int)$this->getBirthdate()->diff(new DateTime('now', new DateTimeZone('UTC')))->format('%y'); } - public function profileFields(bool $filterEmpty = true): array { - if(($userId = $this->getId()) < 1) - return []; - return ProfileField::user($userId, $filterEmpty); - } - public function bumpActivity(string $lastRemoteAddress): void { $this->user_active = time(); $this->last_ip = $lastRemoteAddress; diff --git a/templates/profile/index.twig b/templates/profile/index.twig index 1f96501..2524a90 100644 --- a/templates/profile/index.twig +++ b/templates/profile/index.twig @@ -77,12 +77,11 @@ {% endif %}
- {% set profile_fields = profile_user.profileFields(not (profile_is_editing and perms.edit_profile))|default([]) %} - {% set show_profile_fields = profile_is_editing ? perms.edit_profile : profile_fields|length > 0 %} + {% set show_profile_fields = not profile_is_guest and (profile_is_editing ? perms.edit_profile : profile_fields_display_values is not empty) %} {% set show_background_settings = profile_is_editing and perms.edit_background %} {% set show_birthdate = profile_is_editing and perms.edit_birthdate %} {% set show_active_forum_info = not profile_is_editing and (profile_active_category_info.forum_id|default(0) > 0 or profile_active_topic_info.topic_id|default(0) > 0) %} - {% set show_sidebar = show_profile_fields or show_background_settings or show_birthdate or show_active_forum_info %} + {% set show_sidebar = profile_is_guest or show_profile_fields or show_background_settings or show_birthdate or show_active_forum_info %} {% if show_sidebar %}
@@ -114,25 +113,26 @@ {{ container_title('Elsewhere') }}
- {% for field in profile_fields %} -
diff --git a/utility.php b/utility.php index fd81987..902692f 100644 --- a/utility.php +++ b/utility.php @@ -1,6 +1,12 @@