Browse code

Initial commit: Frontend module member avatar added

oveleon authored on08/03/2019 16:40:16
Showing14 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,44 @@
1
+{
2
+  "name":"oveleon/contao-member-extension-bundle",
3
+  "type":"contao-bundle",
4
+  "description":"Member feature extension for Contao.",
5
+  "keywords":["contao","member-extension-bundle"],
6
+  "homepage":"https://oveleon.de/",
7
+  "license":"MIT",
8
+  "authors":[
9
+    {
10
+      "name":"Oveleon",
11
+      "homepage":"https://oveleon.de/",
12
+      "role":"Developer"
13
+    }
14
+  ],
15
+  "require":{
16
+    "php":">=7.1",
17
+    "contao/core-bundle":"^4.4"
18
+  },
19
+  "require-dev": {
20
+    "contao/manager-plugin": "^2.0"
21
+  },
22
+  "conflict": {
23
+    "contao/core": "*",
24
+    "contao/core-bundle": "4.4.1",
25
+    "contao/manager-plugin": "<2.0 || >=3.0"
26
+  },
27
+  "autoload":{
28
+    "psr-4": {
29
+      "Oveleon\\ContaoMemberExtensionBundle\\": "src/"
30
+    },
31
+    "classmap": [
32
+      "src/Resources/contao/"
33
+    ],
34
+    "exclude-from-classmap": [
35
+      "src/Resources/contao/config/",
36
+      "src/Resources/contao/dca/",
37
+      "src/Resources/contao/languages/",
38
+      "src/Resources/contao/templates/"
39
+    ]
40
+  },
41
+  "extra":{
42
+    "contao-manager-plugin": "Oveleon\\ContaoMemberExtensionBundle\\ContaoManager\\Plugin"
43
+  }
44
+}
0 45
\ No newline at end of file
1 46
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of Oveleon ContaoMemberExtension Bundle.
7
+ *
8
+ * (c) https://www.oveleon.de/
9
+ */
10
+
11
+namespace Oveleon\ContaoMemberExtensionBundle\ContaoManager;
12
+
13
+use Contao\CoreBundle\ContaoCoreBundle;
14
+use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
15
+use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
16
+use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
17
+use Oveleon\ContaoMemberExtensionBundle\ContaoMemberExtensionBundle;
18
+use Symfony\Component\HttpKernel\KernelInterface;
19
+
20
+class Plugin implements BundlePluginInterface
21
+{
22
+    /**
23
+     * {@inheritdoc}
24
+     */
25
+    public function getBundles(ParserInterface $parser): array
26
+    {
27
+        return [
28
+            BundleConfig::create(ContaoMemberExtensionBundle::class)
29
+                ->setLoadAfter([ContaoCoreBundle::class])
30
+                ->setReplace(['contao-member-extension-bundle']),
31
+        ];
32
+    }
33
+}
0 34
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of Oveleon ContaoMemberExtension Bundle.
7
+ *
8
+ * (c) https://www.oveleon.de/
9
+ */
10
+
11
+namespace Oveleon\ContaoMemberExtensionBundle;
12
+
13
+use Symfony\Component\HttpKernel\Bundle\Bundle;
14
+
15
+class ContaoMemberExtensionBundle extends Bundle
16
+{
17
+}
0 18
\ No newline at end of file
1 19
new file mode 100644
... ...
@@ -0,0 +1,202 @@
1
+<?php
2
+
3
+/*
4
+ * This file is part of Contao.
5
+ *
6
+ * (c) Leo Feyer
7
+ *
8
+ * @license LGPL-3.0-or-later
9
+ */
10
+
11
+namespace Oveleon\ContaoMemberExtensionBundle;
12
+
13
+/**
14
+ * Class Member
15
+ *
16
+ * @author Fabian Ekert <fabian@oveleon.de>
17
+ */
18
+class Member extends \Frontend
19
+{
20
+    /**
21
+     * Update avatar of member
22
+     *
23
+     * @param \FrontendUser $objUser
24
+     * @param array         $arrData
25
+     */
26
+    public function updateAvatar($objUser, $arrData)
27
+    {
28
+        $objMember = \MemberModel::findByPk($objUser->id);
29
+
30
+        if ($objMember === null)
31
+        {
32
+            return;
33
+        }
34
+
35
+        $file = $_SESSION['FILES']['avatar'];
36
+        $maxlength_kb = $this->getMaximumUploadSize();
37
+
38
+        // Sanitize the filename
39
+        try
40
+        {
41
+            $file['name'] = \StringUtil::sanitizeFileName($file['name']);
42
+        }
43
+        catch (\InvalidArgumentException $e)
44
+        {
45
+            // ToDo: Fehler: Dateiname beinhaltet unzulässige Zeichen
46
+
47
+            return;
48
+        }
49
+
50
+        // Invalid file name
51
+        if (!\Validator::isValidFileName($file['name']))
52
+        {
53
+            // ToDo: Fehler: Dateiname beinhaltet unzulässige Zeichen
54
+
55
+            return;
56
+        }
57
+
58
+        // File was not uploaded
59
+        // ToDo
60
+
61
+        // File is too big
62
+        if ($file['size'] > $maxlength_kb)
63
+        {
64
+            // ToDo: Fehler: Datei zu groß
65
+            unset($_SESSION['FILES']['avatar']);
66
+
67
+            return;
68
+        }
69
+
70
+        $objFile = new \File($file['name']);
71
+        $uploadTypes = \StringUtil::trimsplit(',', \Config::get('validImageTypes'));
72
+
73
+        // File type is not allowed
74
+        if (!\in_array($objFile->extension, $uploadTypes))
75
+        {
76
+            // ToDo: Fehler: Dateityp nicht erlaubt
77
+            unset($_SESSION['FILES']['avatar']);
78
+
79
+            return;
80
+        }
81
+
82
+        if ($arrImageSize = @getimagesize($file['tmp_name']))
83
+        {
84
+            $intImageWidth = \Config::get('imageWidth');
85
+
86
+            // Image exceeds maximum image width
87
+            if ($intImageWidth > 0 && $arrImageSize[0] > $intImageWidth)
88
+            {
89
+                // ToDo: Fehler: Bild ist zu groß in der breite
90
+                unset($_SESSION['FILES']['avatar']);
91
+
92
+                return;
93
+            }
94
+
95
+            $intImageHeight = \Config::get('imageHeight');
96
+
97
+            // Image exceeds maximum image height
98
+            if ($intImageHeight > 0 && $arrImageSize[1] > $intImageHeight)
99
+            {
100
+                // ToDo: Fehler: Bild ist zu groß in der höhe
101
+                unset($_SESSION['FILES']['avatar']);
102
+
103
+                return;
104
+            }
105
+
106
+            $_SESSION['FILES']['avatar'] = $_SESSION['FILES']['avatar'];
107
+
108
+            // Overwrite the upload folder with user's home directory
109
+            if ($objMember->assignDir && $objMember->homeDir)
110
+            {
111
+                $intUploadFolder = $objMember->homeDir;
112
+            }
113
+
114
+            $objUploadFolder = \FilesModel::findByUuid($intUploadFolder);
115
+
116
+            // The upload folder could not be found
117
+            if ($objUploadFolder === null)
118
+            {
119
+                throw new \Exception("Invalid upload folder ID $intUploadFolder");
120
+            }
121
+
122
+            $strUploadFolder = $objUploadFolder->path;
123
+
124
+            // Store the file if the upload folder exists
125
+            if ($strUploadFolder != '' && is_dir(TL_ROOT . '/' . $strUploadFolder))
126
+            {
127
+                $this->import('Files');
128
+
129
+                // Move the file to its destination
130
+                $this->Files->move_uploaded_file($file['tmp_name'], $strUploadFolder . '/' . $file['name']);
131
+                $this->Files->chmod($strUploadFolder . '/' . $file['name'], \Config::get('defaultFileChmod'));
132
+
133
+                $strUuid = null;
134
+                $strFile = $strUploadFolder . '/' . $file['name'];
135
+
136
+                // Generate the DB entries
137
+                if (\Dbafs::shouldBeSynchronized($strFile))
138
+                {
139
+                    $objModel = \FilesModel::findByPath($strFile);
140
+
141
+                    if ($objModel === null)
142
+                    {
143
+                        $objModel = \Dbafs::addResource($strFile);
144
+                    }
145
+
146
+                    $strUuid = \StringUtil::binToUuid($objModel->uuid);
147
+
148
+                    // Update the hash of the target folder
149
+                    \Dbafs::updateFolderHashes($strUploadFolder);
150
+
151
+                    // Update member avatar
152
+                    $objMember->avatar = $objModel->uuid;
153
+                    $objMember->save();
154
+                }
155
+
156
+                // Add the session entry (see #6986)
157
+                $_SESSION['FILES']['avatar'] = array
158
+                (
159
+                    'name'     => $file['name'],
160
+                    'type'     => $file['type'],
161
+                    'tmp_name' => TL_ROOT . '/' . $strFile,
162
+                    'error'    => $file['error'],
163
+                    'size'     => $file['size'],
164
+                    'uploaded' => true,
165
+                    'uuid'     => $strUuid
166
+                );
167
+
168
+                // Add a log entry
169
+                $this->log('File "' . $strUploadFolder . '/' . $file['name'] . '" has been uploaded', __METHOD__, TL_FILES);
170
+            }
171
+        }
172
+
173
+        unset($_SESSION['FILES']['avatar']);
174
+    }
175
+
176
+    /**
177
+     * Return the maximum upload file size in bytes
178
+     *
179
+     * @return string
180
+     */
181
+    protected function getMaximumUploadSize()
182
+    {
183
+        // Get the upload_max_filesize from the php.ini
184
+        $upload_max_filesize = ini_get('upload_max_filesize');
185
+
186
+        // Convert the value to bytes
187
+        if (stripos($upload_max_filesize, 'K') !== false)
188
+        {
189
+            $upload_max_filesize = round($upload_max_filesize * 1024);
190
+        }
191
+        elseif (stripos($upload_max_filesize, 'M') !== false)
192
+        {
193
+            $upload_max_filesize = round($upload_max_filesize * 1024 * 1024);
194
+        }
195
+        elseif (stripos($upload_max_filesize, 'G') !== false)
196
+        {
197
+            $upload_max_filesize = round($upload_max_filesize * 1024 * 1024 * 1024);
198
+        }
199
+
200
+        return min($upload_max_filesize, \Config::get('maxFileSize'));
201
+    }
202
+}
0 203
\ No newline at end of file
1 204
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+<?php
2
+
3
+/*
4
+ * This file is part of Oveleon ContaoOnofficeShopTv Bundle.
5
+ *
6
+ * (c) https://www.oveleon.de/
7
+ */
8
+
9
+// Back end modules
10
+$GLOBALS['BE_MOD']['system']['member_settings'] = array
11
+(
12
+    'tables'            => array('tl_member_settings'),
13
+    'hideInNavigation'  => true,
14
+);
15
+
16
+// Front end modules
17
+array_insert($GLOBALS['FE_MOD']['user'], -1, array
18
+(
19
+    'avatar' => '\\Oveleon\\ContaoMemberExtensionBundle\\ModuleAvatar'
20
+));
21
+
22
+// Register hooks
23
+$GLOBALS['TL_HOOKS']['updatePersonalData'][] = array('\\Oveleon\\ContaoMemberExtensionBundle\\Member', 'updateAvatar');
0 24
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+<?php
2
+
3
+/*
4
+ * This file is part of Oveleon ContaoMemberExtension Bundle.
5
+ *
6
+ * (c) https://www.oveleon.de/
7
+ */
8
+
9
+// Extend the default palette
10
+Contao\CoreBundle\DataContainer\PaletteManipulator::create()
11
+    ->addField(array('avatar'), 'personal_legend', Contao\CoreBundle\DataContainer\PaletteManipulator::POSITION_APPEND)
12
+    ->applyToPalette('default', 'tl_member')
13
+;
14
+
15
+// Add global operations
16
+array_insert($GLOBALS['TL_DCA']['tl_member']['list']['global_operations'], 0, array
17
+(
18
+    'settings' => array
19
+    (
20
+        'label'               => &$GLOBALS['TL_LANG']['tl_member']['settings'],
21
+        'href'                => 'do=member_settings',
22
+        'icon'                => 'edit.svg',
23
+        'attributes'          => 'onclick="Backend.getScrollOffset()" accesskey="e"'
24
+    )
25
+));
26
+
27
+// Add fields to tl_user
28
+$GLOBALS['TL_DCA']['tl_member']['fields']['avatar'] = array
29
+(
30
+    'label'                   => &$GLOBALS['TL_LANG']['tl_member']['avatar'],
31
+    'exclude'                 => true,
32
+    'inputType'               => 'fileTree',
33
+    'eval'                    => array('feEditable'=>true, 'feViewable'=>true, 'feGroup'=>'personal', 'fieldType'=>'radio', 'filesOnly'=>true, 'isGallery'=>true, 'extensions'=>Config::get('validImageTypes'), 'tl_class'=>'clr'),
34
+    'sql'                     => "binary(16) NULL"
35
+);
0 36
\ No newline at end of file
1 37
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+<?php
2
+
3
+/*
4
+ * This file is part of Oveleon ContaoMemberExtension Bundle.
5
+ *
6
+ * (c) https://www.oveleon.de/
7
+ */
8
+
9
+$GLOBALS['TL_DCA']['tl_member_settings'] = array
10
+(
11
+
12
+	// Config
13
+	'config' => array
14
+	(
15
+		'dataContainer'               => 'File',
16
+		'closed'                      => true
17
+	),
18
+
19
+	// Palettes
20
+	'palettes' => array
21
+	(
22
+		'default'                     => '{avatar_legend},defaultAvatar;'
23
+	),
24
+
25
+	// Fields
26
+	'fields' => array
27
+	(
28
+		'defaultAvatar' => array
29
+		(
30
+            'label'                   => &$GLOBALS['TL_LANG']['tl_member_settings']['defaultAvatar'],
31
+            'inputType'               => 'fileTree',
32
+            'eval'                    => array('fieldType'=>'radio', 'filesOnly'=>true, 'isGallery'=>true, 'extensions'=>Config::get('validImageTypes'), 'tl_class'=>'clr')
33
+		)
34
+	)
35
+);
0 36
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+<?php
2
+
3
+/*
4
+ * This file is part of Oveleon ContaoOnofficeShopTv Bundle.
5
+ *
6
+ * (c) https://www.oveleon.de/
7
+ */
8
+
9
+array_insert($GLOBALS['TL_DCA']['tl_module']['palettes'], 0, array
10
+(
11
+    'avatar' => '{title_legend},name,headline,type;{source_legend},imgSize;{template_legend:hide},memberTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'
12
+));
0 13
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+<?xml version="1.0" ?><xliff version="1.1">
2
+  <file datatype="php" original="src/Resources/contao/languages/en/modules.php" source-language="en" target-language="de">
3
+    <body>
4
+      <trans-unit id="FMD.avatar.0">
5
+        <source>Avatar</source>
6
+        <target>Avatar</target>
7
+      </trans-unit>
8
+      <trans-unit id="FMD.avatar.1">
9
+        <source>Displays the avatar of the member.</source>
10
+        <target>Zeigt den Avatar des Mitgliedes an.</target>
11
+      </trans-unit>
12
+    </body>
13
+  </file>
14
+</xliff>
0 15
\ No newline at end of file
1 16
new file mode 100644
... ...
@@ -0,0 +1,22 @@
1
+<?xml version="1.0" ?><xliff version="1.1">
2
+  <file datatype="php" original="src/Resources/contao/languages/en/tl_member.php" source-language="en" target-language="de">
3
+    <body>
4
+      <trans-unit id="tl_member.avatar.0">
5
+        <source>Avatar</source>
6
+        <target>Avatar</target>
7
+      </trans-unit>
8
+      <trans-unit id="tl_member.avatar.1">
9
+        <source>Here you can choose an avatar for the member.</source>
10
+        <target>Hier können Sie einen Avatar für das Mitglied auswählen.</target>
11
+      </trans-unit>
12
+      <trans-unit id="tl_member.settings.0">
13
+        <source>Settings</source>
14
+        <target>Einstellungen</target>
15
+      </trans-unit>
16
+      <trans-unit id="tl_member.settings.1">
17
+        <source>Member settings</source>
18
+        <target>Mitglieder-Einstellungen</target>
19
+      </trans-unit>
20
+    </body>
21
+  </file>
22
+</xliff>
0 23
\ No newline at end of file
1 24
new file mode 100644
... ...
@@ -0,0 +1,18 @@
1
+<?xml version="1.0" ?><xliff version="1.1">
2
+  <file datatype="php" original="src/Resources/contao/languages/en/tl_member.php" source-language="en" target-language="de">
3
+    <body>
4
+      <trans-unit id="tl_member_settings.defaultAvatar.0">
5
+        <source>Default avatar</source>
6
+        <target>Standard-Avatar</target>
7
+      </trans-unit>
8
+      <trans-unit id="tl_member_settings.defaultAvatar.1">
9
+        <source>The default avatar is displayed for members who have not set their own avatar.</source>
10
+        <target>Der Standard-Avatar wird bei Mitgliedern angezeigt, die keinen eigene Avatar gesetzt haben.</target>
11
+      </trans-unit>#
12
+      <trans-unit id="tl_member_settings.avatar_legend">
13
+        <source>Avatar</source>
14
+        <target>Avatar</target>
15
+      </trans-unit>
16
+    </body>
17
+  </file>
18
+</xliff>
0 19
\ No newline at end of file
1 20
new file mode 100644
... ...
@@ -0,0 +1,107 @@
1
+<?php
2
+
3
+/*
4
+ * This file is part of Contao.
5
+ *
6
+ * (c) Leo Feyer
7
+ *
8
+ * @license LGPL-3.0-or-later
9
+ */
10
+
11
+namespace Oveleon\ContaoMemberExtensionBundle;
12
+
13
+use Patchwork\Utf8;
14
+
15
+/**
16
+ * Class ModuleAvatar
17
+ *
18
+ * @author Fabian Ekert <fabian@oveleon.de>
19
+ */
20
+class ModuleAvatar extends \Module
21
+{
22
+
23
+	/**
24
+	 * Template
25
+	 * @var string
26
+	 */
27
+	protected $strTemplate = 'member_avatar';
28
+
29
+	/**
30
+	 * Return a wildcard in the back end
31
+	 *
32
+	 * @return string
33
+	 */
34
+	public function generate()
35
+	{
36
+		if (TL_MODE == 'BE')
37
+		{
38
+			/** @var BackendTemplate|object $objTemplate */
39
+			$objTemplate = new \BackendTemplate('be_wildcard');
40
+
41
+			$objTemplate->wildcard = '### ' . Utf8::strtoupper($GLOBALS['TL_LANG']['FMD']['avatar'][0]) . ' ###';
42
+			$objTemplate->title = $this->headline;
43
+			$objTemplate->id = $this->id;
44
+			$objTemplate->link = $this->name;
45
+			$objTemplate->href = 'contao/main.php?do=themes&amp;table=tl_module&amp;act=edit&amp;id=' . $this->id;
46
+
47
+			return $objTemplate->parse();
48
+		}
49
+
50
+		// Return if user is not logged in
51
+		if (!FE_USER_LOGGED_IN)
52
+		{
53
+			return '';
54
+		}
55
+
56
+		if ($this->memberTpl != '')
57
+		{
58
+			$this->strTemplate = $this->memberTpl;
59
+		}
60
+
61
+		return parent::generate();
62
+	}
63
+
64
+	/**
65
+	 * Generate the module
66
+	 */
67
+	protected function compile()
68
+	{
69
+        $this->size = $this->imgSize;
70
+
71
+        $this->import('FrontendUser', 'User');
72
+
73
+        if ($this->User->avatar == '' && \Config::get('defaultAvatar') == '')
74
+        {
75
+            return '';
76
+        }
77
+
78
+        if ($this->User->avatar == '')
79
+        {
80
+            $objFile = \FilesModel::findByUuid(\Config::get('defaultAvatar'));
81
+
82
+            if ($objFile === null || !is_file(TL_ROOT . '/' . $objFile->path))
83
+            {
84
+                return '';
85
+            }
86
+
87
+            $this->singleSRC = $objFile->path;
88
+
89
+            $this->addImageToTemplate($this->Template, $this->arrData);
90
+            return;
91
+        }
92
+
93
+        $objFile = \FilesModel::findByUuid($this->User->avatar);
94
+
95
+        if ($objFile === null || !is_file(TL_ROOT . '/' . $objFile->path))
96
+        {
97
+            $this->singleSRC = \FilesModel::findByUuid(\Config::get('defaultAvatar'))->path;
98
+
99
+            $this->addImageToTemplate($this->Template, $this->arrData);
100
+            return;
101
+        }
102
+
103
+        $this->singleSRC = $objFile->path;
104
+
105
+        $this->addImageToTemplate($this->Template, $this->arrData, null, null, $objFile);
106
+	}
107
+}
0 108
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+<?php $this->extend('block_searchable'); ?>
2
+
3
+<?php $this->block('content'); ?>
4
+
5
+  <figure class="image_container">
6
+      <?php $this->insert('picture_default', $this->picture); ?>
7
+  </figure>
8
+
9
+<?php $this->endblock(); ?>
0 10
new file mode 100644
1 11
Binary files /dev/null and b/src/Resources/public/avatar.png differ