272 lines
9.9 KiB
PHP
272 lines
9.9 KiB
PHP
<?php
|
|
namespace Misuzu\Profile;
|
|
|
|
use InvalidArgumentException;
|
|
use RuntimeException;
|
|
use Index\Data\DbStatementCache;
|
|
use Index\Data\DbTools;
|
|
use Index\Data\IDbConnection;
|
|
use Index\Data\IDbResult;
|
|
use Misuzu\Users\User;
|
|
|
|
class ProfileFields {
|
|
private DbStatementCache $cache;
|
|
|
|
public function __construct(IDbConnection $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)', DbTools::prepareListString($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)', DbTools::prepareListString($fieldInfos));
|
|
}
|
|
if($hasFieldValueInfos)
|
|
$query .= sprintf(' %s format_id IN (%s)',
|
|
(++$args > 1 ? 'AND' : 'WHERE'),
|
|
DbTools::prepareListString($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($fieldInfo);
|
|
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 '
|
|
. DbTools::prepareListString($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)',
|
|
DbTools::prepareListString($fieldInfos)
|
|
));
|
|
$stmt->addParameter(++$args, $userInfo);
|
|
foreach($fieldInfos as $value)
|
|
$stmt->addParameter(++$args, $value);
|
|
$stmt->execute();
|
|
}
|
|
}
|