Improved profile fields code.
This commit is contained in:
parent
2e49940260
commit
f32624c61d
11 changed files with 528 additions and 221 deletions
|
@ -4,6 +4,7 @@ namespace Misuzu;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Index\ByteFormat;
|
use Index\ByteFormat;
|
||||||
use Misuzu\Parsers\Parser;
|
use Misuzu\Parsers\Parser;
|
||||||
|
use Misuzu\Profile\ProfileFields;
|
||||||
use Misuzu\Users\User;
|
use Misuzu\Users\User;
|
||||||
use Misuzu\Users\UserNotFoundException;
|
use Misuzu\Users\UserNotFoundException;
|
||||||
use Misuzu\Users\UserSession;
|
use Misuzu\Users\UserSession;
|
||||||
|
@ -34,6 +35,7 @@ if($profileUser->isDeleted()) {
|
||||||
|
|
||||||
$notices = [];
|
$notices = [];
|
||||||
|
|
||||||
|
$profileFields = new ProfileFields($db);
|
||||||
$currentUser = User::getCurrent();
|
$currentUser = User::getCurrent();
|
||||||
$viewingAsGuest = $currentUser === null;
|
$viewingAsGuest = $currentUser === null;
|
||||||
$currentUserId = $viewingAsGuest ? 0 : $currentUser->getId();
|
$currentUserId = $viewingAsGuest ? 0 : $currentUser->getId();
|
||||||
|
@ -72,19 +74,37 @@ if($isEditing) {
|
||||||
if(!CSRF::validateRequest()) {
|
if(!CSRF::validateRequest()) {
|
||||||
$notices[] = 'Couldn\'t verify you, please refresh the page and retry.';
|
$notices[] = 'Couldn\'t verify you, please refresh the page and retry.';
|
||||||
} else {
|
} 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']) {
|
if(!$perms['edit_profile']) {
|
||||||
$notices[] = 'You\'re not allowed to edit your profile';
|
$notices[] = 'You\'re not allowed to edit your profile';
|
||||||
} else {
|
} else {
|
||||||
$profileFields = $profileUser->profileFields(false);
|
$profileFieldInfos = $profileFields->getFields();
|
||||||
|
$profileFieldsSetInfos = [];
|
||||||
|
$profileFieldsSetValues = [];
|
||||||
|
$profileFieldsRemove = [];
|
||||||
|
|
||||||
foreach($profileFields as $profileField) {
|
foreach($profileFieldInfos as $fieldInfo) {
|
||||||
if(isset($_POST['profile'][$profileField->field_key])
|
$fieldName = $fieldInfo->getName();
|
||||||
&& $profileField->field_value !== $_POST['profile'][$profileField->field_key]
|
$fieldValue = empty($profileFieldsSubmit[$fieldName]) ? '' : (string)filter_var($profileFieldsSubmit[$fieldName]);
|
||||||
&& !$profileField->setFieldValue($_POST['profile'][$profileField->field_key])) {
|
|
||||||
$notices[] = sprintf('%s was formatted incorrectly!', $profileField->field_title);
|
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);
|
$aboutValid = User::validateProfileAbout($aboutParse, $aboutText);
|
||||||
|
|
||||||
if($aboutValid === '')
|
if($aboutValid === '')
|
||||||
$currentUser->setProfileAboutText($aboutText)->setProfileAboutParser($aboutParse);
|
$profileUser->setProfileAboutText($aboutText)->setProfileAboutParser($aboutParse);
|
||||||
else switch($aboutValid) {
|
else switch($aboutValid) {
|
||||||
case 'parser':
|
case 'parser':
|
||||||
$notices[] = 'The selected about section parser is invalid.';
|
$notices[] = 'The selected about section parser is invalid.';
|
||||||
|
@ -121,7 +141,7 @@ if($isEditing) {
|
||||||
$sigValid = User::validateForumSignature($sigParse, $sigText);
|
$sigValid = User::validateForumSignature($sigParse, $sigText);
|
||||||
|
|
||||||
if($sigValid === '')
|
if($sigValid === '')
|
||||||
$currentUser->setForumSignatureText($sigText)->setForumSignatureParser($sigParse);
|
$profileUser->setForumSignatureText($sigText)->setForumSignatureParser($sigParse);
|
||||||
else switch($sigValid) {
|
else switch($sigValid) {
|
||||||
case 'parser':
|
case 'parser':
|
||||||
$notices[] = 'The selected forum signature parser is invalid.';
|
$notices[] = 'The selected forum signature parser is invalid.';
|
||||||
|
@ -146,7 +166,7 @@ if($isEditing) {
|
||||||
$birthValid = User::validateBirthdate($birthYear, $birthMonth, $birthDay);
|
$birthValid = User::validateBirthdate($birthYear, $birthMonth, $birthDay);
|
||||||
|
|
||||||
if($birthValid === '')
|
if($birthValid === '')
|
||||||
$currentUser->setBirthdate($birthYear, $birthMonth, $birthDay);
|
$profileUser->setBirthdate($birthYear, $birthMonth, $birthDay);
|
||||||
else switch($birthValid) {
|
else switch($birthValid) {
|
||||||
case 'year':
|
case 'year':
|
||||||
$notices[] = 'The given birth year is invalid.';
|
$notices[] = 'The given birth year is invalid.';
|
||||||
|
@ -352,21 +372,64 @@ switch($profileMode) {
|
||||||
$template = 'profile.index';
|
$template = 'profile.index';
|
||||||
$warnings = $profileUser->getProfileWarnings($currentUser);
|
$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([
|
Template::set([
|
||||||
'profile_warnings' => $warnings,
|
'profile_warnings' => $warnings,
|
||||||
'profile_warnings_view_private' => $canManageWarnings,
|
'profile_warnings_view_private' => $canManageWarnings,
|
||||||
'profile_warnings_can_manage' => $canManageWarnings,
|
'profile_warnings_can_manage' => $canManageWarnings,
|
||||||
|
]);
|
||||||
|
|
||||||
|
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_stats' => $activeCategoryStats,
|
||||||
'profile_active_category_info' => $activeCategoryInfo,
|
'profile_active_category_info' => $activeCategoryInfo,
|
||||||
'profile_active_topic_stats' => $activeTopicStats,
|
'profile_active_topic_stats' => $activeTopicStats,
|
||||||
'profile_active_topic_info' => $activeTopicInfo,
|
'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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,5 +443,6 @@ if(!empty($template)) {
|
||||||
'profile_can_edit' => $canEdit,
|
'profile_can_edit' => $canEdit,
|
||||||
'profile_is_editing' => $isEditing,
|
'profile_is_editing' => $isEditing,
|
||||||
'profile_is_banned' => $isBanned,
|
'profile_is_banned' => $isBanned,
|
||||||
|
'profile_is_guest' => $viewingAsGuest,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ class Changelog {
|
||||||
$query .= (++$args > 1 ? ' AND' : ' WHERE');
|
$query .= (++$args > 1 ? ' AND' : ' WHERE');
|
||||||
$query .= sprintf(
|
$query .= sprintf(
|
||||||
' change_id IN (SELECT change_id FROM msz_changelog_change_tags WHERE tag_id IN (%s))',
|
' 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);
|
$stmt = $this->cache->get($query);
|
||||||
|
@ -177,7 +177,7 @@ class Changelog {
|
||||||
$query .= (++$args > 1 ? ' AND' : ' WHERE');
|
$query .= (++$args > 1 ? ' AND' : ' WHERE');
|
||||||
$query .= sprintf(
|
$query .= sprintf(
|
||||||
' change_id IN (SELECT change_id FROM msz_changelog_change_tags WHERE tag_id IN (%s))',
|
' 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';
|
$query .= ' GROUP BY change_created, change_id ORDER BY change_created DESC, change_id DESC';
|
||||||
|
|
|
@ -23,10 +23,6 @@ class DbConfig implements IConfig {
|
||||||
return preg_match('#^([a-z][a-zA-Z0-9._]+)$#', $name) === 1;
|
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 {
|
public function reset(): void {
|
||||||
$this->values = [];
|
$this->values = [];
|
||||||
}
|
}
|
||||||
|
@ -61,7 +57,7 @@ class DbConfig implements IConfig {
|
||||||
|
|
||||||
$stmt = $this->cache->get(sprintf(
|
$stmt = $this->cache->get(sprintf(
|
||||||
'SELECT COUNT(*) FROM msz_config WHERE config_name IN (%s)',
|
'SELECT COUNT(*) FROM msz_config WHERE config_name IN (%s)',
|
||||||
self::whereInList($nameCount)
|
msz_where_in_list($nameCount)
|
||||||
));
|
));
|
||||||
for($i = 0; $i < $nameCount; ++$i)
|
for($i = 0; $i < $nameCount; ++$i)
|
||||||
$stmt->addParameter($i + 1, $names[$i]);
|
$stmt->addParameter($i + 1, $names[$i]);
|
||||||
|
@ -87,7 +83,7 @@ class DbConfig implements IConfig {
|
||||||
$nameCount = count($names);
|
$nameCount = count($names);
|
||||||
$stmt = $this->cache->get(sprintf(
|
$stmt = $this->cache->get(sprintf(
|
||||||
'DELETE FROM msz_config WHERE config_name IN (%s)',
|
'DELETE FROM msz_config WHERE config_name IN (%s)',
|
||||||
self::whereInList($nameCount)
|
msz_where_in_list($nameCount)
|
||||||
));
|
));
|
||||||
|
|
||||||
for($i = 0; $i < $nameCount; ++$i)
|
for($i = 0; $i < $nameCount; ++$i)
|
||||||
|
@ -147,7 +143,7 @@ class DbConfig implements IConfig {
|
||||||
|
|
||||||
$stmt = $this->cache->get(sprintf(
|
$stmt = $this->cache->get(sprintf(
|
||||||
'SELECT config_name, config_value FROM msz_config WHERE config_name IN (%s)',
|
'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)
|
for($i = 0; $i < $nameCount; ++$i)
|
||||||
$stmt->addParameter($i + 1, $names[$i]);
|
$stmt->addParameter($i + 1, $names[$i]);
|
||||||
|
@ -271,7 +267,7 @@ class DbConfig implements IConfig {
|
||||||
|
|
||||||
$stmt = $this->cache->get(sprintf(
|
$stmt = $this->cache->get(sprintf(
|
||||||
'REPLACE INTO msz_config (config_name, config_value) VALUES %s',
|
'REPLACE INTO msz_config (config_name, config_value) VALUES %s',
|
||||||
implode(', ', array_fill(0, $valueCount, '(?, ?)'))
|
msz_where_in_list($valueCount, '(?, ?)')
|
||||||
));
|
));
|
||||||
|
|
||||||
$args = 0;
|
$args = 0;
|
||||||
|
|
56
src/Profile/ProfileFieldFormatInfo.php
Normal file
56
src/Profile/ProfileFieldFormatInfo.php
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\Profile;
|
||||||
|
|
||||||
|
use Index\Data\IDbResult;
|
||||||
|
|
||||||
|
class ProfileFieldFormatInfo {
|
||||||
|
private string $id;
|
||||||
|
private string $fieldId;
|
||||||
|
private ?string $regex;
|
||||||
|
private ?string $linkFormat;
|
||||||
|
private string $displayFormat;
|
||||||
|
|
||||||
|
public function __construct(IDbResult $result) {
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
48
src/Profile/ProfileFieldInfo.php
Normal file
48
src/Profile/ProfileFieldInfo.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\Profile;
|
||||||
|
|
||||||
|
use Index\Data\IDbResult;
|
||||||
|
|
||||||
|
class ProfileFieldInfo {
|
||||||
|
private string $id;
|
||||||
|
private int $order;
|
||||||
|
private string $name;
|
||||||
|
private string $title;
|
||||||
|
private string $regex;
|
||||||
|
|
||||||
|
public function __construct(IDbResult $result) {
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
34
src/Profile/ProfileFieldValueInfo.php
Normal file
34
src/Profile/ProfileFieldValueInfo.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\Profile;
|
||||||
|
|
||||||
|
use Index\Data\IDbResult;
|
||||||
|
|
||||||
|
class ProfileFieldValueInfo {
|
||||||
|
private string $fieldId;
|
||||||
|
private string $userId;
|
||||||
|
private string $formatId;
|
||||||
|
private string $value;
|
||||||
|
|
||||||
|
public function __construct(IDbResult $result) {
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
273
src/Profile/ProfileFields.php
Normal file
273
src/Profile/ProfileFields.php
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\Profile;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use RuntimeException;
|
||||||
|
use Index\Data\IDbConnection;
|
||||||
|
use Index\Data\IDbResult;
|
||||||
|
use Misuzu\DbStatementCache;
|
||||||
|
use Misuzu\Users\User;
|
||||||
|
|
||||||
|
class ProfileFields {
|
||||||
|
private IDbConnection $dbConn;
|
||||||
|
private DbStatementCache $cache;
|
||||||
|
|
||||||
|
public function __construct(IDbConnection $dbConn) {
|
||||||
|
$this->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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,164 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Misuzu\Users;
|
|
||||||
|
|
||||||
use Misuzu\DB;
|
|
||||||
|
|
||||||
class ProfileField {
|
|
||||||
// Database fields
|
|
||||||
public $field_id;
|
|
||||||
public $user_id;
|
|
||||||
public $field_regex;
|
|
||||||
public $field_value;
|
|
||||||
public $field_order;
|
|
||||||
public $field_key;
|
|
||||||
public $field_title;
|
|
||||||
public $format_id;
|
|
||||||
public $format_regex;
|
|
||||||
public $format_link;
|
|
||||||
public $format_display;
|
|
||||||
|
|
||||||
public static function createField(
|
|
||||||
string $fieldKey,
|
|
||||||
string $fieldTitle,
|
|
||||||
string $fieldRegex,
|
|
||||||
int $fieldOrder
|
|
||||||
): ?ProfileField {
|
|
||||||
$createField = DB::prepare('
|
|
||||||
INSERT INTO `msz_profile_fields` (
|
|
||||||
`field_order`, `field_key`, `field_title`, `field_regex`
|
|
||||||
) VALUES (:order, :key, :title, :regex)
|
|
||||||
')->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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -335,12 +335,6 @@ class User implements HasRankInterface {
|
||||||
return (int)$this->getBirthdate()->diff(new DateTime('now', new DateTimeZone('UTC')))->format('%y');
|
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 {
|
public function bumpActivity(string $lastRemoteAddress): void {
|
||||||
$this->user_active = time();
|
$this->user_active = time();
|
||||||
$this->last_ip = $lastRemoteAddress;
|
$this->last_ip = $lastRemoteAddress;
|
||||||
|
|
|
@ -77,12 +77,11 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="profile__content">
|
<div class="profile__content">
|
||||||
{% set profile_fields = profile_user.profileFields(not (profile_is_editing and perms.edit_profile))|default([]) %}
|
{% set show_profile_fields = not profile_is_guest and (profile_is_editing ? perms.edit_profile : profile_fields_display_values is not empty) %}
|
||||||
{% set show_profile_fields = profile_is_editing ? perms.edit_profile : profile_fields|length > 0 %}
|
|
||||||
{% set show_background_settings = profile_is_editing and perms.edit_background %}
|
{% set show_background_settings = profile_is_editing and perms.edit_background %}
|
||||||
{% set show_birthdate = profile_is_editing and perms.edit_birthdate %}
|
{% 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_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 %}
|
{% if show_sidebar %}
|
||||||
<div class="profile__content__side">
|
<div class="profile__content__side">
|
||||||
|
@ -114,25 +113,26 @@
|
||||||
{{ container_title('Elsewhere') }}
|
{{ container_title('Elsewhere') }}
|
||||||
|
|
||||||
<div class="profile__accounts__content">
|
<div class="profile__accounts__content">
|
||||||
{% for field in profile_fields %}
|
{% for fieldInfo in profile_fields_infos %}
|
||||||
|
{% if profile_is_editing or profile_fields_display_values[fieldInfo.name] is defined %}
|
||||||
<label class="profile__accounts__item">
|
<label class="profile__accounts__item">
|
||||||
<div class="profile__accounts__title">
|
<div class="profile__accounts__title">
|
||||||
{{ field.field_title }}
|
{{ fieldInfo.title }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if profile_is_editing %}
|
{% if profile_is_editing %}
|
||||||
{{ input_text('profile[' ~ field.field_key ~ ']', 'profile__accounts__input', field.field_value, data.type|default('text')) }}
|
{{ input_text('profile[' ~ fieldInfo.name ~ ']', 'profile__accounts__input', profile_fields_raw_values[fieldInfo.name]|default('')) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="profile__accounts__value">
|
<div class="profile__accounts__value">
|
||||||
{% set profile_field_value = field.format_display|format(field.field_value) %}
|
{% if profile_fields_link_values[fieldInfo.name] is defined %}
|
||||||
{% if field.format_link is empty %}
|
<a href="{{ profile_fields_link_values[fieldInfo.name] }}" class="profile__accounts__link" target="_blank" rel="noreferrer noopener">{{ profile_fields_display_values[fieldInfo.name] }}</a>
|
||||||
{{ profile_field_value }}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ field.format_link|format(field.field_value) }}" class="profile__accounts__link" target="_blank" rel="noreferrer noopener">{{ profile_field_value }}</a>
|
{{ profile_fields_display_values[fieldInfo.name] }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</label>
|
</label>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
use Index\Colour\Colour;
|
use Index\Colour\Colour;
|
||||||
|
|
||||||
|
function msz_where_in_list(Countable|array|int $count, string $repeat = '?', string $separator = ', '): string {
|
||||||
|
if(is_countable($count))
|
||||||
|
$count = count($count);
|
||||||
|
return implode($separator, array_fill(0, $count, $repeat));
|
||||||
|
}
|
||||||
|
|
||||||
// render_error and render_info need to be nuked from orbit
|
// render_error and render_info need to be nuked from orbit
|
||||||
|
|
||||||
function render_error(int $code, string $template = 'errors.%d'): string {
|
function render_error(int $code, string $template = 'errors.%d'): string {
|
||||||
|
|
Loading…
Reference in a new issue