Skip to content

Commit 55f21c5

Browse files
committed
add image field
1 parent d35747a commit 55f21c5

17 files changed

Lines changed: 628 additions & 30 deletions

Config/TheliaMain.sql

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,28 @@ CREATE TABLE `custom_field_value`
8080
ON DELETE CASCADE
8181
) ENGINE=InnoDB;
8282

83+
-- ---------------------------------------------------------------------
84+
-- custom_field_image
85+
-- ---------------------------------------------------------------------
86+
87+
DROP TABLE IF EXISTS `custom_field_image`;
88+
89+
CREATE TABLE `custom_field_image`
90+
(
91+
`id` INTEGER NOT NULL AUTO_INCREMENT,
92+
`custom_field_value_id` INTEGER,
93+
`file` VARCHAR(255) NOT NULL,
94+
`created_at` TIMESTAMP NULL,
95+
`updated_at` TIMESTAMP NULL,
96+
PRIMARY KEY (`id`),
97+
INDEX `custom_field_image_fi_7441d9` (`custom_field_value_id`),
98+
CONSTRAINT `custom_field_image_fk_7441d9`
99+
FOREIGN KEY (`custom_field_value_id`)
100+
REFERENCES `custom_field_value` (`id`)
101+
ON UPDATE RESTRICT
102+
ON DELETE CASCADE
103+
) ENGINE=InnoDB;
104+
83105
-- ---------------------------------------------------------------------
84106
-- custom_field_value_i18n
85107
-- ---------------------------------------------------------------------

Config/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<language>en_US</language>
2222
<language>fr_FR</language>
2323
</languages>
24-
<version>1.0.2</version>
24+
<version>1.0.3</version>
2525
<authors>
2626
<author>
2727
<name>Openstudio</name>

Config/schema.xml

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<database defaultIdMethod="native" name="TheliaMain"
2+
<database defaultIdMethod="native" name="TheliaMain" namespace="CustomFields\Model"
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:noNamespaceSchemaLocation="../../../vendor/thelia/propel/resources/xsd/database.xsd" >
55
<!--
66
See propel documentation on http://propelorm.org for all information about schema file
77
8-
<table name="product_rel" namespace="CustomFields\Model">
8+
<table name="product_rel">
99
<column autoIncrement="true" name="id" primaryKey="true" required="true" type="INTEGER" />
1010
<column defaultValue="0" name="visible" required="true" type="TINYINT" />
1111
<column defaultValue="0" name="position" required="true" type="INTEGER" />
@@ -26,19 +26,19 @@
2626
<!-- ===================== -->
2727
<!-- custom_field_parent -->
2828
<!-- ===================== -->
29-
<table name="custom_field_parent" namespace="CustomFields\Model">
29+
<table name="custom_field_parent">
3030
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true"/>
3131
<column name="title" type="VARCHAR" size="255" required="true"/>
3232
</table>
3333

3434
<!-- ===================== -->
3535
<!-- custom_field -->
3636
<!-- ===================== -->
37-
<table name="custom_field" namespace="CustomFields\Model">
37+
<table name="custom_field">
3838
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true"/>
3939
<column name="code" type="VARCHAR" size="100" required="true"/>
4040
<column name="title" type="VARCHAR" size="255" required="true"/>
41-
<column name="type" type="ENUM" valueSet="text,textarea, wysiwyg, content, category, folder, product" required="true" default="text"/>
41+
<column name="type" type="ENUM" valueSet="text,textarea, wysiwyg, content, category, folder, product, image" required="true" default="text"/>
4242
<column name="custom_field_parent_id" type="INTEGER" required="false"/>
4343

4444
<foreign-key foreignTable="custom_field_parent" onDelete="SET NULL" onUpdate="CASCADE">
@@ -53,7 +53,7 @@
5353
<!-- ===================== -->
5454
<!-- custom_field_source -->
5555
<!-- ===================== -->
56-
<table name="custom_field_source" namespace="CustomFields\Model">
56+
<table name="custom_field_source">
5757
<column name="custom_field_id" type="INTEGER" required="true" primaryKey="true"/>
5858
<column name="source" type="VARCHAR" size="100" required="true" primaryKey="true"/>
5959
<!-- ex: content, product, ... -->
@@ -63,10 +63,11 @@
6363
</foreign-key>
6464
</table>
6565

