Responsive Menu - Version 3.0.5

Version Description

(13th July 2016) = * Requires PHP 5.4 * Fixed bug with push animation * Improved PHP version check functionality * Fixed issue where custom menu classes weren't being added

Download this release

Release Info

Developer ResponsiveMenu
Plugin Icon 128x128 Responsive Menu
Version 3.0.5
Comparing to
See all releases

Code changes from version 3.0.4 to 3.0.5

readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://responsive.menu/donate
4
  Tags: responsive, menu, responsive menu, mobile menu, wordpress responsive menu, wp responsive menu, tablet menu, mobile, tablet, 3 lines, 3 line, three line, three lines
5
  Requires at least: 3.5.0
6
  Tested up to: 4.5.3
7
- Stable tag: 3.0.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -146,6 +146,12 @@ To view our whole FAQ, please go to https://responsive.menu/faq/
146
 
147
  == Changelog ==
148
 
 
 
 
 
 
 
149
  = 3.0.4 (9th July 2016) =
150
  * **Requires PHP 5.4**
151
  * Fixed bug with overwriting values with shortcode
4
  Tags: responsive, menu, responsive menu, mobile menu, wordpress responsive menu, wp responsive menu, tablet menu, mobile, tablet, 3 lines, 3 line, three line, three lines
5
  Requires at least: 3.5.0
6
  Tested up to: 4.5.3
7
+ Stable tag: 3.0.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
146
 
147
  == Changelog ==
148
 
149
+ = 3.0.5 (13th July 2016) =
150
+ * **Requires PHP 5.4**
151
+ * Fixed bug with push animation
152
+ * Improved PHP version check functionality
153
+ * Fixed issue where custom menu classes weren't being added
154
+
155
  = 3.0.4 (9th July 2016) =
156
  * **Requires PHP 5.4**
157
  * Fixed bug with overwriting values with shortcode
responsive-menu.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Responsive Menu
5
  Plugin URI: https://responsive.menu
6
  Description: Highly Customisable Responsive Menu Plugin for WordPress
7
- Version: 3.0.4
8
  Author: Responsive Menu
9
  Text Domain: responsive-menu
10
  Author URI: https://responsive.menu
@@ -12,14 +12,18 @@ License: GPL2
12
  Tags: responsive, menu, responsive menu
13
  */
14
 
15
- /* Check correct PHP version first */
16
- register_activation_hook(__FILE__, 'activate_responsive_menu');
17
- function activate_responsive_menu() {
18
- if(version_compare(PHP_VERSION, '5,4', '<')):
19
- deactivate_plugins(plugin_basename(__FILE__ ));
20
- wp_die(sprintf('Responsive Menu requires PHP 5.4 or higher. You are still on %s', PHP_VERSION));
21
- endif;
22
- }
 
 
 
 
23
 
24
  /* Required includes for plugin to function */
25
  include dirname(__FILE__) . '/autoload.php';
@@ -38,8 +42,7 @@ if(is_admin()):
38
  /*
39
  * Initial Migration and Version Check synchronisation */
40
  add_action('admin_init', function() use($container) {
41
- include dirname(__FILE__) . '/src/config/default_options.php';
42
- $migration = new ResponsiveMenu\Database\Migration($container['database'], $default_options);
43
  $migration->setup();
44
  $migration->synchronise();
45
  });
@@ -48,8 +51,8 @@ if(is_admin()):
48
  Polylang Integration Section */
