├── LICENSE
├── README.md
└── magento2-theme-manager.sh
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # magento2-theme-manager
2 | Interactive bash script for managing themes in Magento 2
3 |
--------------------------------------------------------------------------------
/magento2-theme-manager.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | clear
4 | CORE_PATH="app/design/frontend"
5 | REFERENCE_FILE="app/etc/config.php"
6 | REFERENCE_VIEW_XML_FILE="vendor/magento/theme-frontend-blank/etc/view.xml"
7 |
8 | # sql queries run when extending theme
9 | MYSQL_COMMAND_1='select distinct theme_id, theme_path from theme where area="frontend"'
10 | MYSQL_COMMAND_2='select theme_path from theme where theme_id='
11 |
12 | # sql queries run when deleting themes
13 | MYSQL_COMMAND_3='select count(parent_id) from theme where parent_id='
14 | MYSQL_COMMAND_4='select theme_path, theme_title, preview_image from theme where theme_id='
15 | MYSQL_COMMAND_5='delete from theme where theme_id='
16 |
17 | # the script must be run from document root folder
18 | isMagento2RootFolder () {
19 | if [ ! -f "$REFERENCE_FILE" ]; then
20 | printf "\nThe script must be run from document root!"
21 | exitScript
22 | fi
23 | }
24 |
25 | # get user input and create vendor folder
26 | promptVendorName () {
27 | printf "\nPlease specify vendor name: "
28 | read -r VENDOR_NAME
29 |
30 | VENDOR_PATH=$CORE_PATH"/"$VENDOR_NAME
31 |
32 | # if vendor folder doesn't exists, create it
33 | if [ ! -d "$VENDOR_PATH" ]; then
34 | mkdir -p "$VENDOR_PATH"
35 | printf "Created vendor folder: %s" "$VENDOR_PATH"
36 | fi
37 | }
38 |
39 | # get user input and create theme folder
40 | promptThemeName () {
41 | printf "\nPlease specify theme name: "
42 | read -r THEME_NAME
43 |
44 | THEME_PATH=$VENDOR_PATH"/"$THEME_NAME
45 |
46 | # if theme folder doesn't exists, create it
47 | if [ ! -d "$THEME_PATH" ]; then
48 | mkdir -p "$THEME_PATH"
49 | printf "Created theme folder: %s" "$THEME_PATH"
50 | fi
51 | }
52 |
53 | # process themes theme.xml file
54 | renderThemeXmlFile () {
55 | # check if argument has been passed to the function
56 | if [ ! -z "$1" ] ; then
57 | PARENT_PATH="$1"
58 | fi
59 |
60 | THEME_XML_FILE=$THEME_PATH"/theme.xml"
61 |
62 | if [ -f "$THEME_XML_FILE" ]; then
63 | printf "\nERROR: found: %s" "$THEME_XML_FILE"
64 | exitScript
65 | else
66 |
67 | # get user input for theme title that will be visible in admin area
68 | printf "\nPlease specify theme title: "
69 | read -r THEME_TITLE
70 |
71 | THEME_XML_CONTENT='
77 |
78 | '$THEME_TITLE'
79 | '$PARENT_PATH'
80 |
81 | media/preview.jpg
82 |
83 | '
84 |
85 | # output configuration to .xml file
86 | echo "$THEME_XML_CONTENT" > "$THEME_XML_FILE"
87 | printf "Created file: %s" "$THEME_XML_FILE"
88 | fi
89 | }
90 |
91 | # process themes registration.php file
92 | renderRegistrationPhpFile () {
93 | VENDOR=$VENDOR_NAME"/"$THEME_NAME
94 | REGISTRATION_PHP_FILE=$THEME_PATH"/registration.php"
95 |
96 | if [ -f "$REGISTRATION_PHP_FILE" ]; then
97 | printf "\nERROR: found: %s" "$REGISTRATION_PHP_FILE"
98 | exitScript
99 | else
100 | REGISTRATION_PHP_CONTENT=" "$REGISTRATION_PHP_FILE"
114 | printf "\nCreated file: %s" "$REGISTRATION_PHP_FILE"
115 | fi
116 | }
117 |
118 | # this function is run only when creating new theme
119 | renderEtcViewXmlFile () {
120 | ETC_PATH="$THEME_PATH/etc"
121 |
122 | # if etc folder doesn't exists, create it
123 | if [ ! -d "$ETC_PATH" ]; then
124 | mkdir "$ETC_PATH"
125 | printf "\nCreated folder: %s" "$ETC_PATH"
126 | fi
127 |
128 | VIEW_XML_FILE="$ETC_PATH/view.xml"
129 |
130 | if [ -f "$VIEW_XML_FILE" ]; then
131 | printf "\nERROR: found: %s" "$VIEW_XML_FILE"
132 | exitScript
133 | else
134 | if [ ! -f "$REFERENCE_VIEW_XML_FILE" ] ; then
135 | printf "\nFile not found: $REFERENCE_VIEW_XML_FILE"
136 | exitScript
137 | fi
138 | # always copy view.xml file from Magento/blank theme
139 | cp "$REFERENCE_VIEW_XML_FILE" "$ETC_PATH"
140 | printf "\nCopied vendor/magento/theme-frontend-blank/view.xml to %s" "$ETC_PATH"
141 | printf "\nBrowse this file and customize its configuration"
142 | fi
143 | }
144 |
145 | # each new theme must have its own preview image
146 | downloadPreviewImage () {
147 | IMAGE_LINK="http://inchoo.net/wp-content/uploads/2016/02/Inchoo-logo.jpg"
148 |
149 | MEDIA_PATH=$THEME_PATH"/media"
150 |
151 | # if media folder doesn't exists, create it
152 | if [ ! -d "$MEDIA_PATH" ]; then
153 | mkdir "$MEDIA_PATH"
154 | printf "\nCreated folder: %s" "$MEDIA_PATH"
155 | fi
156 |
157 | MEDIA_IMG=$MEDIA_PATH"/preview.jpg"
158 | if [ -f "$MEDIA_IMG" ]; then
159 | printf "\nERROR: found: %s" "$MEDIA_IMG"
160 | exitScript
161 | else
162 | # download image from specified link and save it into media folder
163 | # and rename it to preview.jpg
164 | wget -c -q $IMAGE_LINK -O "$MEDIA_PATH/preview.jpg"
165 | printf "\nDownloaded preview image to %s" "$MEDIA_PATH"
166 | fi
167 | }
168 |
169 | createInchooLessFile () {
170 | WEB_PATH=$THEME_PATH"/web"
171 | # if media folder doesn't exists, create it
172 | if [ ! -d "$WEB_PATH" ]; then
173 | mkdir "$WEB_PATH"
174 | printf "\nCreated folder: %s" "$WEB_PATH"
175 | fi
176 |
177 | WEB_CSS_PATH=$WEB_PATH"/css"
178 | if [ ! -d "$WEB_CSS_PATH" ]; then
179 | mkdir "$WEB_CSS_PATH"
180 | printf "\nCreated folder: %s" "$WEB_CSS_PATH"
181 | fi
182 |
183 | DESIGN_FILE=$WEB_CSS_PATH"/inchoo.less"
184 | if [ ! -f "$DESIGN_FILE" ]; then
185 | touch "$DESIGN_FILE"
186 | printf "\nCreated file: %s" "$DESIGN_FILE"
187 | fi
188 |
189 | DESIGN_FILE_CONTENT="@inchoo-green: #79AD36;
190 | body {
191 | background-color: @inchoo-green !important;
192 | }"
193 | echo "$DESIGN_FILE_CONTENT" > "$DESIGN_FILE"
194 | }
195 |
196 | promptLocale () {
197 | DEFAULT_LOCALE="en_US"
198 |
199 | printf "\nPlease specify themes locale setting or press Enter for default (en_US): "
200 | read -r THEME_LOCALE
201 |
202 | # if user did press Enter, update variable to default
203 | if [ -z "$THEME_LOCALE" ]; then
204 | THEME_LOCALE=$DEFAULT_LOCALE
205 | printf "Theme is using default locale: %s" "$THEME_LOCALE"
206 | else
207 | printf "Custom locale: %s" "$THEME_LOCALE"
208 | fi
209 | }
210 |
211 | updateThemeJs () {
212 | printf "\nIn your text editor, open the follwoing file:"
213 | printf "\n"
214 | printf "\ndev/tools/grunt/configs/themes.js"
215 | printf "\n"
216 | printf "\nand paste the following code just before the last closing curly bracket: "
217 | printf "\n"
218 | printf ",
219 | %s: {
220 | area: 'frontend',
221 | name: '%s',
222 | locale: '%s',
223 | files: [
224 | 'css/inchoo'
225 | ],
226 | dsl: 'less'
227 | }" "$THEME_NAME" "$VENDOR" "$THEME_LOCALE"
228 | }
229 |
230 | displayDeploymentCommands () {
231 | printf "\n"
232 | printf "\nPlease open Magento Admin Dashboard -> Content -> Themes"
233 | printf "\n"
234 | printf "\nNow, copy and paste the following commands:"
235 | printf "\n"
236 | printf "\ngrunt clean"
237 | printf "\ngrunt exec:%s" "$THEME_NAME"
238 | printf "\nphp bin/magento cache:clean"
239 | printf "\nphp bin/magento setup:static-content:deploy"
240 | printf "\n"
241 | printf "\nTheme preview image is located in folder pub/media/theme/preview"
242 | printf "\nCompiled css file is located in folder pub/static/frontend/%s/%s/css" "$THEME_PATH" "$THEME_LOCALE"
243 | }
244 |
245 | updatePermissions () {
246 | IFS='\ ' read -r OWNER_USER OWNER_GROUP <<< "$(ls -ld "$REFERENCE_FILE" | awk '{print $3, $4}')"
247 | printf "\n\nSetting permissions: (%s:%s) to %s\n" "$OWNER_USER" "$OWNER_GROUP" "$THEME_PATH"
248 | sudo chown -R "$OWNER_USER":"$OWNER_GROUP" "$THEME_PATH"
249 | }
250 |
251 | # get user input for mysql credentials
252 | promptMysqlCredentials () {
253 | printf "\nType in your mysql username: "
254 | read -r MYSQL_USERNAME
255 |
256 | printf "Type in your mysql password: "
257 | read -r -s MYSQL_PASSWORD
258 |
259 | printf "\nType in database name: "
260 | read -r MYSQL_DB_NAME
261 | }
262 |
263 | # define mysql connection
264 | mysql_conn () {
265 | mysql -N -s -u "$MYSQL_USERNAME" -p"$MYSQL_PASSWORD" -D "$MYSQL_DB_NAME" -e "$1"
266 | }
267 |
268 | # perform simple mysql connection
269 | testMysqlConnection () {
270 | mysql_conn "use $MYSQL_DB_NAME"
271 |
272 | # if error occured, the script will exit
273 | if [ ! "$?" = "0" ]; then
274 | exitScript
275 | fi
276 | }
277 |
278 | # display all available magento themes
279 | listExistingThemes () {
280 | printf "\nListing existing themes:\n"
281 |
282 | mysql_conn "$MYSQL_COMMAND_1" | while read -r line
283 | do
284 | IFS=$'\t' read -r THEME_ID THEME_PATH <<< "$line"
285 | echo "[$THEME_ID, $THEME_PATH]"
286 | done
287 |
288 | printf "\nPlease, select one of the numbers: "
289 | read -r SELECTED_INPUT_THEME_ID
290 |
291 | PARENT_VENDOR=$(mysql_conn "$MYSQL_COMMAND_2$SELECTED_INPUT_THEME_ID")
292 | }
293 |
294 | promptAndDeleteTheme () {
295 | # parse sql results
296 | read -r HOW_MANY_CHILD_THEMES <<< "$(mysql_conn "$MYSQL_COMMAND_3$SELECTED_INPUT_THEME_ID")";
297 |
298 | if [ "$HOW_MANY_CHILD_THEMES" -eq 0 ] ; then
299 | # theme exists in database
300 |
301 | # parse results
302 | read -r THEME_PATH THEME_TITLE THEME_IMAGE<<< "$(mysql_conn "$MYSQL_COMMAND_4$SELECTED_INPUT_THEME_ID")";
303 |
304 | if [ -n "$THEME_TITLE" ] ; then
305 | # theme is not parent theme, it is safe to remove it
306 |
307 | # remove theme folder and its files
308 | printf "\nDeleting theme files in: %s/%s" "$CORE_PATH" "$THEME_PATH"
309 | rm -rf "$CORE_PATH"/"$THEME_PATH"
310 |
311 | if [ ! -z $THEME_IMAGE ] ; then
312 | printf "\nDeleting theme preview image in pub/media/theme/preview/%s" "$THEME_IMAGE"
313 | PUB_THEME_IMAGE="pub/media/theme/preview/$THEME_IMAGE"
314 | rm "$PUB_THEME_IMAGE"
315 | fi
316 |
317 | # remove theme entry in database
318 | printf "\nDeleting database entry in table 'theme'"
319 | mysql_conn "$MYSQL_COMMAND_5$SELECTED_INPUT_THEME_ID"
320 |
321 | # notify user to delete content in grunts theme.js file
322 | IFS='/' read -a DB_THEME_PATH <<< "$THEME_PATH"
323 | printf "\n\nIn your text editor, open the following file:"
324 | printf "\ndev/tools/grunt/configs/themes.js"
325 | printf "\nand delete content that is related to key '%s'" "${DB_THEME_PATH[1]}"
326 |
327 | printf "\n\nDone"
328 | else
329 | # row entry in database table does not exist
330 | printf "\nERROR - theme with [theme_id, %s] is not found in database!" "$SELECTED_INPUT_THEME_ID"
331 | exitScript
332 | fi
333 | else
334 | # theme is parent theme, do nothing
335 | echo "Cannot delete $PARENT_VENDOR, theme is parent to total of $HOW_MANY_CHILD_THEMES theme(s)!"
336 | exitScript
337 | fi
338 | }
339 |
340 | createNewTheme () {
341 | promptVendorName
342 | promptThemeName
343 | renderThemeXmlFile
344 | promptLocale
345 | renderRegistrationPhpFile
346 | renderEtcViewXmlFile
347 | downloadPreviewImage
348 | createInchooLessFile
349 | updatePermissions
350 | updateThemeJs
351 | displayDeploymentCommands
352 | }
353 |
354 | extendExistingTheme () {
355 | promptMysqlCredentials
356 | testMysqlConnection
357 | listExistingThemes
358 | promptVendorName
359 | promptThemeName
360 | renderThemeXmlFile "$PARENT_VENDOR"
361 | promptLocale
362 | renderRegistrationPhpFile
363 | downloadPreviewImage
364 | createInchooLessFile
365 | updatePermissions
366 | updateThemeJs
367 | displayDeploymentCommands
368 | }
369 |
370 | deleteTheme () {
371 | promptMysqlCredentials
372 | testMysqlConnection
373 | listExistingThemes
374 | promptAndDeleteTheme
375 | }
376 |
377 | exitScript () {
378 | echo " "
379 | echo "The script is going to exit"
380 | exit
381 | }
382 |
383 | # this is where script output starts
384 | printf "*********** Magento2 Theme Manager ***********"
385 |
386 | isMagento2RootFolder
387 |
388 | printf "\nWould you like to:"
389 | printf "\n1) create a new theme"
390 | printf "\n2) create a child theme"
391 | printf "\n3) delete a theme"
392 | printf "\nPlease, enter your option: "
393 | read -r THEME_OPTION
394 |
395 | # : '
396 | case "$THEME_OPTION" in
397 | 1 ) createNewTheme ;;
398 | 2 ) extendExistingTheme ;;
399 | 3 ) deleteTheme ;;
400 | * ) printf "\nUnknown argument specified: %s" "$THEME_OPTION"
401 | exitScript ;;
402 | esac
403 | #'
404 |
405 | echo " "
406 | echo "*********** Magento2 Theme Manager has finished successfully ***********"
--------------------------------------------------------------------------------