66+
6667
<!-- ===================== -->
6768
<!-- custom_field_value -->
6869
<!-- ===================== -->
69-
<table name="custom_field_value" namespace="CustomFields\Model">
70+
<table name="custom_field_value">
7071
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true"/>
7172
<column name="custom_field_id" type="INTEGER" required="true"/>
7273
<column name="source" type="VARCHAR" size="100" required="true"/>
@@ -96,5 +97,21 @@
9697
<parameter name="i18n_columns" value="value" />
9798
</behavior>
9899
</table>
100+
101+
<!-- ===================== -->
102+
<!-- custom_field_image -->
103+
<!-- ===================== -->
104+
<table name="custom_field_image">
105+
<column autoIncrement="true" name="id" primaryKey="true" required="true" type="INTEGER" />
106+
<column name="custom_field_value_id" type="INTEGER" />
107+
108+
<column name="file" required="true" size="255" type="VARCHAR" />
109+
<behavior name="timestampable" />
110+
<foreign-key foreignTable="custom_field_value" onDelete="CASCADE" onUpdate="RESTRICT">
111+
<reference foreign="id" local="custom_field_value_id" />
112+
</foreign-key>
113+
114+
</table>
115+
99116
<external-schema filename="vendor/thelia/config/schema.xml" referenceOnly="true"/>
100117
</database>

Config/update/1.0.3.sql

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# This is a fix for InnoDB in MySQL >= 4.1.x
2+
# It "suspends judgement" for fkey relationships until are tables are set.
3+
SET FOREIGN_KEY_CHECKS = 0;
4+
5+
-- ---------------------------------------------------------------------
6+
-- custom_field_image
7+
-- ---------------------------------------------------------------------
8+
9+
DROP TABLE IF EXISTS `custom_field_image`;
10+
11+
CREATE TABLE `custom_field_image`
12+
(
13+
`id` INTEGER NOT NULL AUTO_INCREMENT,
14+
`custom_field_value_id` INTEGER,
15+
`file` VARCHAR(255) NOT NULL,
16+
`created_at` TIMESTAMP NULL,
17+
`updated_at` TIMESTAMP NULL,
18+
PRIMARY KEY (`id`),
19+
INDEX `custom_field_image_fi_7441d9` (`custom_field_value_id`),
20+
CONSTRAINT `custom_field_image_fk_7441d9`
21+
FOREIGN KEY (`custom_field_value_id`)
22+
REFERENCES `custom_field_value` (`id`)
23+
ON UPDATE RESTRICT
24+
ON DELETE CASCADE
25+
) ENGINE=InnoDB;
26+
SET FOREIGN_KEY_CHECKS = 1;

Controller/Admin/CustomFieldController.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function listCustomFields(): Response
5656

5757

5858
$generalValues = [];
59+
$generalValueIds = [];
5960
$editLanguageId = (int) $this->getRequest()->query->get('edit_language_id', $this->getSession()->getLang()->getId());
6061

6162
$locale = LangQuery::create()->findOneById($editLanguageId)->getLocale();
@@ -76,11 +77,14 @@ public function listCustomFields(): Response
7677

7778
if ($value && in_array($customField->getType(), CustomFieldValueController::CUSTOM_FIELD_SIMPLE_VALUES)) {
7879
$generalValues[$customField->getId()] = $value->getSimpleValue() ?? '';
80+
$generalValueIds[$customField->getId()] = $value->getId();
7981
} elseif ($value) {
8082
$value->setLocale($locale);
8183
$generalValues[$customField->getId()] = $value->getValue();
84+
$generalValueIds[$customField->getId()] = $value->getId();
8285
} else {
8386
$generalValues[$customField->getId()] = '';
87+
$generalValueIds[$customField->getId()] = null;
8488
}
8589
}
8690

