web/lib/Artist.php

330 lines
7.5 KiB
PHP

<?
use Safe\DateTimeImmutable;
/**
* @property ?int $DeathYear
* @property ?string $UrlName
* @property ?string $Url
* @property string $DeleteUrl
* @property array<string> $AlternateNames
* @property string $AlternateNamesString
*/
class Artist{
use Traits\Accessor;
use Traits\PropertyFromHttp;
public int $ArtistId;
public string $Name = '';
public DateTimeImmutable $Created;
public DateTimeImmutable $Updated;
public ?int $DeathYear = null;
protected string $_UrlName;
protected string $_Url;
protected string $_DeleteUrl;
/** @var array<string> $_AlternateNames */
protected array $_AlternateNames;
protected string $_AlternateNamesString;
// *******
// GETTERS
// *******
protected function GetUrlName(): string{
if(!isset($this->_UrlName)){
if(!isset($this->Name) || $this->Name == ''){
$this->_UrlName = '';
}
else{
$this->_UrlName = Formatter::MakeUrlSafe($this->Name);
}
}
return $this->_UrlName;
}
protected function GetUrl(): string{
return $this->_Url ??= '/artworks/' . $this->UrlName;
}
protected function GetDeleteUrl(): string{
return $this->_DeleteUrl ??= '/artworks/' . $this->UrlName . '/delete';
}
/**
* @return array<string>
*/
protected function GetAlternateNames(): array{
if(!isset($this->_AlternateNames)){
$this->_AlternateNames = [];
$result = Db::Query('
SELECT *
from ArtistAlternateNames
where ArtistId = ?
', [$this->ArtistId]);
foreach($result as $row){
$this->_AlternateNames[] = $row->Name;
}
}
return $this->_AlternateNames;
}
protected function GetAlternateNamesString(): string{
if(!isset($this->_AlternateNamesString)){
$this->_AlternateNamesString = '';
$alternateNames = array_slice($this->AlternateNames, 0, -2);
$lastTwoAlternateNames = array_slice($this->AlternateNames, -2);
foreach($alternateNames as $alternateName){
$this->_AlternateNamesString .= $alternateName . ', ';
}
$this->_AlternateNamesString = rtrim($this->_AlternateNamesString, ', ');
if(sizeof($lastTwoAlternateNames) == 1){
if(sizeof($alternateNames) > 0){
$this->_AlternateNamesString .= ', and ';
}
$this->_AlternateNamesString .= $lastTwoAlternateNames[0];
}
if(sizeof($lastTwoAlternateNames) == 2){
if(sizeof($alternateNames) > 0){
$this->_AlternateNamesString .= ', ';
$this->_AlternateNamesString .= $lastTwoAlternateNames[0] . ', and ' . $lastTwoAlternateNames[1];
}
else{
$this->_AlternateNamesString .= $lastTwoAlternateNames[0] . ' and ' . $lastTwoAlternateNames[1];
}
}
}
return $this->_AlternateNamesString;
}
// *******
// METHODS
// *******
/**
* @throws Exceptions\InvalidArtistException
*/
public function Validate(): void{
$thisYear = intval(NOW->format('Y'));
$error = new Exceptions\InvalidArtistException();
$this->Name = trim($this->Name ?? '');
if($this->Name == ''){
$error->Add(new Exceptions\ArtistNameRequiredException());
}
elseif(strlen($this->Name) > ARTWORK_MAX_STRING_LENGTH){
$error->Add(new Exceptions\StringTooLongException('Artist Name'));
}
if($this->Name == 'Anonymous' && $this->DeathYear !== null){
$this->DeathYear = null;
}
if($this->DeathYear !== null && ($this->DeathYear <= 0 || $this->DeathYear > $thisYear + 50)){
$error->Add(new Exceptions\InvalidDeathYearException());
}
if($error->HasExceptions){
throw $error;
}
}
public function FillFromHttpPost(): void{
$this->PropertyFromHttp('Name');
$this->PropertyFromHttp('DeathYear');
}
// ***********
// ORM METHODS
// ***********
/**
* @throws Exceptions\ArtistNotFoundException
*/
public static function Get(?int $artistId): Artist{
if($artistId === null){
throw new Exceptions\ArtistNotFoundException();
}
return Db::Query('
SELECT *
from Artists
where ArtistId = ?
', [$artistId], Artist::class)[0] ?? throw new Exceptions\ArtistNotFoundException();
}
/**
* @return array<Artist>
*/
public static function GetAll(): array{
return Db::Query('
SELECT *
from Artists
order by Name asc', [], Artist::class);
}
/**
* @throws Exceptions\ArtistNotFoundException
*/
public static function GetByName(?string $name): Artist{
if($name === null){
throw new Exceptions\ArtistNotFoundException();
}
return Db::Query('
SELECT a.*
from Artists a
left outer join ArtistAlternateNames aan using (ArtistId)
where a.Name = ?
or aan.Name = ?
', [$name, $name], Artist::class)[0] ?? throw new Exceptions\ArtistNotFoundException();
}
/**
* @throws Exceptions\ArtistNotFoundException
*/
public static function GetByUrlName(?string $urlName): Artist{
if($urlName === null){
throw new Exceptions\ArtistNotFoundException();
}
return Db::Query('
SELECT *
from Artists
where UrlName = ?
', [$urlName], Artist::class)[0] ?? throw new Exceptions\ArtistNotFoundException();
}
/**
* @throws Exceptions\ArtistNotFoundException
*/
public static function GetByAlternateUrlName(?string $urlName): Artist{
if($urlName === null){
throw new Exceptions\ArtistNotFoundException();
}
return Db::Query('
SELECT a.*
from Artists a
left outer join ArtistAlternateNames aan using (ArtistId)
where aan.UrlName = ?
limit 1
', [$urlName], Artist::class)[0] ?? throw new Exceptions\ArtistNotFoundException();
}
/**
* @throws Exceptions\ArtistAlternateNameExistsException
*/
public function AddAlternateName(string $name): void{
try{
Db::Query('
INSERT into ArtistAlternateNames (ArtistId, Name, UrlName)
values (?,
?,
?)
', [$this->ArtistId, $name, Formatter::MakeUrlSafe($name)]);
}
catch(Exceptions\DuplicateDatabaseKeyException){
throw new Exceptions\ArtistAlternateNameExistsException();
}
}
/**
* Reassigns all the artworks currently assigned to this artist to the given canoncial artist.
*
* @param Artist $canonicalArtist
*/
public function ReassignArtworkTo(Artist $canonicalArtist): void{
Db::Query('
UPDATE Artworks
set ArtistId = ?
where ArtistId = ?
', [$canonicalArtist->ArtistId, $this->ArtistId]);
Db::Query('
UPDATE
ArtistAlternateNames
set ArtistId = ?
where ArtistId = ?
', [$canonicalArtist->ArtistId, $this->ArtistId]);
}
/**
* @throws Exceptions\InvalidArtistException
*/
public function Create(): void{
$this->Validate();
Db::Query('
INSERT into Artists (Name, UrlName, DeathYear)
values (?,
?,
?)
', [$this->Name, $this->UrlName, $this->DeathYear]);
$this->ArtistId = Db::GetLastInsertedId();
}
/**
* @throws Exceptions\InvalidArtistException
*/
public static function GetOrCreate(Artist $artist): Artist{
$result = Db::Query('
SELECT a.*
from Artists a
left outer join ArtistAlternateNames aan using (ArtistId)
where a.UrlName = ?
or aan.UrlName = ?
limit 1
', [$artist->UrlName, $artist->UrlName], Artist::class);
if(isset($result[0])){
return $result[0];
}
else{
$artist->Create();
return $artist;
}
}
/**
* @throws Exceptions\ArtistHasArtworkException
*/
public function Delete(): void{
$hasArtwork = Db::QueryBool('
SELECT exists (
SELECT ArtworkId
from Artworks
where ArtistId = ?
)', [$this->ArtistId]);
if($hasArtwork){
throw new Exceptions\ArtistHasArtworkException();
}
Db::Query('
DELETE
from Artists
where ArtistId = ?
', [$this->ArtistId]);
Db::Query('
DELETE
from ArtistAlternateNames
where ArtistId = ?
', [$this->ArtistId]);
}
}