misuzu/src/Profile/ProfileFields.php

272 lines
9.9 KiB
PHP

<?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 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)', 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($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 '
. 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();
}
}