@@ -93,6 +97,7 @@ public function listCustomFields(): Response
9397
'general_custom_fields' => $generalCustomFields,
9498
'grouped_general_fields' => $groupedGeneralFields,
9599
'general_values' => $generalValues,
100+
'general_value_ids' => $generalValueIds,
96101
'edit_language_id' => $editLanguageId,
97102
]);
98103
}

Controller/Admin/CustomFieldValueController.php

Lines changed: 124 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
namespace CustomFields\Controller\Admin;
66

77
use CustomFields\Form\CustomFieldValueForm;
8+
use CustomFields\Model\CustomFieldImage;
9+
use CustomFields\Model\CustomFieldImageQuery;
810
use CustomFields\Model\CustomFieldQuery;
911
use CustomFields\Model\CustomFieldValueQuery;
1012
use CustomFields\Model\Map\CustomFieldTableMap;
1113
use Propel\Runtime\Exception\PropelException;
14+
use Symfony\Component\HttpFoundation\File\UploadedFile;
1215
use Symfony\Component\HttpFoundation\RedirectResponse;
1316
use Symfony\Component\HttpFoundation\Response;
1417
use Symfony\Component\HttpKernel\Attribute\AsController;
@@ -59,25 +62,85 @@ public function saveCustomFieldValues(): Response
5962