49
  add_action('plugins_loaded', function() use($container) {
50
  if(function_exists('pll_register_string')):
51
- $repo = $container['option_repository'];
52
- $options = $repo->all();
53
 
54
  $menu_to_use = isset($options['menu_to_use']) ? $options['menu_to_use']->getValue() : '';
55
  $button_title = isset($options['button_title']) ? $options['button_title']->getValue() : '';
4
  Plugin Name: Responsive Menu
5
  Plugin URI: https://responsive.menu
6
  Description: Highly Customisable Responsive Menu Plugin for WordPress
7
+ Version: 3.0.5
8
  Author: Responsive Menu
9
  Text Domain: responsive-menu
10
  Author URI: https://responsive.menu
12
  Tags: responsive, menu, responsive menu
13
  */
14
 
15
+ /* Check correct PHP version first */
16
+ add_action('admin_init', 'check_responsive_menu_php_version');
17
+ function check_responsive_menu_php_version() {
18
+ if(version_compare(PHP_VERSION, '5.4', '<')):
19
+ add_action('admin_notices', 'responsive_menu_deactivation_text');
20
+ deactivate_plugins(plugin_basename(__FILE__));
21
+ endif;
22
+ }
23
+
24
+ function responsive_menu_deactivation_text() {
25
+ echo '<div class="error"><p>' . sprintf(__('Responsive Menu requires PHP 5.4 or higher to function and has therefore been automatically disabled. You are still on %s.%sPlease speak to your webhost about upgrading your PHP version. For more information please visit %s', 'responsive-menu'), PHP_VERSION, '<br /><br />', '<a target="_blank" href="https://responsive.menu/why-php-5-4/">this page</a>.') . '</p></div>';
26
+ }
27
 
28
  /* Required includes for plugin to function */
29
  include dirname(__FILE__) . '/autoload.php';
42
  /*
43
  * Initial Migration and Version Check synchronisation */
44
  add_action('admin_init', function() use($container) {
45
+ $migration = $container['migration'];
 
46
  $migration->setup();
47
  $migration->synchronise();
48
  });
51
  Polylang Integration Section */
52
  add_action('plugins_loaded', function() use($container) {
53
  if(function_exists('pll_register_string')):
54
+ $service = $container['option_service'];
55
+ $options = $service->all();
56
 
57
  $menu_to_use = isset($options['menu_to_use']) ? $options['menu_to_use']->getValue() : '';
58
  $button_title = isset($options['button_title']) ? $options['button_title']->getValue() : '';
src/app/Collections/OptionsCollection.php CHANGED
@@ -76,4 +76,8 @@ class OptionsCollection implements \ArrayAccess {
76
  unset($this->options[$offset]);
77
  }
78
 
 
 
 
 
79
  }
76
  unset($this->options[$offset]);
77
  }
78
 
79
+ public function isEmpty() {
80
+ return isset($this->options) && count($this->options) > 0 ? false : true;
81
+ }
82
+
83
  }
src/app/Controllers/Admin.php CHANGED
@@ -2,82 +2,44 @@
2
 
3
  namespace ResponsiveMenu\Controllers;
4
  use ResponsiveMenu\View\View as View;
5
- use ResponsiveMenu\Repositories\OptionRepository as OptionRepository;
6
- use ResponsiveMenu\Factories\OptionFactory as OptionFactory;
7
- use ResponsiveMenu\Factories\AdminSaveFactory as SaveFactory;
8
- use ResponsiveMenu\WPML\WPML as WPML;
9
 
10
  class Admin {
11
 
12
- public function __construct(OptionRepository $repository, View $view) {
13
- $this->repository = $repository;
14
  $this->view = $view;
15
  }
16
 
17
- public function update($default_options) {
18
-
19
- $options = array_merge($default_options, $_POST['menu']);
20
-
21
- $option_factory = new OptionFactory;
22
- foreach($options as $key => $val)
23
- $this->repository->update($option_factory->build($key, $val));
24
-
25
- $options = $this->repository->all();
26
- $save_factory = new SaveFactory();
27
- $flash['errors'] = $save_factory->build($options);
28
- $flash['success'] = __('Responsive Menu Options Updated Successfully', 'responsive-menu');
29
-
30
- $wpml = new WPML;
31
- $wpml->saveFromOptions($options);
32
-
33
- $this->view->render('main', ['options' => $options, 'flash' => $flash]);
34
-
35
  }
36
 
37
  public function reset($default_options) {
38
-
39
- $option_factory = new OptionFactory;
40
- foreach($default_options as $key => $val)
41
- $this->repository->update($option_factory->build($key, $val));
42
-
43
- $options = $this->repository->all();
44
- $save_factory = new SaveFactory();
45
- $flash['errors'] = $save_factory->build($options);
46
- $flash['success'] = __('Responsive Menu Options Reset Successfully', 'responsive-menu');
47
-
48
- $wpml = new WPML;
49
- $wpml->saveFromOptions($options);
50
-
51
- $this->view->render('main', ['options' => $options, 'flash' => $flash]);
52
-
53
  }
54
 
55
  public function index() {
56
- $this->view->render('main', ['options' => $this->repository->all()]);
57
  }
58
 
59
- public function import() {
60
-
61
- if(!empty($_FILES['responsive_menu_import_file']['tmp_name'])):
62
- $file = file_get_contents($_FILES['responsive_menu_import_file']['tmp_name']);
63
  $decoded = json_decode($file);
64
-
65
- $option_factory = new OptionFactory;
66
- foreach($decoded as $key => $val)
67
- $this->repository->update($option_factory->build($key, $val));
68
-
69
- $options = $this->repository->all();
70
- $save_factory = new SaveFactory();
71
- $flash['errors'] = $save_factory->build($options);
72
  $flash['success'] = __('Responsive Menu Options Reset Successfully', 'responsive-menu');
73
  else:
74
  $flash['errors'][] = __('No file selected', 'responsive-menu');
75
- $options = $this->repository->all();
76
  endif;
77
 
78
- $wpml = new WPML;
79
- $wpml->saveFromOptions($options);
80
-
81
  $this->view->render('main', ['options' => $options, 'flash' => $flash]);
82
  }
83
 
@@ -87,7 +49,7 @@ class Admin {
87
  header( 'Content-Disposition: attachment; filename=export.json' );
88
  header( "Expires: 0" );
89
  $final = [];
90
- foreach($this->repository->all()->all() as $option)
91
  $final[$option->getName()] = $option->getValue();
92
  echo json_encode($final);
93
  exit();
2
 
3
  namespace ResponsiveMenu\Controllers;
4
  use ResponsiveMenu\View\View as View;
5
+ use ResponsiveMenu\Services\OptionService as OptionService;
 
 
 
6
 
7
  class Admin {
8
 
9
+ public function __construct(OptionService $service, View $view) {
10
+ $this->service = $service;
11
  $this->view = $view;
12
  }
13
 
14
+ public function update($default_options, $new_options) {
15
+ $this->view->render('main', [
16
+ 'options' => $this->service->updateOptions(array_merge($default_options, array_filter($new_options))),
17
+ 'flash' => ['success' => __('Responsive Menu Options Updated Successfully', 'responsive-menu')]
18
+ ]);
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  public function reset($default_options) {
22
+ $this->view->render('main', [
23
+ 'options' => $this->service->updateOptions($default_options),
24
+ 'flash' => ['success' => __('Responsive Menu Options Reset Successfully', 'responsive-menu')]
25
+ ]);
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
 
28
  public function index() {
29
+ $this->view->render('main', ['options' => $this->service->all()]);
30
  }
31
 
32
+ public function import($default_options, $file) {
33
+ if(!empty($file['tmp_name'])):
34
+ $file = file_get_contents($file['tmp_name']);
 
35
  $decoded = json_decode($file);
36
+ $options = $this->service->updateOptions(array_merge($default_options, array_filter($decoded)));
 
 
 
 
 
 
 
37
  $flash['success'] = __('Responsive Menu Options Reset Successfully', 'responsive-menu');
38
  else:
39
  $flash['errors'][] = __('No file selected', 'responsive-menu');
40
+ $options = $this->service->all();
41
  endif;
42
 
 
 
 
43
  $this->view->render('main', ['options' => $options, 'flash' => $flash]);
44
  }
45
 
49
  header( 'Content-Disposition: attachment; filename=export.json' );
50
  header( "Expires: 0" );
51
  $final = [];
52
+ foreach($this->service->all()->all() as $option)
53
  $final[$option->getName()] = $option->getValue();
54
  echo json_encode($final);
55
  exit();
src/app/Controllers/Front.php CHANGED
@@ -2,23 +2,21 @@
2
 
3
  namespace ResponsiveMenu\Controllers;
4
  use ResponsiveMenu\View\View as View;
5
- use ResponsiveMenu\Repositories\OptionRepository as OptionRepository;
6
- use ResponsiveMenu\Controllers\Base as Base;
7
  use ResponsiveMenu\ViewModels\Menu as MenuViewModel;
8
  use ResponsiveMenu\ViewModels\Button as ButtonViewModel;
9
  use ResponsiveMenu\Factories\FrontDisplayFactory as DisplayFactory;
10
- use ResponsiveMenu\Shortcodes\ResponsiveMenuShortcode as Shortcode;
11
 
12
  class Front {
13
 
14
- public function __construct(OptionRepository $repository, View $view) {
15
- $this->repository = $repository;
16
  $this->view = $view;
17
  }
18
 
19
  public function index() {
20
  # Get Latest Options
21
- $options = $this->repository->all();
22
 
23
  # This needs refactoring - Martin Fowler HELP!
24
  $display_factory = new DisplayFactory();
2
 
3
  namespace ResponsiveMenu\Controllers;
4
  use ResponsiveMenu\View\View as View;
5
+ use ResponsiveMenu\Services\OptionService as OptionService;
 
6
  use ResponsiveMenu\ViewModels\Menu as MenuViewModel;
7
  use ResponsiveMenu\ViewModels\Button as ButtonViewModel;
8
  use ResponsiveMenu\Factories\FrontDisplayFactory as DisplayFactory;
 
9
 
10
  class Front {
11
 
12
+ public function __construct(OptionService $service, View $view) {
13
+ $this->service = $service;
14
  $this->view = $view;
15
  }
16
 
17
  public function index() {
18
  # Get Latest Options
19
+ $options = $this->service->all();
20
 
21
  # This needs refactoring - Martin Fowler HELP!
22
  $display_factory = new DisplayFactory();
src/app/Database/Migration.php CHANGED
@@ -1,49 +1,56 @@
1
  <?php
2
 
3
  namespace ResponsiveMenu\Database;
4
- use ResponsiveMenu\Options\Options as Options;
5
  use ResponsiveMenu\Database\Database as Database;
 
6
 
7
- class Migration{
8
 
9
  protected $db;
10
 
11
- protected static $version_var = 'RMVer';
12
- protected static $old_options_var = 'RMOptions';
 
 
 
13
  protected static $table = 'responsive_menu';
 
14
 
15
- public function __construct(Database $db, $default_options) {
16
- $this->db = $db;
17
- $this->defaults = $default_options;
 
 
 
 
18
  }
19
 
20
- protected function addNewOptions() {
21
- # If DB is empty we need to fill it up!
22
- $options = $this->db->all(self::$table);
23
- if(empty($options)):
24
- foreach($this->defaults as $name => $value)
25
- $this->db->insert(self::$table, array('name' => $name, 'value' => $value));
26
- # Otherwise we only add new options
27
- else:
28
- foreach($options as $converted)
29
- $current[$converted->name] = $converted->value;
30
- $final = array_diff_key($this->defaults, $current);
31
- if(is_array($final)):
32
- foreach($final as $name => $value)
33
- $this->db->insert(self::$table, array('name' => $name, 'value' => $value));
34
- endif;
35
- endif;
36
  }
37
 
38
- protected function tidyUpOptions() {
39
- $current = array_map(function($a) { return $a->name; }, $this->db->all(self::$table));
40
- foreach(array_diff($current, array_keys($this->defaults)) as $to_delete)
41
- $this->db->delete(self::$table, array('name' => $to_delete));
42
  }
43
 
 
 
 
 
 
 
 
 
 
44
  public function setup() {
45
  # Create the database table if it doesn't exist
46
- if(!$this->isVersion3($this->getOldVersion())):
47
  $sql = "CREATE TABLE " . $this->db->getPrefix() . self::$table . " (
48
  name varchar(50) NOT NULL,
49
  value varchar(5000) DEFAULT NULL,
@@ -58,12 +65,12 @@ class Migration{
58
  }
59
 
60
  public function synchronise() {
 
61
  # First Thing we need to do is migrate any old options
62
- if(!$this->isVersion3($this->getOldVersion())):
63
  $this->migrateVersion2Options();
64
- endif;
65
-
66
- if($this->needsUpdate($this->getOldVersion(), $this->getCurrentVersion())):
67
 
68
  # Now we can add any new options
69
  $this->addNewOptions();
@@ -74,27 +81,35 @@ class Migration{
74
  # And Update Version
75
  $this->updateVersion();
76
 
77
- endif;
78
- }
79
 
80
- protected function needsUpdate($current_version, $old_version) {
81
- return version_compare($current_version, $old_version, '<');
82
  }
83
 
84
- protected function getOldVersion() {
85
- return get_option(self::$version_var);
86
  }
87
 
88
  protected function updateVersion() {
89
- update_option(self::$version_var, $this->getCurrentVersion());
90
  }
91
 
92
- protected function isVersion3($version) {
93
- return substr($version, 0, 1) == 3;
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
 
96
- protected function migrateVersion2Options() {
97
- $old_options = get_option(self::$old_options_var);
98
 
99
  $new_options = [
100
  'menu_to_use' => $old_options['RM'] ? $old_options['RM'] : '',
@@ -107,7 +122,7 @@ class Migration{
107
  'button_line_colour' => $old_options['RMLineCol'] ? $old_options['RMLineCol'] : '',
108
  'button_background_colour' => $old_options['RMClickBkg'] ? $old_options['RMClickBkg'] : '',
109
  'button_title' => $old_options['RMClickTitle'] ? $old_options['RMClickTitle'] : '',
110
- 'button_transparent_background' => $old_options['RMBkgTran'] ? 'on' : 'off',
111
  'menu_font' => $old_options['RMFont'] ? $old_options['RMFont'] : '',
112
  'button_position_type' => $old_options['RMPos'] ? 'fixed' : '',
113
  'menu_title_image' => $old_options['RMImage'] ? $old_options['RMImage'] : '',
@@ -127,7 +142,7 @@ class Migration{
127
  'menu_link_hover_colour' => $old_options['RMTextColHov'] ? $old_options['RMTextColHov'] : '',
128
  'menu_sub_arrow_shape_hover_colour' => $old_options['RMTextColHov'] ? $old_options['RMTextColHov'] : '',
129
  'menu_title_hover_colour' => $old_options['RMTitleColHov'] ? $old_options['RMTitleColHov'] : '',
130
- 'animation_type' => $old_options['RMAnim'] == 'overlay' ? 'slide' : 'push',
131
  'page_wrapper' => $old_options['RMPushCSS'] ? $old_options['RMPushCSS'] : '',
132
  'menu_title_background_colour' => $old_options['RMTitleBkg'] ? $old_options['RMTitleBkg'] : '',
133
  'menu_title_background_hover_colour' => $old_options['RMTitleBkg'] ? $old_options['RMTitleBkg'] : '',
@@ -139,34 +154,34 @@ class Migration{
139
  'animation_speed' => $old_options['RMAnimSpd'] ? $old_options['RMAnimSpd'] : '',
140
  'transition_speed' => $old_options['RMTranSpd'] ? $old_options['RMTranSpd'] : '',
141
  'menu_text_alignment' => $old_options['RMTxtAlign'] ? $old_options['RMTxtAlign'] : '',
142
- 'auto_expand_all_submenus' => $old_options['RMExpand'] ? 'on' : 'off',
143
  'menu_links_height' => $old_options['RMLinkHeight'] ? $old_options['RMLinkHeight'] + 24 : '',
144
  'submenu_arrow_height' => $old_options['RMLinkHeight'] ? $old_options['RMLinkHeight'] + 24 : '',
145
  'submenu_arrow_width' => $old_options['RMLinkHeight'] ? $old_options['RMLinkHeight'] + 24 : '',
146
- 'external_files' => $old_options['RMExternal'] ? 'on' : 'off',
147
  'menu_appear_from' => $old_options['RMSide'] ? $old_options['RMSide'] : '',
148
- 'scripts_in_footer' => $old_options['RMFooter'] ? 'on' : 'off',
149
  'button_image' => $old_options['RMClickImg'] ? $old_options['RMClickImg'] : '',
150
- 'minify_scripts' => $old_options['RMMinify'] ? 'on' : 'off',
151
- 'menu_close_on_link_click' => $old_options['RMClickClose'] ? 'on' : 'off',
152
  'menu_minimum_width' => $old_options['RMMinWidth'] ? $old_options['RMMinWidth'] : '',
153
  'menu_maximum_width' => $old_options['RMMaxWidth'] ? $old_options['RMMaxWidth'] : '',
154
- 'auto_expand_current_submenus' => $old_options['RMExpandPar'] ? 'on' : 'off',
155
- 'menu_item_click_to_trigger_submenu' => $old_options['RMIgnParCli'] ? 'on' : 'off',
156
- 'menu_close_on_body_click' => $old_options['RMCliToClo'] ? 'on' : 'off',
157
  'menu_title_link' => $old_options['RMTitleLink'] ? $old_options['RMTitleLink'] : '',
158
  'menu_additional_content' => $old_options['RMHtml'] ? $old_options['RMHtml'] : '',
159
- 'shortcode' => $old_options['RMShortcode'] ? 'on' : 'off',
160
  'button_line_height' => $old_options['RMLineHeight'] ? $old_options['RMLineHeight'] : '',
161
  'button_line_width' => $old_options['RMLineWidth'] ? $old_options['RMLineWidth'] : '',
162
  'button_line_margin' => $old_options['RMLineMargin'] ? $old_options['RMLineMargin'] : '',
163
  'button_image_when_clicked' => $old_options['RMClickImgClicked'] ? $old_options['RMClickImgClicked'] : '',
164
- 'accordion_animation' => $old_options['RMAccordion'] ? 'on' : 'off',
165
  'active_arrow_shape' => $old_options['RMArShpA'] ? json_decode($old_options['RMArShpA']) : '',
166
  'inactive_arrow_shape' => $old_options['RMArShpI'] ? json_decode($old_options['RMArShpI']) : '',
167
  'active_arrow_image' => $old_options['RMArImgA'] ? $old_options['RMArImgA'] : '',
168
  'inactive_arrow_image' => $old_options['RMArImgI'] ? $old_options['RMArImgI'] : '',
169
- 'button_push_with_animation' => $old_options['RMPushBtn'] ? 'on' : 'off',
170
  'menu_current_item_background_hover_colour' => $old_options['RMCurBkgHov'] ? $old_options['RMCurBkgHov'] : '',
171
  'menu_current_link_hover_colour' => $old_options['RMCurColHov'] ? $old_options['RMCurColHov'] : '',
172
  'custom_walker' => $old_options['RMWalker'] ? $old_options['RMWalker'] : '',
@@ -175,14 +190,12 @@ class Migration{
175
  'button_title_position' => $old_options['RMClickTitlePos'] ? $old_options['RMClickTitlePos'] : '',
176
  ];
177
 
178
- foreach(array_filter($new_options) as $key => $val)
179
- $this->db->insert(self::$table, array('name' => $key, 'value' => $val));
180
 
181
- }
 
182
 
183
- public function getCurrentVersion() {
184
- $plugin_data = get_plugin_data(dirname(dirname(dirname(dirname(__FILE__)))) . '/responsive-menu.php', false, false);
185
- return $plugin_data['Version'];
186
  }
187
 
188
  }
1
  <?php
2
 
3
  namespace ResponsiveMenu\Database;
4
+ use ResponsiveMenu\Collections\OptionsCollection as OptionsCollection;
5
  use ResponsiveMenu\Database\Database as Database;
6
+ use ResponsiveMenu\Services\OptionService as OptionService;
7
 
8
+ class Migration {
9
 
10
  protected $db;
11
 
12
+ protected $current_version;
13
+ protected $old_version;
14
+ protected $old_options;
15
+ protected $defaults;
16
+
17
  protected static $table = 'responsive_menu';
18
+ protected static $version_var = 'RMVer';
19
 
20
+ public function __construct(Database $db, OptionService $service, $defaults, $current_version, $old_version, $old_options) {
21
+ $this->db = $db;
22
+ $this->service = $service;
23
+ $this->defaults = $defaults;
24
+ $this->current_version = $current_version;
25
+ $this->old_version = $old_version;
26
+ $this->old_options = $old_options;
27
  }
28
 
29
+ public function addNewOptions() {
30
+ $options = $this->service->all();
31
+ if($options->isEmpty())
32
+ $this->service->createOptions($this->defaults);
33
+ else
34
+ $this->service->createOptions($this->getNewOptions($options));
 
 
 
 
 
 
 
 
 
 
35
  }
36
 
37
+ public function tidyUpOptions() {
38
+ foreach($this->getOptionsToDelete() as $delete)
39
+ $this->db->delete(self::$table, array('name' => $delete));
 
40
  }
41
 
42
+ public function getNewOptions(OptionsCollection $options) {
43
+ $current = [];
44
+ foreach($options->all() as $converted)
45
+ $current[$converted->getName()] = $converted->getValue();
46
+ return array_diff_key($this->defaults, $current);
47
+ }
48
+
49
+ /*
50
+ Can't be tested :-( */
51
  public function setup() {
52
  # Create the database table if it doesn't exist
53
+ if(!$this->isVersion3()):
54
  $sql = "CREATE TABLE " . $this->db->getPrefix() . self::$table . " (
55
  name varchar(50) NOT NULL,
56
  value varchar(5000) DEFAULT NULL,
65
  }
66
 
67
  public function synchronise() {
68
+
69
  # First Thing we need to do is migrate any old options
70
+ if(!$this->isVersion3())
71
  $this->migrateVersion2Options();
72
+
73
+ if($this->needsUpdate()):
 
74
 
75
  # Now we can add any new options
76
  $this->addNewOptions();
81
  # And Update Version
82
  $this->updateVersion();
83
 
84
+ endif;
 
85
 
 
 
86
  }
87
 
88
+ public function needsUpdate() {
89
+ return version_compare($this->old_version, $this->current_version, '<');
90
  }
91
 
92
  protected function updateVersion() {
93
+ update_option(self::$version_var, $this->current_version);
94
  }
95
 
96
+ public function isVersion3() {
97
+ return substr($this->old_version, 0, 1) == 3;
98
+ }
99
+
100
+ public function migrateVersion2Options() {
101
+ $this->service->createOptions($this->getMigratedOptions());
102
+ }
103
+
104
+ public function getOptionsToDelete() {
105
+ return array_diff(
106
+ array_map(function($a) { return $a->getName(); }, $this->service->all()->all()),
107
+ array_keys($this->defaults)
108
+ );
109
  }
110
 
111
+ public function getMigratedOptions() {
112
+ $old_options = $this->old_options;
113
 
114
  $new_options = [
115
  'menu_to_use' => $old_options['RM'] ? $old_options['RM'] : '',
122
  'button_line_colour' => $old_options['RMLineCol'] ? $old_options['RMLineCol'] : '',
123
  'button_background_colour' => $old_options['RMClickBkg'] ? $old_options['RMClickBkg'] : '',
124
  'button_title' => $old_options['RMClickTitle'] ? $old_options['RMClickTitle'] : '',
125
+ 'button_transparent_background' => $old_options['RMBkgTran'] ? 'on' : '',
126
  'menu_font' => $old_options['RMFont'] ? $old_options['RMFont'] : '',
127
  'button_position_type' => $old_options['RMPos'] ? 'fixed' : '',
128
  'menu_title_image' => $old_options['RMImage'] ? $old_options['RMImage'] : '',
142
  'menu_link_hover_colour' => $old_options['RMTextColHov'] ? $old_options['RMTextColHov'] : '',
143
  'menu_sub_arrow_shape_hover_colour' => $old_options['RMTextColHov'] ? $old_options['RMTextColHov'] : '',
144
  'menu_title_hover_colour' => $old_options['RMTitleColHov'] ? $old_options['RMTitleColHov'] : '',
145
+ 'animation_type' => $old_options['RMAnim'] == 'push' ? 'push' : '',
146
  'page_wrapper' => $old_options['RMPushCSS'] ? $old_options['RMPushCSS'] : '',
147
  'menu_title_background_colour' => $old_options['RMTitleBkg'] ? $old_options['RMTitleBkg'] : '',
148
  'menu_title_background_hover_colour' => $old_options['RMTitleBkg'] ? $old_options['RMTitleBkg'] : '',
154
  'animation_speed' => $old_options['RMAnimSpd'] ? $old_options['RMAnimSpd'] : '',
155
  'transition_speed' => $old_options['RMTranSpd'] ? $old_options['RMTranSpd'] : '',
156
  'menu_text_alignment' => $old_options['RMTxtAlign'] ? $old_options['RMTxtAlign'] : '',
157
+ 'auto_expand_all_submenus' => $old_options['RMExpand'] ? 'on' : '',
158
  'menu_links_height' => $old_options['RMLinkHeight'] ? $old_options['RMLinkHeight'] + 24 : '',
159
  'submenu_arrow_height' => $old_options['RMLinkHeight'] ? $old_options['RMLinkHeight'] + 24 : '',
160
  'submenu_arrow_width' => $old_options['RMLinkHeight'] ? $old_options['RMLinkHeight'] + 24 : '',
161
+ 'external_files' => $old_options['RMExternal'] ? 'on' : '',
162
  'menu_appear_from' => $old_options['RMSide'] ? $old_options['RMSide'] : '',
163
+ 'scripts_in_footer' => $old_options['RMFooter'] ? 'on' : '',
164
  'button_image' => $old_options['RMClickImg'] ? $old_options['RMClickImg'] : '',
165
+ 'minify_scripts' => $old_options['RMMinify'] ? 'on' : '',
166
+ 'menu_close_on_link_click' => $old_options['RMClickClose'] ? 'on' : '',
167
  'menu_minimum_width' => $old_options['RMMinWidth'] ? $old_options['RMMinWidth'] : '',
168
  'menu_maximum_width' => $old_options['RMMaxWidth'] ? $old_options['RMMaxWidth'] : '',
169
+ 'auto_expand_current_submenus' => $old_options['RMExpandPar'] ? 'on' : '',
170
+ 'menu_item_click_to_trigger_submenu' => $old_options['RMIgnParCli'] ? 'on' : '',
171
+ 'menu_close_on_body_click' => $old_options['RMCliToClo'] ? 'on' : '',
172
  'menu_title_link' => $old_options['RMTitleLink'] ? $old_options['RMTitleLink'] : '',
173
  'menu_additional_content' => $old_options['RMHtml'] ? $old_options['RMHtml'] : '',
174
+ 'shortcode' => $old_options['RMShortcode'] ? 'on' : '',
175
  'button_line_height' => $old_options['RMLineHeight'] ? $old_options['RMLineHeight'] : '',
176
  'button_line_width' => $old_options['RMLineWidth'] ? $old_options['RMLineWidth'] : '',
177
  'button_line_margin' => $old_options['RMLineMargin'] ? $old_options['RMLineMargin'] : '',
178
  'button_image_when_clicked' => $old_options['RMClickImgClicked'] ? $old_options['RMClickImgClicked'] : '',
179
+ 'accordion_animation' => $old_options['RMAccordion'] ? 'on' : '',
180
  'active_arrow_shape' => $old_options['RMArShpA'] ? json_decode($old_options['RMArShpA']) : '',
181
  'inactive_arrow_shape' => $old_options['RMArShpI'] ? json_decode($old_options['RMArShpI']) : '',
182
  'active_arrow_image' => $old_options['RMArImgA'] ? $old_options['RMArImgA'] : '',
183
  'inactive_arrow_image' => $old_options['RMArImgI'] ? $old_options['RMArImgI'] : '',
184
+ 'button_push_with_animation' => $old_options['RMPushBtn'] ? 'on' : '',
185
  'menu_current_item_background_hover_colour' => $old_options['RMCurBkgHov'] ? $old_options['RMCurBkgHov'] : '',
186
  'menu_current_link_hover_colour' => $old_options['RMCurColHov'] ? $old_options['RMCurColHov'] : '',
187
  'custom_walker' => $old_options['RMWalker'] ? $old_options['RMWalker'] : '',
190
  'button_title_position' => $old_options['RMClickTitlePos'] ? $old_options['RMClickTitlePos'] : '',
191
  ];
192
 
193
+ $to_save = [];
 
194
 
195
+ foreach(array_filter($new_options) as $key => $val)
196
+ $to_save[$key] = $val;
197
 
198
+ return $to_save;
 
 
199
  }
200
 
201
  }
src/app/Factories/AdminSaveFactory.php CHANGED
@@ -12,34 +12,31 @@ class AdminSaveFactory {
12
 
13
  $flash = [];
14
 
15
- if($options['external_files'] == 'on'):
16
-
17
- $css_factory = new CssFactory;
18
- $js_factory = new JsFactory;
19
- $file_creator = new FileCreator;
20
-
21
- # Create Data Folders if They don't exist
22
- $data_folder_dir = dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/responsive-menu-data';
23
- $js_folder = $data_folder_dir . '/js';
24
- $css_folder = $data_folder_dir . '/css';
25
- if($options['external_files'] == 'on' && !is_dir($data_folder_dir)):
26
- if(!mkdir($data_folder_dir)) $flash['errors'][] = __('Unable to make data directory', 'responsive-menu');
27
- if(!mkdir($css_folder)) $flass['errors'][] = __('Unable to make CSS data directory', 'responsive-menu');
28
- if(!mkdir($js_folder)) $flash['errors'][] = __('Unable to make JS data directory', 'responsive-menu');
29
- endif;
30
-
31
- $css = $css_factory->build($options);
32
- $js = $js_factory->build($options);
33
 
34
- if(!$file_creator->createCssFile($css_folder, 'responsive-menu-' . get_current_blog_id() . '.css', $css))
35
- $flash['errors'][] = __('Unable to create CSS file', 'responsive-menu');
36
 
37
- if(!$file_creator->createJsFile($js_folder, 'responsive-menu-' . get_current_blog_id() . '.js', $js))
38
- $flash['errors'][] = __('Unable to create JS file', 'responsive-menu');
39
 
40
- endif;
 
41
 
42
  return empty($flash) ? null : $flash;
43
 
44
  }
 
45
  }
12
 
13
  $flash = [];
14
 
15
+ $css_factory = new CssFactory;
16
+ $js_factory = new JsFactory;
17
+ $file_creator = new FileCreator;
18
+
19
+ # Create Data Folders if They don't exist
20
+ $data_folder_dir = dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/responsive-menu-data';
21
+ $js_folder = $data_folder_dir . '/js';
22
+ $css_folder = $data_folder_dir . '/css';
23
+ if($options['external_files'] == 'on' && !is_dir($data_folder_dir)):
24
+ if(!mkdir($data_folder_dir)) $flash['errors'][] = __('Unable to make data directory', 'responsive-menu');
25
+ if(!mkdir($css_folder)) $flass['errors'][] = __('Unable to make CSS data directory', 'responsive-menu');
26
+ if(!mkdir($js_folder)) $flash['errors'][] = __('Unable to make JS data directory', 'responsive-menu');
27
+ endif;
 
 
 
 
 
28
 
29
+ $css = $css_factory->build($options);
30
+ $js = $js_factory->build($options);
31
 
32
+ if(!$file_creator->createCssFile($css_folder, 'responsive-menu-' . get_current_blog_id() . '.css', $css))
33
+ $flash['errors'][] = __('Unable to create CSS file', 'responsive-menu');
34
 
35
+ if(!$file_creator->createJsFile($js_folder, 'responsive-menu-' . get_current_blog_id() . '.js', $js))
36
+ $flash['errors'][] = __('Unable to create JS file', 'responsive-menu');
37
 
38
  return empty($flash) ? null : $flash;
39
 
40
  }
41
+
42
  }
src/app/Factories/OptionFactory.php CHANGED
@@ -5,9 +5,7 @@ use ResponsiveMenu\Models\Option as Option;
5
 
6
  class OptionFactory {
7
 
8
- public function __construct() {
9
- include dirname(dirname(dirname(__FILE__))) . '/config/option_helpers.php';
10
- include dirname(dirname(dirname(__FILE__))) . '/config/default_options.php';
11
  $this->defaults = $default_options;
12
  $this->helper = $option_helpers;
13
  }
5
 
6
  class OptionFactory {
7
 
8
+ public function __construct($default_options, $option_helpers) {
 
 
9
  $this->defaults = $default_options;
10
  $this->helper = $option_helpers;
11
  }
src/app/Mappers/JsMapper.php CHANGED
@@ -107,7 +107,7 @@ class JsMapper
107
  }
108
  if(this.animationType == 'push') {
109
  $(this.pageWrapper).css({'transform':translate});
110
- $('html,body').css('overflow-x', 'hidden');
111
  }
112
  if(this.pushButton == 'on') {
113
  $('#responsive-menu-button').css({'transform':translate});
@@ -118,8 +118,8 @@ class JsMapper
118
  if(this.animationType == 'push') {
119
  $(this.pageWrapper).css({'transform':''});
120
  setTimeout(function() {
121
- $('html,body').css('overflow-x', '');
122
- }, self.animationSpeed * 1000);
123
  }
124
  if(this.pushButton == 'on') {
125
  $('#responsive-menu-button').css({'transform':''});
107
  }
108
  if(this.animationType == 'push') {
109
  $(this.pageWrapper).css({'transform':translate});
110
+ $('html, body').css('overflow-x', 'hidden');
111
  }
112
  if(this.pushButton == 'on') {
113
  $('#responsive-menu-button').css({'transform':translate});
118
  if(this.animationType == 'push') {
119
  $(this.pageWrapper).css({'transform':''});
120
  setTimeout(function() {
121
+ $('html, body').css('overflow-x', '');
122
+ }, self.animationSpeed);
123
  }
124
  if(this.pushButton == 'on') {
125
  $('#responsive-menu-button').css({'transform':''});
src/app/Repositories/OptionRepository.php CHANGED
@@ -22,12 +22,15 @@ class OptionRepository {
22
  }
23
 
24
  public function update(Option $option) {
25
- $this->db->update(self::$table, ['value' => $option->getFiltered()], ['name' => $option->getName()]);
 
 
 
26
  }
27
 
28
- public function create($name, $value) {
29
- $arguments['name'] = $name;
30
- $arguments['value'] = $value;
31
  $arguments['created_at'] = current_time('mysql');
32
  $this->db->insert(self::$table, $arguments);
33
  }
22
  }
23
 
24
  public function update(Option $option) {
25
+ $this->db->update(self::$table,
26
+ ['value' => $option->getFiltered()],
27
+ ['name' => $option->getName()]
28
+ );
29
  }
30
 
31
+ public function create(Option $option) {
32
+ $arguments['name'] = $option->getName();
33
+ $arguments['value'] = $option->getFiltered();
34
  $arguments['created_at'] = current_time('mysql');
35
  $this->db->insert(self::$table, $arguments);
36
  }
src/app/Routing/WpRouting.php CHANGED
@@ -40,12 +40,20 @@ class WpRouting implements Routing {
40
  'responsive-menu',
41
  function() use ($method) {
42
  $controller = $this->container['admin_controller'];
43
- if($method == 'update' || $method == 'reset'):
44
- include dirname(dirname(dirname(__FILE__))) . '/config/default_options.php';
45
- $controller->$method($default_options);
46
- else:
47
- $controller->$method();
48
- endif;
 
 
 
 
 
 
 
 
49
  },
50
  'dashicons-menu');
51
  }
40
  'responsive-menu',
41
  function() use ($method) {
42
  $controller = $this->container['admin_controller'];
43
+ switch ($method) :
44
+ case 'update':
45
+ $controller->$method($this->container['default_options'], $_POST['menu']);
46
+ break;
47
+ case 'reset':
48
+ $controller->$method($this->container['default_options']);
49
+ break;
50
+ case 'import':
51
+ $controller->$method($this->container['default_options'], $_FILES['responsive_menu_import_file']);
52
+ break;
53
+ default:
54
+ $controller->$method();
55
+ break;
56
+ endswitch;
57
  },
58
  'dashicons-menu');
59
  }
src/app/Services/OptionService.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\Services;
4
+ use ResponsiveMenu\Repositories\OptionRepository as OptionRepository;
5
+ use ResponsiveMenu\WPML\WPML as WPML;
6
+ use ResponsiveMenu\Factories\AdminSaveFactory as SaveFactory;
7
+ use ResponsiveMenu\Factories\OptionFactory as OptionFactory;
8
+ use ResponsiveMenu\Collections\OptionsCollection as OptionsCollection;
9
+
10
+ class OptionService {
11
+
12
+ public function __construct(OptionRepository $repository, OptionFactory $factory) {
13
+ $this->repository = $repository;
14
+ $this->factory = $factory;
15
+ }
16
+
17
+ public function updateOptions(array $options) {
18
+
19
+ foreach($options as $key => $val)
20
+ $this->repository->update($this->factory->build($key, $val));
21
+
22
+ $options = $this->all();
23
+
24
+ $this->updateWpml($options);
25
+ $this->buildFiles($options);
26
+
27
+ return $options;
28
+ }
29
+
30
+ public function createOptions(array $options) {
31
+
32
+ foreach($options as $key => $val)
33
+ $this->repository->create($this->factory->build($key, $val));
34
+
35
+ $options = $this->all();
36
+
37
+ $this->updateWpml($options);
38
+ $this->buildFiles($options);
39
+
40
+ return $options;
41
+ }
42
+
43
+ public function all() {
44
+ return $this->repository->all();
45
+ }
46
+
47
+ public function updateWpml(OptionsCollection $options) {
48
+ $wpml = new WPML;
49
+ $wpml->saveFromOptions($options);
50
+ }
51
+
52
+ public function buildFiles(OptionsCollection $options) {
53
+ if($options['external_files'] == 'on'):
54
+ $save_factory = new SaveFactory();
55
+ $save_factory->build($options);
56
+ endif;
57
+ }
58
+
59
+ }
src/app/ViewModels/Components/Admin/Tabs.php CHANGED
@@ -11,8 +11,11 @@ class Tabs {
11
  }
12
 
13
  public function render() {
 
14
  foreach(array_keys($this->config) as $tab_name) {
15
- echo '<a id="tab_' . $this->i($tab_name) . '" class="tab page-title-action">' . $tab_name . '</a>';
 
 
16
  }
17
  }
18
 
11
  }
12
 
13
  public function render() {
14
+ $i=0;
15
  foreach(array_keys($this->config) as $tab_name) {
16
+ $active_class = $i == 0 ? ' active_tab' : '';
17
+ echo '<a id="tab_' . $this->i($tab_name) . '" class="tab page-title-action' . $active_class . '">' . $tab_name . '</a>';
18
+ $i++;
19
  }
20
  }
21
 
src/app/WPML/WPML.php CHANGED
@@ -6,10 +6,17 @@ use ResponsiveMenu\Collections\OptionsCollection as OptionsCollection;
6
  class WPML {
7
 
8
  public function saveFromOptions(OptionsCollection $options) {
9
- do_action('wpml_register_single_string', 'Responsive Menu', 'menu_to_use', $options['menu_to_use']->getValue());
10
- do_action('wpml_register_single_string', 'Responsive Menu', 'button_title', $options['button_title']->getValue());
11
- do_action('wpml_register_single_string', 'Responsive Menu', 'menu_title', $options['menu_title']->getValue());
12
- do_action('wpml_register_single_string', 'Responsive Menu', 'menu_title_link', $options['menu_title_link']->getValue());
 
 
 
 
 
 
 
13
  }
14
 
15
  }
6
  class WPML {
7
 
8
  public function saveFromOptions(OptionsCollection $options) {
9
+ if(isset($options['menu_to_use']))
10
+ do_action('wpml_register_single_string', 'Responsive Menu', 'menu_to_use', $options['menu_to_use']->getValue());
11
+
12
+ if(isset($options['button_title']))
13
+ do_action('wpml_register_single_string', 'Responsive Menu', 'button_title', $options['button_title']->getValue());
14
+
15
+ if(isset($options['menu_title']))
16
+ do_action('wpml_register_single_string', 'Responsive Menu', 'menu_title', $options['menu_title']->getValue());
17
+
18
+ if(isset($options['menu_title_link']))
19
+ do_action('wpml_register_single_string', 'Responsive Menu', 'menu_title_link', $options['menu_title_link']->getValue());
20
  }
21
 
22
  }
src/app/Walkers/WpWalker.php CHANGED
@@ -37,7 +37,7 @@ class WpWalker extends \Walker_Nav_Menu
37
  {
38
  $this->curItem = $item;
39
  $classes = empty( $item->classes ) ? array() : (array) $item->classes;
40
- $responsive_menu_classes = [];
41
 
42
  # Turn into our Responsive Menu Classes
43
  foreach($classes as $class):
37
  {
38
  $this->curItem = $item;
39
  $classes = empty( $item->classes ) ? array() : (array) $item->classes;
40
+ $responsive_menu_classes = $classes;
41
 
42
  # Turn into our Responsive Menu Classes
43
  foreach($classes as $class):
src/config/route_dependencies.php CHANGED
@@ -2,16 +2,63 @@
2
 
3
  $container = new ResponsiveMenu\Routing\Container();
4
 
 
 
 
 
 
 
 
 
 
 
5
  $container['database'] = function($c) {
6
  return new ResponsiveMenu\Database\WpDatabase;
7
  };
8
 
9
  $container['option_factory'] = function($c) {
10
- return new ResponsiveMenu\Factories\OptionFactory;
 
 
 
11
  };
12
 
13
  $container['option_repository'] = function($c) {
14
- return new ResponsiveMenu\Repositories\OptionRepository($c['database'], $c['option_factory']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  };
16
 
17
  $container['admin_view'] = function($c) {
@@ -23,9 +70,15 @@ $container['front_view'] = function($c) {
23
  };
24
 
25
  $container['admin_controller'] = function($c) {
26
- return new ResponsiveMenu\Controllers\Admin($c['option_repository'], $c['admin_view']);
 
 
 
27
  };
28
 
29
  $container['front_controller'] = function($c) {
30
- return new ResponsiveMenu\Controllers\Front($c['option_repository'], $c['front_view']);
 
 
 
31
  };
2
 
3
  $container = new ResponsiveMenu\Routing\Container();
4
 
5
+ $container['option_helpers'] = function($c) {
6
+ include dirname(__FILE__) . '/option_helpers.php';
7
+ return $option_helpers;
8
+ };
9
+
10
+ $container['default_options'] = function($c) {
11
+ include dirname(__FILE__) . '/default_options.php';
12
+ return $default_options;
13
+ };
14
+
15
  $container['database'] = function($c) {
16
  return new ResponsiveMenu\Database\WpDatabase;
17
  };
18
 
19
  $container['option_factory'] = function($c) {
20
+ return new ResponsiveMenu\Factories\OptionFactory(
21
+ $c['default_options'],
22
+ $c['option_helpers']
23
+ );
24
  };
25
 
26
  $container['option_repository'] = function($c) {
27
+ return new ResponsiveMenu\Repositories\OptionRepository(
28
+ $c['database'],
29
+ $c['option_factory']
30
+ );
31
+ };
32
+
33
+ $container['option_service'] = function($c) {
34
+ return new ResponsiveMenu\Services\OptionService(
35
+ $c['option_repository'],
36
+ $c['option_factory']
37
+ );
38
+ };
39
+
40
+ $container['current_version'] = function($c) {
41
+ $plugin_data = get_plugin_data(dirname(dirname(dirname(__FILE__))) . '/responsive-menu.php', false, false);
42
+ return $plugin_data['Version'];
43
+ };
44
+
45
+ $container['old_version'] = function($c) {
46
+ return get_option('RMVer');
47
+ };
48
+
49
+ $container['old_options'] = function($c) {
50
+ return get_option('RMOptions');
51
+ };
52
+
53
+ $container['migration'] = function($c) {
54
+ return new ResponsiveMenu\Database\Migration(
55
+ $c['database'],
56
+ $c['option_service'],
57
+ $c['default_options'],
58
+ $c['current_version'],
59
+ $c['old_version'],
60
+ $c['old_options']
61
+ );
62
  };
63
 
64
  $container['admin_view'] = function($c) {
70
  };
71
 
72
  $container['admin_controller'] = function($c) {
73
+ return new ResponsiveMenu\Controllers\Admin(
74
+ $c['option_service'],
75
+ $c['admin_view']
76
+ );
77
  };
78
 
79
  $container['front_controller'] = function($c) {
80
+ return new ResponsiveMenu\Controllers\Front(
81
+ $c['option_service'],
82
+ $c['front_view']
83
+ );
84
  };
src/public/css/admin/main.css CHANGED
@@ -227,10 +227,11 @@ input[type="text"].image,
227
  bottom: 0;
228
  position: absolute;
229
  text-align: center;
230
- color: #333;
231
- transform: translateY(30%);
232
  font-weight: bold;
233
  font-size: 14px;
 
 
234
  }
235
 
236
  #items_order_container td:last-child,
227
  bottom: 0;
228
  position: absolute;
229
  text-align: center;
230
+ color: #fff;
 
231
  font-weight: bold;
232
  font-size: 14px;
233
+ padding-top: 2%;
234
+ background: rgba(222, 75, 66, 0.6);
235
  }
236
 
237
  #items_order_container td:last-child,