Initial import of space_profiles module
This commit is contained in:
291
models/forms/SpaceProfileForm.php
Normal file
291
models/forms/SpaceProfileForm.php
Normal file
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
namespace humhub\modules\space_profiles\models\forms;
|
||||
|
||||
use humhub\modules\content\components\ContentContainerActiveRecord;
|
||||
use humhub\modules\rescue_foundation\components\UploadStandards;
|
||||
use humhub\modules\rescue_foundation\components\ValidationStandards;
|
||||
use humhub\modules\space\models\Space;
|
||||
use humhub\modules\space_profiles\components\TemplateRegistry;
|
||||
use humhub\modules\space_profiles\helpers\ProfileHtmlSanitizer;
|
||||
use humhub\modules\space_profiles\models\SpaceProfile;
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use yii\helpers\FileHelper;
|
||||
use yii\web\UploadedFile;
|
||||
|
||||
class SpaceProfileForm extends Model
|
||||
{
|
||||
public ContentContainerActiveRecord $contentContainer;
|
||||
|
||||
public string $rescue_name = '';
|
||||
public string $address = '';
|
||||
public string $city = '';
|
||||
public string $state = '';
|
||||
public string $zip = '';
|
||||
public string $email = '';
|
||||
public string $phone = '';
|
||||
public string $animals_we_accept = '';
|
||||
public string $description = '';
|
||||
public string $mission_statement = '';
|
||||
public string $template_key = TemplateRegistry::TEMPLATE_RESCUE_CENTER;
|
||||
public ?string $header_html = null;
|
||||
public ?string $body_html = null;
|
||||
public ?string $footer_html = null;
|
||||
|
||||
public UploadedFile|string|null $iconFile = null;
|
||||
public UploadedFile|string|null $backgroundImageFile = null;
|
||||
public bool $removeIcon = false;
|
||||
public bool $removeBackgroundImage = false;
|
||||
|
||||
private ?SpaceProfile $profile = null;
|
||||
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->profile = SpaceProfile::findOne(['contentcontainer_id' => $this->contentContainer->contentcontainer_id]);
|
||||
|
||||
if ($this->profile) {
|
||||
$this->address = (string)$this->profile->address;
|
||||
$this->city = (string)$this->profile->city;
|
||||
$this->state = (string)$this->profile->state;
|
||||
$this->zip = (string)$this->profile->zip;
|
||||
$this->email = (string)$this->profile->email;
|
||||
$this->phone = (string)$this->profile->phone;
|
||||
$this->animals_we_accept = (string)$this->profile->animals_we_accept;
|
||||
$this->mission_statement = (string)$this->profile->mission_statement;
|
||||
$this->template_key = !empty($this->profile->template_key)
|
||||
? (string)$this->profile->template_key
|
||||
: TemplateRegistry::TEMPLATE_RESCUE_CENTER;
|
||||
$this->header_html = $this->profile->header_html;
|
||||
$this->body_html = $this->profile->body_html;
|
||||
$this->footer_html = $this->profile->footer_html;
|
||||
}
|
||||
|
||||
$this->rescue_name = $this->getSpaceName();
|
||||
$this->description = $this->getSpaceDescription();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$contactRules = ValidationStandards::contactRules([
|
||||
'email' => 'email',
|
||||
'phone' => 'phone',
|
||||
'state' => 'state',
|
||||
'zip' => 'zip',
|
||||
]);
|
||||
|
||||
return array_merge([
|
||||
[['address', 'city', 'state', 'zip', 'email', 'phone', 'animals_we_accept', 'mission_statement', 'template_key'], 'required'],
|
||||
[['animals_we_accept', 'description', 'mission_statement', 'header_html', 'body_html', 'footer_html'], 'string'],
|
||||
[['template_key'], 'in', 'range' => array_keys(TemplateRegistry::options())],
|
||||
[['rescue_name', 'email'], 'string', 'max' => 190],
|
||||
[['address'], 'string', 'max' => 255],
|
||||
[['city'], 'string', 'max' => 120],
|
||||
[['state'], 'string', 'max' => 2],
|
||||
[['zip'], 'string', 'max' => 10],
|
||||
[['phone'], 'string', 'max' => 32],
|
||||
[['template_key'], 'string', 'max' => 64],
|
||||
[['removeIcon', 'removeBackgroundImage'], 'boolean'],
|
||||
[['iconFile', 'backgroundImageFile'], 'file',
|
||||
'skipOnEmpty' => true,
|
||||
'extensions' => UploadStandards::imageExtensions(),
|
||||
'checkExtensionByMimeType' => true,
|
||||
'mimeTypes' => UploadStandards::imageMimeTypes(),
|
||||
'maxSize' => UploadStandards::IMAGE_MAX_BYTES,
|
||||
],
|
||||
], $contactRules);
|
||||
}
|
||||
|
||||
public function save(): bool
|
||||
{
|
||||
if (!$this->validate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$persistedDescription = $this->resolvePersistedDescription();
|
||||
|
||||
$profile = $this->profile ?: new SpaceProfile();
|
||||
$profile->contentcontainer_id = $this->contentContainer->contentcontainer_id;
|
||||
$profile->rescue_name = $this->getSpaceName();
|
||||
$profile->address = trim($this->address);
|
||||
$profile->city = trim($this->city);
|
||||
$profile->state = strtoupper(trim($this->state));
|
||||
$profile->zip = trim($this->zip);
|
||||
$profile->email = trim($this->email);
|
||||
$profile->phone = trim($this->phone);
|
||||
$profile->animals_we_accept = trim($this->animals_we_accept);
|
||||
$profile->description = $persistedDescription;
|
||||
$profile->mission_statement = trim($this->mission_statement);
|
||||
$profile->slug = $this->generateUniqueSlug();
|
||||
$profile->template_key = $this->template_key;
|
||||
$profile->header_html = ProfileHtmlSanitizer::sanitize($this->header_html);
|
||||
$profile->body_html = ProfileHtmlSanitizer::sanitize($this->body_html);
|
||||
$profile->footer_html = ProfileHtmlSanitizer::sanitize($this->footer_html);
|
||||
|
||||
if ($this->removeIcon) {
|
||||
$this->deleteStoredFile($profile->icon_path);
|
||||
$profile->icon_path = null;
|
||||
}
|
||||
|
||||
if ($this->removeBackgroundImage) {
|
||||
$this->deleteStoredFile($profile->background_image_path);
|
||||
$profile->background_image_path = null;
|
||||
}
|
||||
|
||||
if ($this->iconFile instanceof UploadedFile) {
|
||||
$this->deleteStoredFile($profile->icon_path);
|
||||
$profile->icon_path = $this->storeImage($this->iconFile, 'icon');
|
||||
}
|
||||
|
||||
if ($this->backgroundImageFile instanceof UploadedFile) {
|
||||
$this->deleteStoredFile($profile->background_image_path);
|
||||
$profile->background_image_path = $this->storeImage($this->backgroundImageFile, 'background');
|
||||
}
|
||||
|
||||
if (!$profile->save()) {
|
||||
$this->addErrors($profile->getErrors());
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setDefaultHomePage();
|
||||
$this->profile = $profile;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getProfile(): ?SpaceProfile
|
||||
{
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
public function getTemplateOptions(): array
|
||||
{
|
||||
return TemplateRegistry::options();
|
||||
}
|
||||
|
||||
private function storeImage(UploadedFile $file, string $prefix): ?string
|
||||
{
|
||||
$relativeDir = '/uploads/space-profiles/' . $this->contentContainer->contentcontainer_id;
|
||||
$absoluteDir = Yii::getAlias('@webroot') . $relativeDir;
|
||||
FileHelper::createDirectory($absoluteDir);
|
||||
|
||||
$random = Yii::$app->security->generateRandomString(8);
|
||||
$fileName = $prefix . '-' . time() . '-' . $random . '.' . strtolower((string)$file->extension);
|
||||
$absolutePath = $absoluteDir . '/' . $fileName;
|
||||
|
||||
if (!$file->saveAs($absolutePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $relativeDir . '/' . $fileName;
|
||||
}
|
||||
|
||||
private function deleteStoredFile(?string $relativePath): void
|
||||
{
|
||||
if (empty($relativePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$absolutePath = Yii::getAlias('@webroot') . $relativePath;
|
||||
if (is_file($absolutePath)) {
|
||||
@unlink($absolutePath);
|
||||
}
|
||||
}
|
||||
|
||||
private function buildBaseSlug(): string
|
||||
{
|
||||
$source = $this->getSpaceName();
|
||||
|
||||
$normalized = trim((string)$source);
|
||||
$ascii = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $normalized);
|
||||
if ($ascii !== false) {
|
||||
$normalized = $ascii;
|
||||
}
|
||||
|
||||
$slug = strtolower($normalized);
|
||||
$slug = preg_replace('/[^a-z0-9]+/', '-', $slug) ?? '';
|
||||
$slug = trim($slug, '-');
|
||||
|
||||
return $slug !== '' ? $slug : 'rescue';
|
||||
}
|
||||
|
||||
private function generateUniqueSlug(): string
|
||||
{
|
||||
$base = $this->buildBaseSlug();
|
||||
$candidate = $base;
|
||||
$suffix = 1;
|
||||
|
||||
while ($this->slugExists($candidate)) {
|
||||
$candidate = $base . '-' . $suffix;
|
||||
$suffix++;
|
||||
}
|
||||
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
private function slugExists(string $slug): bool
|
||||
{
|
||||
$query = SpaceProfile::find()->where(['slug' => $slug]);
|
||||
|
||||
if ($this->profile && !$this->profile->isNewRecord) {
|
||||
$query->andWhere(['!=', 'id', (int)$this->profile->id]);
|
||||
}
|
||||
|
||||
return $query->exists();
|
||||
}
|
||||
|
||||
private function setDefaultHomePage(): void
|
||||
{
|
||||
if (!$this->contentContainer instanceof Space) {
|
||||
return;
|
||||
}
|
||||
|
||||
$defaultUrl = $this->contentContainer->createUrl('/space_profiles/profile/view');
|
||||
$settings = $this->contentContainer->getSettings();
|
||||
$settings->set('indexUrl', $defaultUrl);
|
||||
$settings->set('indexGuestUrl', $defaultUrl);
|
||||
}
|
||||
|
||||
private function getSpaceName(): string
|
||||
{
|
||||
if ($this->contentContainer instanceof Space) {
|
||||
return trim((string)$this->contentContainer->name);
|
||||
}
|
||||
|
||||
return trim($this->rescue_name);
|
||||
}
|
||||
|
||||
private function getSpaceDescription(): string
|
||||
{
|
||||
if ($this->contentContainer instanceof Space) {
|
||||
$about = trim((string)$this->contentContainer->about);
|
||||
if ($about !== '') {
|
||||
return $about;
|
||||
}
|
||||
|
||||
return trim((string)$this->contentContainer->description);
|
||||
}
|
||||
|
||||
return trim($this->description);
|
||||
}
|
||||
|
||||
private function resolvePersistedDescription(): string
|
||||
{
|
||||
$description = $this->getSpaceDescription();
|
||||
if ($description !== '') {
|
||||
return $description;
|
||||
}
|
||||
|
||||
$mission = trim($this->mission_statement);
|
||||
if ($mission !== '') {
|
||||
return $mission;
|
||||
}
|
||||
|
||||
$animals = trim($this->animals_we_accept);
|
||||
if ($animals !== '') {
|
||||
return $animals;
|
||||
}
|
||||
|
||||
return $this->getSpaceName();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user