6063
foreach ($customFields as $customField) {
6164
$fieldKey = 'custom_field_'.$customField->getId();
62-
$value = $this->getRequest()->request->get($fieldKey);
63-
64-
if (null !== $value) {
65-
// Find or create custom field value
66-
$customFieldValue = CustomFieldValueQuery::create()
67-
->filterByCustomFieldId($customField->getId())
68-
->filterBySource($source)
69-
->filterBySourceId($sourceId)
70-
->findOneOrCreate();
71-
72-
if (in_array($customField->getType(), self::CUSTOM_FIELD_SIMPLE_VALUES)) {
73-
$customFieldValue
74-
->setSimpleValue($value)
75-
->save();
76-
} else {
77-
$customFieldValue
78-
->setLocale($locale)
79-
->setValue($value)
80-
->save();
65+
66+
// Handle image type separately
67+
if ($customField->getType() === CustomFieldTableMap::COL_TYPE_IMAGE) {
68+
// Skip if no file field exists in the request
69+
if (!$this->getRequest()->files->has($fieldKey)) {
70+
continue;
71+
}
72+
73+
try {
74+
/** @var UploadedFile|null $uploadedFile */
75+
$uploadedFile = $this->getRequest()->files->get($fieldKey);
76+
77+
// Skip if no valid file was uploaded (empty file input)
78+
if (!$uploadedFile instanceof UploadedFile || $uploadedFile->getError() !== UPLOAD_ERR_OK) {
79+
continue;
80+
}
81+
82+
// Create upload directory if it doesn't exist
83+
$uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images' . DS . 'customField';
84+
if (!is_dir($uploadDir)) {
85+
mkdir($uploadDir, 0777, true);
86+
}
87+
88+
// Generate unique filename
89+
$fileName = uniqid() . '_' . $uploadedFile->getClientOriginalName();
90+
$uploadedFile->move($uploadDir, $fileName);
91+
92+
// Find or create custom field value first
93+
$customFieldValue = CustomFieldValueQuery::create()
94+
->filterByCustomFieldId($customField->getId())
95+
->filterBySource($source)
96+
->filterBySourceId($sourceId)
97+
->findOneOrCreate();
98+
99+
$customFieldValue->save();
100+
101+
// Check if image already exists for this custom field value
102+
$customFieldImage = CustomFieldImageQuery::create()
103+
->filterByCustomFieldValueId($customFieldValue->getId())
104+
->findOne();
105+
106+
if (!$customFieldImage) {
107+
$customFieldImage = new CustomFieldImage();
108+
$customFieldImage->setCustomFieldValueId($customFieldValue->getId());
109+
} else {
110+
// Delete old file if exists
111+
$oldFile = $uploadDir . DS . $customFieldImage->getFile();
112+
if (file_exists($oldFile)) {
113+
unlink($oldFile);
114+
}
115+
}
116+
117+
$customFieldImage->setFile($fileName);
118+
$customFieldImage->save();
119+
} catch (\Exception $e) {
120+
// Skip this field if there's an error with the file
121+
continue;
122+
}
123+
} else {
124+
$value = $this->getRequest()->request->get($fieldKey);
125+
126+
if (null !== $value) {
127+
// Find or create custom field value
128+
$customFieldValue = CustomFieldValueQuery::create()
129+
->filterByCustomFieldId($customField->getId())
130+
->filterBySource($source)
131+
->filterBySourceId($sourceId)
132+
->findOneOrCreate();
133+
134+
if (in_array($customField->getType(), self::CUSTOM_FIELD_SIMPLE_VALUES)) {
135+
$customFieldValue
136+
->setSimpleValue($value)
137+
->save();
138+
} else {
139+
$customFieldValue
140+
->setLocale($locale)
141+
->setValue($value)
142+
->save();
143+
}
81144
}
82145
}
83146
}
@@ -137,4 +200,46 @@ public function saveCustomFieldValues(): Response
137200
])
138201
);
139202
}
203+
204+
#[Route(path: '/image/delete/{id}', name: 'image_delete', methods: ['POST', 'GET'])]
205+
public function deleteCustomFieldImage(int $id): Response
206+
{
207+
if (null !== $response = $this->checkAuth(AdminResources::MODULE, 'CustomFields', AccessManager::DELETE)) {
208+
return $response;
209+
}
210+
211+
$customFieldImage = CustomFieldImageQuery::create()->findPk($id);
212+
213+
if (!$customFieldImage) {
214+
return new RedirectResponse(
215+
URL::getInstance()->absoluteUrl($this->getRequest()->headers->get('referer', '/admin/module/customfields/list'), [
216+
'error' => Translator::getInstance()->trans('Image not found', [], 'customfields'),
217+
])
218+
);
219+
}
220+
221+
try {
222+
// Delete physical file
223+
$uploadDir = $customFieldImage->getUploadDir();
224+
$file = $uploadDir . DS . $customFieldImage->getFile();
225+
if (file_exists($file)) {
226+
unlink($file);
227+
}
228+
229+
// Delete database entry
230+
$customFieldImage->delete();
231+
232+
return new RedirectResponse(
233+
URL::getInstance()->absoluteUrl($this->getRequest()->headers->get('referer', '/admin/module/customfields/list'), [
234+
'success' => Translator::getInstance()->trans('Image deleted successfully', [], 'customfields'),
235+
])
236+
);
237+
} catch (PropelException $e) {
238+
return new RedirectResponse(
239+
URL::getInstance()->absoluteUrl($this->getRequest()->headers->get('referer', '/admin/module/customfields/list'), [
240+
'error' => Translator::getInstance()->trans('An error occurred while deleting the image', [], 'customfields'),
241+
])
242+
);
243+
}
244+
}
140245
}

Form/CustomFieldForm.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ protected function buildForm(): void
7777
Translator::getInstance()->trans('Category', [], 'customfields') => CustomFieldTableMap::COL_TYPE_CATEGORY,
7878
Translator::getInstance()->trans('Folder', [], 'customfields') => CustomFieldTableMap::COL_TYPE_FOLDER,
7979
Translator::getInstance()->trans('Product', [], 'customfields') => CustomFieldTableMap::COL_TYPE_PRODUCT,
80+
Translator::getInstance()->trans('Image', [], 'customfields') => CustomFieldTableMap::COL_TYPE_IMAGE,
8081
],
8182
'label' => Translator::getInstance()->trans('Type', [], 'customfields'),
8283
'label_attr' => ['for' => 'custom_field_type'],

0 commit comments

Comments
 (0)