362 lines
11 KiB
PHP
362 lines
11 KiB
PHP
<?php
|
|
namespace YTKNS;
|
|
|
|
use Exception;
|
|
|
|
class ZoneNotFoundException extends Exception {};
|
|
class ZoneCreationFailedException extends Exception {};
|
|
class ZoneInvalidIdException extends Exception {};
|
|
class ZoneInvalidNameException extends Exception {};
|
|
class ZoneInvalidTitleException extends Exception {};
|
|
|
|
final class Zone {
|
|
private $effects = null;
|
|
private $passiveMode = false;
|
|
|
|
public function __construct() {
|
|
}
|
|
|
|
public function setPassiveMode(): void {
|
|
$this->passiveMode = true;
|
|
|
|
if($this->effects === null)
|
|
$this->effects = [];
|
|
}
|
|
|
|
public function getId(): int {
|
|
return $this->zone_id ?? 0;
|
|
}
|
|
public function hasId(): bool {
|
|
return isset($this->zone_id) && $this->zone_id > 0;
|
|
}
|
|
private function setId(int $id): void {
|
|
if($id < 1)
|
|
throw new ZoneInvalidIdException;
|
|
|
|
$this->zone_id = $id;
|
|
}
|
|
|
|
public function getUserId(): int {
|
|
return $this->user_id ?? 0;
|
|
}
|
|
public function setUserId(int $userId): void {
|
|
$this->user_id = $userId;
|
|
}
|
|
|
|
private $userObj = null;
|
|
public function getUser(): User {
|
|
if($this->userObj === null)
|
|
$this->userObj = User::byId($this->getUserId());
|
|
|
|
return $this->userObj;
|
|
}
|
|
|
|
public function getName(): string {
|
|
return $this->zone_name;
|
|
}
|
|
public function setName(string $name): void {
|
|
if(!self::validName($name))
|
|
throw new ZoneInvalidNameException;
|
|
|
|
$this->zone_name = $name;
|
|
}
|
|
|
|
public function getUrl(): string {
|
|
return 'https://' . sprintf(Config::get('domain.zone'), $this->getName());
|
|
}
|
|
public function getUrlForPreview(): string {
|
|
return $this->getUrl() . '?preview=1';
|
|
}
|
|
|
|
public function getScreenshotPath(): string {
|
|
return YTKNS_SCREENSHOTS . '/' . $this->getName() . '.jpg';
|
|
}
|
|
public function getScreenshotUrl(): string {
|
|
return 'https://' . Config::get('domain.main') . '/ss/' . $this->getName() . '.jpg';
|
|
}
|
|
public function takeScreenshot(): void {
|
|
$path = escapeshellarg($this->getScreenshotPath());
|
|
$url = escapeshellarg($this->getUrlForPreview());
|
|
system(sprintf('/usr/bin/firefox --window-size=800,600 --screenshot %s %s', $path, $url));
|
|
//system(sprintf('/usr/bin/convert %1$s 200x150 %1$s', $path));
|
|
|
|
}
|
|
public function removeScreenshot(): void {
|
|
$path = $this->getScreenshotPath();
|
|
|
|
if(is_file($path))
|
|
unlink($path);
|
|
}
|
|
|
|
public function getTitle(): string {
|
|
return $this->zone_title;
|
|
}
|
|
public function setTitle(string $title): void {
|
|
if(strlen($title) > 255)
|
|
throw new ZoneInvalidTitleException;
|
|
|
|
$this->zone_title = $title;
|
|
}
|
|
|
|
public function getViews(): int {
|
|
return $this->zone_views ?? 0;
|
|
}
|
|
|
|
public function incrementViews(): void {
|
|
$updateViews = DB::prepare('
|
|
UPDATE `ytkns_zones`
|
|
SET `zone_views` = `zone_views` + 1
|
|
WHERE `zone_id` = :zone
|
|
');
|
|
$updateViews->bindValue('zone', $this->getId());
|
|
if($updateViews->execute())
|
|
$this->zone_views = $this->getViews() + 1;
|
|
}
|
|
|
|
public function getEffects(): array {
|
|
if(!is_array($this->effects))
|
|
$this->effects = $this->hasId() ? ZoneEffect::byZone($this) : [];
|
|
|
|
return $this->effects;
|
|
}
|
|
|
|
public function getPageBuilder(bool $quiet = false): PageBuilder {
|
|
$pageBuilder = new PageBuilder($this->getTitle());
|
|
|
|
$effects = $this->getEffects();
|
|
|
|
foreach($effects as $effect)
|
|
$effect->applyEffect($pageBuilder, $quiet);
|
|
|
|
return $pageBuilder;
|
|
}
|
|
|
|
public function addEffect(PageEffectInterface $effect): void {
|
|
if(is_array($this->effects))
|
|
$this->effects[] = $effect;
|
|
|
|
if(!$this->passiveMode)
|
|
$this->addEffectDatabase($effect);
|
|
}
|
|
private function addEffectDatabase(PageEffectInterface $effect): void {
|
|
if(!$this->hasId())
|
|
return;
|
|
|
|
$insert = DB::prepare('
|
|
REPLACE INTO `ytkns_zones_effects` (
|
|
`zone_id`, `effect_name`, `effect_params`
|
|
) VALUES (
|
|
:zone, :name, :params
|
|
)
|
|
');
|
|
$insert->bindValue('zone', $this->getId());
|
|
$insert->bindValue('name', substr(get_class($effect), 14, -6));
|
|
$insert->bindValue('params', json_encode($effect->getEffectParams()));
|
|
$insert->execute();
|
|
}
|
|
|
|
public function removeEffects(): void {
|
|
$this->effects = [];
|
|
|
|
if(!$this->passiveMode)
|
|
$this->removeEffectsDatabase();
|
|
}
|
|
private function removeEffectsDatabase(): void {
|
|
if(!$this->hasId())
|
|
return;
|
|
|
|
$removeEffects = DB::prepare('
|
|
DELETE FROM `ytkns_zones_effects`
|
|
WHERE `zone_id` = :zone
|
|
');
|
|
$removeEffects->bindValue('zone', $this->getId());
|
|
$removeEffects->execute();
|
|
}
|
|
|
|
public static function byId(string $id): self {
|
|
$getZone = DB::prepare('
|
|
SELECT `zone_id`, `user_id`, `zone_name`, `zone_title`, `zone_views`,
|
|
UNIX_TIMESTAMP(`zone_created`) AS `zone_created`,
|
|
UNIX_TIMESTAMP(`zone_updated`) AS `zone_updated`
|
|
FROM `ytkns_zones`
|
|
WHERE `zone_id` = :zone
|
|
');
|
|
$getZone->bindValue('zone', $id);
|
|
$zone = $getZone->execute() ? $getZone->fetchObject(self::class) : false;
|
|
|
|
if(!$zone)
|
|
throw new ZoneNotFoundException;
|
|
|
|
return $zone;
|
|
}
|
|
|
|
public static function byName(string $name): self {
|
|
$getZone = DB::prepare('
|
|
SELECT `zone_id`, `user_id`, `zone_name`, `zone_title`, `zone_views`,
|
|
UNIX_TIMESTAMP(`zone_created`) AS `zone_created`,
|
|
UNIX_TIMESTAMP(`zone_updated`) AS `zone_updated`
|
|
FROM `ytkns_zones`
|
|
WHERE `zone_name` = :name
|
|
');
|
|
$getZone->bindValue('name', $name);
|
|
$zone = $getZone->execute() ? $getZone->fetchObject(self::class) : false;
|
|
|
|
if(!$zone)
|
|
throw new ZoneNotFoundException;
|
|
|
|
return $zone;
|
|
}
|
|
|
|
public static function byUser(User $user, ?string $orderBy = null, bool $ascending = true, int $take = 0, int $offset = 0): array {
|
|
$getZonesQuery = '
|
|
SELECT `zone_id`, `user_id`, `zone_name`, `zone_title`, `zone_views`,
|
|
UNIX_TIMESTAMP(`zone_created`) AS `zone_created`,
|
|
UNIX_TIMESTAMP(`zone_updated`) AS `zone_updated`
|
|
FROM `ytkns_zones`
|
|
WHERE `user_id` = :user
|
|
';
|
|
|
|
if($orderBy !== null)
|
|
$getZonesQuery .= sprintf('ORDER BY `%s` %s', $orderBy, $ascending ? 'ASC' : 'DESC');
|
|
if($take > 0)
|
|
$getZonesQuery .= sprintf(' LIMIT %d OFFSET %d', $take, $offset);
|
|
|
|
$getZones = DB::prepare($getZonesQuery);
|
|
$getZones->bindValue('user', $user->getId());
|
|
$getZones->execute();
|
|
$zones = [];
|
|
|
|
while($zone = $getZones->fetchObject(self::class))
|
|
$zones[] = $zone;
|
|
|
|
return $zones;
|
|
}
|
|
|
|
public static function all(?string $orderBy = null, bool $ascending = true, int $take = 0, int $offset = 0): array {
|
|
$getZonesQuery = '
|
|
SELECT `zone_id`, `user_id`, `zone_name`, `zone_title`, `zone_views`,
|
|
UNIX_TIMESTAMP(`zone_created`) AS `zone_created`,
|
|
UNIX_TIMESTAMP(`zone_updated`) AS `zone_updated`
|
|
FROM `ytkns_zones`
|
|
';
|
|
|
|
if($orderBy !== null)
|
|
$getZonesQuery .= sprintf(' ORDER BY `%s` %s', $orderBy, $ascending ? 'ASC' : 'DESC');
|
|
if($take > 0)
|
|
$getZonesQuery .= sprintf(' LIMIT %d OFFSET %d', $take, $offset);
|
|
|
|
$getZones = DB::prepare($getZonesQuery);
|
|
$getZones->execute();
|
|
$zones = [];
|
|
|
|
while($zone = $getZones->fetchObject(self::class))
|
|
$zones[] = $zone;
|
|
|
|
return $zones;
|
|
}
|
|
|
|
public static function count(): int {
|
|
$getZoneCount = DB::prepare('
|
|
SELECT COUNT(`zone_id`)
|
|
FROM `ytkns_zones`
|
|
');
|
|
return (int)($getZoneCount->execute() ? $getZoneCount->fetchColumn() : 0);
|
|
}
|
|
|
|
public static function create(User $user, string $name, string $title): self {
|
|
$create = DB::prepare('
|
|
INSERT INTO `ytkns_zones` (
|
|
`user_id`, `zone_name`, `zone_title`
|
|
) VALUES (
|
|
:user, LOWER(:name), :title
|
|
)
|
|
');
|
|
$create->bindValue('user', $user->getId());
|
|
$create->bindValue('name', $name);
|
|
$create->bindValue('title', $title);
|
|
$create->execute();
|
|
|
|
try {
|
|
return self::byName($name);
|
|
} catch(ZoneNotFoundException $ex) {
|
|
throw new ZoneCreationFailedException;
|
|
}
|
|
}
|
|
|
|
public function update(array $save = ['user_id', 'zone_name', 'zone_title']): void {
|
|
if(!$this->hasId())
|
|
return;
|
|
|
|
$set = [
|
|
'`zone_updated` = NOW()',
|
|
];
|
|
|
|
foreach($save as $param)
|
|
$set[] = sprintf('`%1$s` = :%1$s', $param);
|
|
|
|
$update = DB::prepare(sprintf('UPDATE `ytkns_zones` SET %s WHERE `zone_id` = :zone', implode(', ', $set)));
|
|
|
|
if(in_array('user_id', $save))
|
|
$update->bindValue('user_id', $this->getUserId());
|
|
if(in_array('zone_name', $save))
|
|
$update->bindValue('zone_name', $this->getName());
|
|
if(in_array('zone_title', $save))
|
|
$update->bindValue('zone_title', $this->getTitle());
|
|
|
|
$update->bindValue('zone', $this->getId());
|
|
$update->execute();
|
|
|
|
if($this->passiveMode) {
|
|
$effects = $this->getEffects();
|
|
$this->removeEffectsDatabase();
|
|
|
|
foreach($this->getEffects() as $effectInfo)
|
|
$this->addEffectDatabase($effectInfo);
|
|
}
|
|
}
|
|
|
|
public static function exists(string $name): bool {
|
|
$check = DB::prepare('
|
|
SELECT COUNT(`zone_name`) > 0
|
|
FROM `ytkns_zones`
|
|
WHERE `zone_name` = :name
|
|
');
|
|
$check->bindValue('name', $name);
|
|
return $check->execute() ? (bool)$check->fetchColumn() : true;
|
|
}
|
|
|
|
public function delete(): void {
|
|
$delete = DB::prepare('
|
|
DELETE FROM `ytkns_zones`
|
|
WHERE `zone_id` = :zone
|
|
');
|
|
$delete->bindValue('zone', $this->getId());
|
|
$delete->execute();
|
|
}
|
|
|
|
public static function validName(string $name): bool {
|
|
return preg_match('#^([A-Za-z0-9]{1,50})$#', $name);
|
|
}
|
|
|
|
public function toJson(bool $asString = false) {
|
|
$zoneInfo = [
|
|
'id' => $this->getId(),
|
|
'name' => $this->getName(),
|
|
'title' => $this->getTitle(),
|
|
'effects' => [],
|
|
];
|
|
|
|
foreach($this->getEffects() as $effect)
|
|
$zoneInfo['effects'][] = $effect->toJson();
|
|
|
|
if($asString)
|
|
$zoneInfo = json_encode($zoneInfo);
|
|
|
|
return $zoneInfo;
|
|
}
|
|
|
|
public function queueTask(string $task, ...$params): void {
|
|
ZoneTask::enqueue($this, $task, $params);
|
|
}
|
|
}
|