mirror of
https://github.com/openvk/openvk
synced 2024-11-14 02:59:12 +03:00
Add themepack support
This commit is contained in:
parent
3eb5b6b4fc
commit
d509096d46
14 changed files with 330 additions and 171 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -6,5 +6,8 @@ Web/static/js/node_modules
|
|||
|
||||
tmp/*
|
||||
!tmp/.gitkeep
|
||||
!tmp/themepack_artifacts/.gitkeep
|
||||
themepacks/*
|
||||
!themepacks/.gitkeep
|
||||
storage/*
|
||||
!storage/.gitkeep
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities;
|
||||
use openvk\Web\Themes\{Themepack, Themepacks};
|
||||
use openvk\Web\Util\DateTime;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use openvk\Web\Models\Entities\{Photo, Message, Correspondence};
|
||||
|
@ -53,11 +54,16 @@ class User extends RowModel
|
|||
return $this->getRecord()->id;
|
||||
}
|
||||
|
||||
function getStyle(): int
|
||||
function getStyle(): string
|
||||
{
|
||||
return $this->getRecord()->style;
|
||||
}
|
||||
|
||||
function getTheme(): ?Themepack
|
||||
{
|
||||
return Themepacks::i()[$this->getStyle()] ?? NULL;
|
||||
}
|
||||
|
||||
function getStyleAvatar(): int
|
||||
{
|
||||
return $this->getRecord()->style_avatar;
|
||||
|
|
35
Web/Presenters/ThemepacksPresenter.php
Normal file
35
Web/Presenters/ThemepacksPresenter.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Themes\Themepacks;
|
||||
|
||||
final class ThemepacksPresenter extends OpenVKPresenter
|
||||
{
|
||||
protected $banTolerant = true;
|
||||
|
||||
function renderResource(string $themepack, string $version, string $resClass, string $resource): void
|
||||
{
|
||||
if(!isset(Themepacks::i()[$themepack]))
|
||||
$this->notFound();
|
||||
else
|
||||
$theme = Themepacks::i()[$themepack];
|
||||
|
||||
if($resClass === "resource") {
|
||||
$data = $theme->fetchStaticResource($resource);
|
||||
} else if($resClass === "stylesheet") {
|
||||
if($resource !== "styles.css")
|
||||
$this->notFound();
|
||||
else
|
||||
$data = $theme->fetchStyleSheet();
|
||||
} else {
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
if(!$data)
|
||||
$this->notFound();
|
||||
|
||||
header("Content-Type: " . system_extension_mime_type($resource));
|
||||
header("Content-Size: " . strlen($data));
|
||||
header("Cache-Control: public, no-transform, max-age=31536000");
|
||||
exit($data);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Util\Sms;
|
||||
use openvk\Web\Themes\Themepacks;
|
||||
use openvk\Web\Models\Entities\Photo;
|
||||
use openvk\Web\Models\Repositories\Users;
|
||||
use openvk\Web\Models\Repositories\Albums;
|
||||
|
@ -91,7 +92,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
if(!$id)
|
||||
$this->notFound();
|
||||
else
|
||||
|
||||
$user = $this->users->get($id);
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
||||
|
@ -215,78 +216,79 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
if(!$id)
|
||||
$this->notFound();
|
||||
else
|
||||
$user = $this->users->get($id);
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
||||
if($this->postParam("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) {
|
||||
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
|
||||
if(!$this->user->identity->getChandlerUser()->updatePassword($this->postParam("new_pass"), $this->postParam("old_pass")))
|
||||
$this->flashFail("err", "Ошибка", "Старый пароль не совпадает.");
|
||||
} else {
|
||||
$this->flashFail("err", "Ошибка", "Новые пароли не совпадают.");
|
||||
}
|
||||
|
||||
$user = $this->users->get($id);
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
||||
if($this->postParam("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) {
|
||||
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
|
||||
if(!$this->user->identity->getChandlerUser()->updatePassword($this->postParam("new_pass"), $this->postParam("old_pass")))
|
||||
$this->flashFail("err", "Ошибка", "Старый пароль не совпадает.");
|
||||
} else {
|
||||
$this->flashFail("err", "Ошибка", "Новые пароли не совпадают.");
|
||||
}
|
||||
|
||||
if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc")))
|
||||
$this->flashFail("err", "Ошибка", "Короткий адрес имеет некорректный формат.");
|
||||
}elseif($_GET['act'] === "privacy") {
|
||||
$settings = [
|
||||
"page.read",
|
||||
"page.info.read",
|
||||
"groups.read",
|
||||
"photos.read",
|
||||
"videos.read",
|
||||
"notes.read",
|
||||
"friends.read",
|
||||
"friends.add",
|
||||
"wall.write",
|
||||
];
|
||||
foreach($settings as $setting) {
|
||||
$input = $this->postParam(str_replace(".", "_", $setting));
|
||||
$user->setPrivacySetting($setting, min(3, abs($input ?? $user->getPrivacySetting($setting))));
|
||||
}
|
||||
}elseif($_GET['act'] === "interface") {
|
||||
if ($this->postParam("style") <= 20 && $this->postParam("style") >= 0)
|
||||
$user->setStyle((int)$this->postParam("style"));
|
||||
|
||||
if ($this->postParam("style_avatar") <= 2 && $this->postParam("style_avatar") >= 0)
|
||||
$user->setStyle_Avatar((int)$this->postParam("style_avatar"));
|
||||
|
||||
if (in_array($this->postParam("rating"), [0, 1]))
|
||||
$user->setShow_Rating((int) $this->postParam("rating"));
|
||||
}elseif($_GET['act'] === "lMenu") {
|
||||
$settings = [
|
||||
"menu_bildoj" => "photos",
|
||||
"menu_filmetoj" => "videos",
|
||||
"menu_mesagoj" => "messages",
|
||||
"menu_notatoj" => "notes",
|
||||
"menu_grupoj" => "groups",
|
||||
"menu_novajoj" => "news",
|
||||
];
|
||||
foreach($settings as $checkbox => $setting)
|
||||
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));
|
||||
}
|
||||
|
||||
try {
|
||||
$user->save();
|
||||
} catch(\PDOException $ex) {
|
||||
if($ex->getCode() == 23000)
|
||||
$this->flashFail("err", "Ошибка", "Данный короткий адрес уже занят.");
|
||||
else
|
||||
throw $ex;
|
||||
if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc")))
|
||||
$this->flashFail("err", "Ошибка", "Короткий адрес имеет некорректный формат.");
|
||||
}elseif($_GET['act'] === "privacy") {
|
||||
$settings = [
|
||||
"page.read",
|
||||
"page.info.read",
|
||||
"groups.read",
|
||||
"photos.read",
|
||||
"videos.read",
|
||||
"notes.read",
|
||||
"friends.read",
|
||||
"friends.add",
|
||||
"wall.write",
|
||||
];
|
||||
foreach($settings as $setting) {
|
||||
$input = $this->postParam(str_replace(".", "_", $setting));
|
||||
$user->setPrivacySetting($setting, min(3, abs($input ?? $user->getPrivacySetting($setting))));
|
||||
}
|
||||
}elseif($_GET['act'] === "interface") {
|
||||
if (isset(Themepacks::i()[$this->postParam("style")]) || $this->postParam("style") === Themepacks::DEFAULT_THEME_ID)
|
||||
$user->setStyle($this->postParam("style"));
|
||||
|
||||
$this->flash(
|
||||
"succ",
|
||||
"Изменения сохранены",
|
||||
"Новые данные появятся на вашей странице.<br/>Если вы изменили стиль, перезагрузите страницу."
|
||||
);
|
||||
if ($this->postParam("style_avatar") <= 2 && $this->postParam("style_avatar") >= 0)
|
||||
$user->setStyle_Avatar((int)$this->postParam("style_avatar"));
|
||||
|
||||
if (in_array($this->postParam("rating"), [0, 1]))
|
||||
$user->setShow_Rating((int) $this->postParam("rating"));
|
||||
}elseif($_GET['act'] === "lMenu") {
|
||||
$settings = [
|
||||
"menu_bildoj" => "photos",
|
||||
"menu_filmetoj" => "videos",
|
||||
"menu_mesagoj" => "messages",
|
||||
"menu_notatoj" => "notes",
|
||||
"menu_grupoj" => "groups",
|
||||
"menu_novajoj" => "news",
|
||||
];
|
||||
foreach($settings as $checkbox => $setting)
|
||||
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));
|
||||
}
|
||||
$this->template->mode = in_array($this->queryParam("act"), [
|
||||
"main", "privacy", "finance", "interface"
|
||||
]) ? $this->queryParam("act")
|
||||
: "main";
|
||||
$this->template->user = $user;
|
||||
|
||||
try {
|
||||
$user->save();
|
||||
} catch(\PDOException $ex) {
|
||||
if($ex->getCode() == 23000)
|
||||
$this->flashFail("err", "Ошибка", "Данный короткий адрес уже занят.");
|
||||
else
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$this->flash(
|
||||
"succ",
|
||||
"Изменения сохранены",
|
||||
"Новые данные появятся на вашей странице.<br/>Если вы изменили стиль, перезагрузите страницу."
|
||||
);
|
||||
}
|
||||
$this->template->mode = in_array($this->queryParam("act"), [
|
||||
"main", "privacy", "finance", "interface"
|
||||
]) ? $this->queryParam("act")
|
||||
: "main";
|
||||
$this->template->user = $user;
|
||||
$this->template->themes = Themepacks::i()->getThemeList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,74 +12,9 @@
|
|||
{script "js/node_modules/umbrellajs/umbrella.min.js"}
|
||||
{script "js/openvk.cls.js"}
|
||||
{ifset $thisUser}
|
||||
{var style = (int) ($_GET['__ovkStyleOverride'] ?? $thisUser->getStyle())}
|
||||
|
||||
{if $style == 1}
|
||||
{css "css/vkontakte.css"}
|
||||
{/if}
|
||||
{if $style == 2}
|
||||
{css "css/ovkdan.5.css"}
|
||||
{/if}
|
||||
{if $style == 3}
|
||||
{css "css/vkontakte.css"}
|
||||
{css "css/vkontakte2006.css"}
|
||||
{/if}
|
||||
{if $style == 4}
|
||||
{css "css/ovkg.css"}
|
||||
{/if}
|
||||
{if $style == 5}
|
||||
{css "css/black.css"}
|
||||
{/if}
|
||||
{if $style == 6}
|
||||
{css "css/ash_oss_themes/vk2015.2.css"}
|
||||
{/if}
|
||||
{if $style == 7}
|
||||
{css "css/spacepink.css"}
|
||||
{/if}
|
||||
{if $style == 9}
|
||||
{css "css/vriska.css"}
|
||||
{/if}
|
||||
{if $style == 8}
|
||||
{css "css/ash_oss_themes/vk2015.2.css"}
|
||||
{/if}
|
||||
{if $style == 10}
|
||||
{css "css/ash_oss_themes/ВСоюзе.css"}
|
||||
{/if}
|
||||
{if $style == 11}
|
||||
{css "css/ash_oss_themes/fb2005.css"}
|
||||
{/if}
|
||||
{if $style == 12}
|
||||
{css "css/ooer.css"}
|
||||
{/if}
|
||||
{if $style == 13}
|
||||
{css "css/ash_oss_themes/Twitter2007.css"}
|
||||
{/if}
|
||||
{if $style == 14}
|
||||
{css "css/kos.css"}
|
||||
{/if}
|
||||
{if $style == 15}
|
||||
{css "css/ash_oss_themes/pager.css"}
|
||||
{/if}
|
||||
{if $style == 16}
|
||||
{css "css/ash_oss_themes/vkdark.css"}
|
||||
{/if}
|
||||
{if $style == 17}
|
||||
{css "css/ash_oss_themes/vtlenu.css"}
|
||||
{/if}
|
||||
{if $style == 18}
|
||||
{css "css/ash_oss_themes/Fb2006.css"}
|
||||
{/if}
|
||||
{if $style == 19}
|
||||
{css "css/ash_oss_themes/vkdefenders08.css"}
|
||||
{/if}
|
||||
{if $style == 20}
|
||||
{css "css/ash_oss_themes/tlenta.css"}
|
||||
{/if}
|
||||
{if $thisUser->getStyleAvatar() == 1}
|
||||
{css "css/avatar.1.css"}
|
||||
{/if}
|
||||
{if $thisUser->getStyleAvatar() == 2}
|
||||
{css "css/avatar.2.css"}
|
||||
{if !is_null($thisUser->getTheme())}
|
||||
{var theme = $thisUser->getTheme()}
|
||||
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/stylesheet/styles.css" />
|
||||
{/if}
|
||||
{/ifset}
|
||||
|
||||
|
@ -105,11 +40,7 @@
|
|||
</div>
|
||||
|
||||
<div class="layout">
|
||||
{ifset $thisUser}
|
||||
{if in_array($thisUser->getStyle(), [4, 5, 6, 20])}
|
||||
<div id="xhead" class="dm"></div>
|
||||
{/if}
|
||||
{/ifset}
|
||||
<div id="xhead" class="dm"></div>
|
||||
<div class="page_header">
|
||||
<a href="/" class="home_button" title="OpenVK">openvk</a>
|
||||
<div n:if="isset($thisUser) ? !$thisUser->isBanned() : true" class="header_navigation">
|
||||
|
|
|
@ -305,33 +305,12 @@ Block chain PRIZM был запущен 17 февраля 2017-го года. П
|
|||
</td>
|
||||
<td>
|
||||
<select name="style">
|
||||
<optgroup label="OpenVK">
|
||||
<option value="0" {if $user->getStyle() == 0}selected{/if}>OpenVK ({_"default"})</option>
|
||||
<option value="2" {if $user->getStyle() == 2}selected{/if}>OpenVK [by Daniel Myslivets]</option>
|
||||
<option value="16" {if $user->getStyle() == 16}selected{/if}>OpenVK Night [by Ash Defenders]</option>
|
||||
<option value="5" {if $user->getStyle() == 5}selected{/if}>OpenVK Black [by Daniel Myslivets]</option>
|
||||
<option value="7" {if $user->getStyle() == 7}selected{/if}>OpenVK SpacePink [by Ash Defenders]</option>
|
||||
</optgroup>
|
||||
<optgroup label="VKontakte">
|
||||
<option value="3" {if $user->getStyle() == 3}selected{/if}>ВКонтакте (2006)</option>
|
||||
<option value="1" {if $user->getStyle() == 1}selected{/if}>ВКонтакте (2007)</option>
|
||||
<option value="8" {if $user->getStyle() == 8}selected{/if}>ВКонтакте (2015) [by Ash Defenders]</option>
|
||||
<option value="19" {if $user->getStyle() == 19}selected{/if}>VK.COM [by Ash Defenders]</option>
|
||||
<option value="6" {if $user->getStyle() == 6}selected{/if} disabled>VK.com (не работает)</option>
|
||||
<option value="10" {if $user->getStyle() == 10}selected{/if}>ВСоюзе</option>
|
||||
<option value="17" {if $user->getStyle() == 17}selected{/if}>ВТлену [by Ash Defenders]</option>
|
||||
</optgroup>
|
||||
<optgroup label="Сайты">
|
||||
<option value="11" {if $user->getStyle() == 11}selected{/if}>TheFacebook (2005) [by Ash Defenders]</option>
|
||||
<option value="18" {if $user->getStyle() == 18}selected{/if}>Facebook (2006) [by Ash Defenders]</option>
|
||||
<option value="13" {if $user->getStyle() == 13}selected{/if}>Twitter (2007) [by Ash Defenders]</option>
|
||||
<option value="4" {if $user->getStyle() == 4}selected{/if}>IVinete.ru [by Daniel Myslivets]</option>
|
||||
<option value="15" {if $user->getStyle() == 15}selected{/if}>Пейджер [by Ash Defenders]</option>
|
||||
<option value="20" {if $user->getStyle() == 20}selected{/if}>TLENTA.RU [by Ash Defenders]</option>
|
||||
<option value="14" {if $user->getStyle() == 14}selected{/if}>kosSpace</option>
|
||||
<option value="9" {if $user->getStyle() == 9}selected{/if}>vriska.ru</option>
|
||||
<option value="12" {if $user->getStyle() == 12}selected{/if}>r/Ooer</option>
|
||||
</optgroup>
|
||||
<option value="ovk" {if $user->getStyle() == 'ovk'}selected{/if}>OpenVK ({_"default"})</option>
|
||||
<option n:foreach="$themes as $id => $theme"
|
||||
n:attr="selected => $user->getStyle() === $id"
|
||||
value="{$id}">
|
||||
{$theme}
|
||||
</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
5
Web/Themes/Exceptions/IncompatibleThemeException.php
Normal file
5
Web/Themes/Exceptions/IncompatibleThemeException.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Themes\Exceptions;
|
||||
|
||||
final class IncompatibleThemeException extends \Exception
|
||||
{}
|
5
Web/Themes/Exceptions/MalformedManifestException.php
Normal file
5
Web/Themes/Exceptions/MalformedManifestException.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Themes\Exceptions;
|
||||
|
||||
final class MalformedManifestException extends \Exception
|
||||
{}
|
5
Web/Themes/Exceptions/NotThemeDirectoryException.php
Normal file
5
Web/Themes/Exceptions/NotThemeDirectoryException.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Themes\Exceptions;
|
||||
|
||||
final class NotThemeDirectoryException extends \Exception
|
||||
{}
|
76
Web/Themes/Themepack.php
Normal file
76
Web/Themes/Themepack.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Themes;
|
||||
|
||||
class Themepack
|
||||
{
|
||||
private $id;
|
||||
private $ver;
|
||||
private $meta;
|
||||
private $home;
|
||||
|
||||
function __construct(string $id, string $ver, object $meta)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->ver = $ver;
|
||||
$this->meta = $meta;
|
||||
$this->home = OPENVK_ROOT . "/themepacks/$id";
|
||||
}
|
||||
|
||||
function getId(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
function getName(?string $lang = NULL): string
|
||||
{
|
||||
if(!$this->meta->name)
|
||||
return $this->getId() . " theme";
|
||||
else if(is_array($this->meta->name))
|
||||
return $this->meta->name[$lang ?? "_"] ?? $this->getId() . " theme";
|
||||
else
|
||||
return $this->meta->name;
|
||||
}
|
||||
|
||||
function getVersion(): string
|
||||
{
|
||||
return $this->ver;
|
||||
}
|
||||
|
||||
function getDescription(): string
|
||||
{
|
||||
return $this->meta->description ?? "A theme with name \"" . $this->getName() . "\"";
|
||||
}
|
||||
|
||||
function getAuthor(): string
|
||||
{
|
||||
return $this->meta->author ?? $this->getName() . " authors";
|
||||
}
|
||||
|
||||
function fetchStyleSheet(): ?string
|
||||
{
|
||||
$file = "$this->home/stylesheet.css";
|
||||
return file_exists($file) ? file_get_contents($file) : NULL;
|
||||
}
|
||||
|
||||
function fetchStaticResource(string $name): ?string
|
||||
{
|
||||
$file = "$this->home/res/$name";
|
||||
return file_exists($file) ? file_get_contents($file) : NULL;
|
||||
}
|
||||
|
||||
static function themepackFromDir(string $dirname): Themepack
|
||||
{
|
||||
$manifestFile = "$dirname/theme.yml";
|
||||
if(!file_exists($manifestFile))
|
||||
throw new Exceptions\NotThemeDirectoryException("Could not locate manifest at $dirname");
|
||||
|
||||
$manifest = (object) chandler_parse_yaml($manifestFile);
|
||||
if(!isset($manifest->id) || !isset($manifest->version) || !isset($manifest->openvk_version) || !isset($manifest->metadata))
|
||||
throw new Exceptions\MalformedManifestException("Manifest is missing required information");
|
||||
|
||||
if($manifest->openvk_version > Themepacks::THEMPACK_ENGINE_VERSION)
|
||||
throw new Exceptions\IncompatibleThemeException("Theme is built for newer OVK (themeEngine" . $manifest->openvk_version . ")");
|
||||
|
||||
return new static($manifest->id, $manifest->version, (object) $manifest->metadata);
|
||||
}
|
||||
}
|
105
Web/Themes/Themepacks.php
Normal file
105
Web/Themes/Themepacks.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Themes;
|
||||
use Nette\InvalidStateException as ISE;
|
||||
use Chandler\Session\Session;
|
||||
use Chandler\Patterns\TSimpleSingleton;
|
||||
|
||||
class Themepacks implements \ArrayAccess
|
||||
{
|
||||
const THEMPACK_ENGINE_VERSION = 1;
|
||||
const DEFAULT_THEME_ID = "ovk"; # блин было бы смешно если было бы Fore, потому что Лунка, а Luna это название дефолт темы винхп
|
||||
|
||||
private $loadedThemepacks = [];
|
||||
|
||||
function __construct()
|
||||
{
|
||||
foreach(glob(OPENVK_ROOT . "/themepacks/*", GLOB_ONLYDIR) as $themeDir) {
|
||||
try {
|
||||
$theme = Themepack::themepackFromDir($themeDir);
|
||||
$tid = $theme->getId();
|
||||
if(isset($this->loadedThemepacks[$tid]))
|
||||
trigger_error("Duplicate theme $tid found at $themeDir, skipping...", E_USER_WARNING);
|
||||
else
|
||||
$this->loadedThemepacks[$tid] = $theme;
|
||||
} catch(\Exception $e) {
|
||||
trigger_error("Could not load theme at $themeDir, skipping...", E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function installUnpacked(string $path): bool
|
||||
{
|
||||
try {
|
||||
$theme = Themepack::themepackFromDir($path);
|
||||
$tid = $theme->getId();
|
||||
if(isset($this->loadedThemepacks[$tid]))
|
||||
return false;
|
||||
|
||||
rename($path, OPENVK_ROOT . "/themepacks/$tid");
|
||||
$this->loadedThemepacks[$tid] = $theme;
|
||||
return true;
|
||||
} catch(\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getThemeList(): \Traversable
|
||||
{
|
||||
foreach($this->loadedThemepacks as $id => $theme)
|
||||
yield $id => ($theme->getName(Session::i()->get("lang", "ru")));
|
||||
}
|
||||
|
||||
/* ArrayAccess */
|
||||
|
||||
function offsetExists($offset): bool
|
||||
{
|
||||
return $offset === Themepacks::DEFAULT_THEME_ID ? false : isset($this->loadedThemepacks[$offset]);
|
||||
}
|
||||
|
||||
function offsetGet($offset)
|
||||
{
|
||||
return $this->loadedThemepacks[$offset];
|
||||
}
|
||||
|
||||
function offsetSet($offset, $value): void
|
||||
{
|
||||
throw new ISE("Theme substitution in runtime is prohbited");
|
||||
}
|
||||
|
||||
function offsetUnset($offset): void
|
||||
{
|
||||
$this->uninstall($offset);
|
||||
}
|
||||
|
||||
/* /ArrayAccess */
|
||||
|
||||
function install(string $archivePath): bool
|
||||
{
|
||||
if(!file_exists($archivePath))
|
||||
return false;
|
||||
|
||||
$tmpDir = mkdir(tempnam(OPENVK_ROOT . "/tmp/themepack_artifacts/", "themex_"));
|
||||
try {
|
||||
$archive = new \CabArchive($archivePath);
|
||||
$archive->extract($tmpDir);
|
||||
|
||||
return $this->installUnpacked($tmpDir);
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
} finally {
|
||||
rmdir($tmpDir);
|
||||
}
|
||||
}
|
||||
|
||||
function uninstall(string $id): bool
|
||||
{
|
||||
if(!isset($loadedThemepacks[$id]))
|
||||
return false;
|
||||
|
||||
rmdir(OPENVK_ROOT . "/themepacks/$id");
|
||||
unset($loadedThemepacks[$id]);
|
||||
return true;
|
||||
}
|
||||
|
||||
use TSimpleSingleton;
|
||||
}
|
|
@ -19,6 +19,7 @@ services:
|
|||
- openvk\Web\Presenters\SupportPresenter
|
||||
- openvk\Web\Presenters\AdminPresenter
|
||||
- openvk\Web\Presenters\MessengerPresenter
|
||||
- openvk\Web\Presenters\ThemepacksPresenter
|
||||
- openvk\Web\Models\Repositories\Users
|
||||
- openvk\Web\Models\Repositories\Posts
|
||||
- openvk\Web\Models\Repositories\Photos
|
||||
|
|
|
@ -91,6 +91,12 @@ routes:
|
|||
handler: "Wall->delete"
|
||||
- url: "/blob_{text}/{text}.{text}"
|
||||
handler: "Blob->file"
|
||||
- url: "/themepack/{text}/{?version}/{?resClass}/{?any}"
|
||||
handler: "Themepacks->resource"
|
||||
placeholders:
|
||||
version: "(?:[0-9]+\\.?)+"
|
||||
resClass: "stylesheet|resource"
|
||||
any: ".+"
|
||||
- url: "/albums{num}"
|
||||
handler: "Photos->albumList"
|
||||
- url: "/albums/create"
|
||||
|
|
0
themepacks/.gitkeep
Normal file
0
themepacks/.gitkeep
Normal file
Loading…
Reference in a new issue