Template/Update (Part 38)

* split Screenshot upload & management into separate endpoints
 * move shared functions to manager classes
 * cleanup javascript
 * move test for config screenshot min size to cfg class
This commit is contained in:
Sarjuuk
2025-08-13 23:19:57 +02:00
parent 3d3e2211e5
commit a369244908
35 changed files with 1546 additions and 1031 deletions

View File

@@ -7,7 +7,7 @@ if (!defined('AOWOW_REVISION'))
class AjaxAdmin extends AjaxHandler
{
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide', 'comment'];
protected $validParams = ['siteconfig', 'weight-presets', 'spawn-override', 'guide', 'comment'];
protected $_get = array(
'action' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkTextLine' ],
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkIdListUnsigned'],
@@ -37,27 +37,7 @@ class AjaxAdmin extends AjaxHandler
if (!$this->params)
return;
if ($this->params[0] == 'screenshots' && $this->_get['action'])
{
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT))
return;
if ($this->_get['action'] == 'list')
$this->handler = 'ssList';
else if ($this->_get['action'] == 'manage')
$this->handler = 'ssManage';
else if ($this->_get['action'] == 'editalt')
$this->handler = 'ssEditAlt';
else if ($this->_get['action'] == 'approve')
$this->handler = 'ssApprove';
else if ($this->_get['action'] == 'sticky')
$this->handler = 'ssSticky';
else if ($this->_get['action'] == 'delete')
$this->handler = 'ssDelete';
else if ($this->_get['action'] == 'relocate')
$this->handler = 'ssRelocate';
}
else if ($this->params[0] == 'siteconfig' && $this->_get['action'])
if ($this->params[0] == 'siteconfig' && $this->_get['action'])
{
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
return;
@@ -100,227 +80,6 @@ class AjaxAdmin extends AjaxHandler
}
}
// get all => null (optional)
// evaled response .. UNK
protected function ssList() : string
{
// ssm_screenshotPages
// ssm_numPagesFound
$pages = CommunityContent::getScreenshotPagesForManager($this->_get['all'], $nPages);
$buff = 'ssm_screenshotPages = '.Util::toJSON($pages).";\n";
$buff .= 'ssm_numPagesFound = '.$nPages.';';
return $buff;
}
// get: [type => type, typeId => typeId] || [user => username]
// evaled response .. UNK
protected function ssManage() : string
{
$res = [];
if ($this->_get['type'] && $this->_get['type'] && $this->_get['typeid'] && $this->_get['typeid'])
$res = CommunityContent::getScreenshotsForManager($this->_get['type'], $this->_get['typeid']);
else if ($this->_get['user'])
if ($uId = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE LOWER(`username`) = LOWER(?)', $this->_get['user']))
$res = CommunityContent::getScreenshotsForManager(0, 0, $uId);
return 'ssm_screenshotData = '.Util::toJSON($res);
}
// get: id => SSid
// resp: ''
protected function ssEditAlt() : void
{
// doesn't need to be htmlEscaped, ths javascript does that
if ($this->_get['id'] && $this->_post['alt'] !== null)
DB::Aowow()->query('UPDATE ?_screenshots SET caption = ? WHERE id = ?d', trim($this->_post['alt']), $this->_get['id'][0]);
}
// get: id => comma-separated SSids
// resp: ''
protected function ssApprove() : void
{
if (!$this->reqGET('id'))
{
trigger_error('AjaxAdmin::ssApprove - screenshotId empty', E_USER_ERROR);
return;
}
// create resized and thumb version of screenshot
$resized = [772, 618];
$thumb = [150, 150];
$path = 'static/uploads/screenshots/%s/%d.jpg';
foreach ($this->_get['id'] as $id)
{
// must not be already approved
if ($ssEntry = DB::Aowow()->selectRow('SELECT userIdOwner, date, type, typeId FROM ?_screenshots WHERE (status & ?d) = 0 AND id = ?d', CC_FLAG_APPROVED, $id))
{
// should also error-log
if (!file_exists(sprintf($path, 'pending', $id)))
{
trigger_error('AjaxAdmin::ssApprove - screenshot #'.$id.' exists in db but not as file', E_USER_ERROR);
continue;
}
$srcImg = imagecreatefromjpeg(sprintf($path, 'pending', $id));
$srcW = imagesx($srcImg);
$srcH = imagesy($srcImg);
// write thumb
$scale = min(1.0, min($thumb[0] / $srcW, $thumb[1] / $srcH));
$destW = $srcW * $scale;
$destH = $srcH * $scale;
$destImg = imagecreatetruecolor($destW, $destH);
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
imagejpeg($destImg, sprintf($path, 'thumb', $id), 100);
// write resized (only if required)
if ($srcW > $resized[0] || $srcH > $resized[1])
{
$scale = min(1.0, min($resized[0] / $srcW, $resized[1] / $srcH));
$destW = $srcW * $scale;
$destH = $srcH * $scale;
$destImg = imagecreatetruecolor($destW, $destH);
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
imagejpeg($destImg, sprintf($path, 'resized', $id), 100);
}
imagedestroy($srcImg);
// move screenshot from pending to normal
rename(sprintf($path, 'pending', $id), sprintf($path, 'normal', $id));
// set as approved in DB and gain rep (once!)
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdApprove = ?d WHERE id = ?d', CC_FLAG_APPROVED, User::$id, $id);
Util::gainSiteReputation($ssEntry['userIdOwner'], SITEREP_ACTION_UPLOAD, ['id' => $id, 'what' => 1, 'date' => $ssEntry['date']]);
// flag DB entry as having screenshots
if ($tbl = Type::getClassAttrib($ssEntry['type'], 'dataTable'))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $ssEntry['typeId']);
}
else
trigger_error('AjaxAdmin::ssApprove - screenshot #'.$id.' not in db or already approved', E_USER_ERROR);
}
return;
}
// get: id => comma-separated SSids
// resp: ''
protected function ssSticky() : void
{
if (!$this->reqGET('id'))
{
trigger_error('AjaxAdmin::ssSticky - screenshotId empty', E_USER_ERROR);
return;
}
// approve soon to be sticky screenshots
$this->ssApprove();
// this one is a bit strange: as far as i've seen, the only thing a 'sticky' screenshot does is show up in the infobox
// this also means, that only one screenshot per page should be sticky
// so, handle it one by one and the last one affecting one particular type/typId-key gets the cake
foreach ($this->_get['id'] as $id)
{
// reset all others
DB::Aowow()->query('UPDATE ?_screenshots a, ?_screenshots b SET a.status = a.status & ~?d WHERE a.type = b.type AND a.typeId = b.typeId AND a.id <> b.id AND b.id = ?d', CC_FLAG_STICKY, $id);
// toggle sticky status
DB::Aowow()->query('UPDATE ?_screenshots SET `status` = IF(`status` & ?d, `status` & ~?d, `status` | ?d) WHERE id = ?d AND `status` & ?d', CC_FLAG_STICKY, CC_FLAG_STICKY, CC_FLAG_STICKY, $id, CC_FLAG_APPROVED);
}
}
// get: id => comma-separated SSids
// resp: ''
// 2 steps: 1) remove from sight, 2) remove from disk
protected function ssDelete() : void
{
if (!$this->reqGET('id'))
{
trigger_error('AjaxAdmin::ssDelete - screenshotId empty', E_USER_ERROR);
return;
}
$path = 'static/uploads/screenshots/%s/%d.jpg';
foreach ($this->_get['id'] as $id)
{
// irrevocably remove already deleted files
if (User::isInGroup(U_GROUP_ADMIN) && DB::Aowow()->selectCell('SELECT 1 FROM ?_screenshots WHERE status & ?d AND id = ?d', CC_FLAG_DELETED, $id))
{
DB::Aowow()->query('DELETE FROM ?_screenshots WHERE id = ?d', $id);
if (file_exists(sprintf($path, 'pending', $id)))
unlink(sprintf($path, 'pending', $id));
continue;
}
// move pending or normal to pending
if (file_exists(sprintf($path, 'normal', $id)))
rename(sprintf($path, 'normal', $id), sprintf($path, 'pending', $id));
// remove resized and thumb
if (file_exists(sprintf($path, 'thumb', $id)))
unlink(sprintf($path, 'thumb', $id));
if (file_exists(sprintf($path, 'resized', $id)))
unlink(sprintf($path, 'resized', $id));
}
// flag as deleted if not aready
$oldEntries = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, GROUP_CONCAT(typeId) FROM ?_screenshots WHERE id IN (?a) GROUP BY `type`', $this->_get['id']);
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdDelete = ?d WHERE id IN (?a)', CC_FLAG_DELETED, User::$id, $this->_get['id']);
// deflag db entry as having screenshots
foreach ($oldEntries as $type => $typeIds)
{
$typeIds = explode(',', $typeIds);
$toUnflag = DB::Aowow()->selectCol('SELECT typeId AS ARRAY_KEY, IF(BIT_OR(`status`) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `type` = ?d AND typeId IN (?a) GROUP BY typeId HAVING hasMore = 0', CC_FLAG_APPROVED, $type, $typeIds);
if ($toUnflag && ($tbl = Type::getClassAttrib($type, 'dataTable')))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id IN (?a)', CUSTOM_HAS_SCREENSHOT, array_keys($toUnflag));
}
}
// get: id => ssId, typeid => typeId (but not type..?)
// resp: ''
protected function ssRelocate() : void
{
if (!$this->reqGET('id', 'typeid'))
{
trigger_error('AjaxAdmin::ssRelocate - screenshotId or typeId empty', E_USER_ERROR);
return;
}
$id = $this->_get['id'][0];
[$type, $oldTypeId] = array_values(DB::Aowow()->selectRow('SELECT type, typeId FROM ?_screenshots WHERE id = ?d', $id));
$typeId = (int)$this->_get['typeid'];
$tc = Type::newList($type, [['id', $typeId]]);
if ($tc && !$tc->error)
{
// move screenshot
DB::Aowow()->query('UPDATE ?_screenshots SET typeId = ?d WHERE id = ?d', $typeId, $id);
// flag target as having screenshot
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $typeId);
// deflag source for having had screenshots (maybe)
$ssInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~status) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `status`& ?d AND `type` = ?d AND typeId = ?d', CC_FLAG_DELETED, CC_FLAG_APPROVED, $type, $oldTypeId);
if($ssInfo || !$ssInfo['hasMore'])
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $oldTypeId);
}
else
trigger_error('AjaxAdmin::ssRelocate - invalid typeId #'.$typeId.' for type #'.$type, E_USER_ERROR);
}
protected function confAdd() : string
{
$key = trim($this->_get['key']);