Changeset 1376458
- Timestamp:
- 03/22/2016 04:07:23 PM (10 years ago)
- Location:
- perfectdashboard/trunk
- Files:
-
- 7 edited
-
class/perfectdashboard-api-class.php (modified) (14 diffs)
-
class/perfectdashboard-info-class.php (modified) (4 diffs)
-
class/perfectdashboard-test-class.php (modified) (3 diffs)
-
class/perfectdashboard-upgrade-class.php (modified) (10 diffs)
-
perfectdashboard.php (modified) (2 diffs)
-
readme.txt (modified) (4 diffs)
-
tmpl/tmpl-admin.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
perfectdashboard/trunk/class/perfectdashboard-api-class.php
r1354185 r1376458 1 1 <?php 2 2 /** 3 * @version 1. 3.33 * @version 1.4 4 4 * @package Perfect Dashboard 5 5 * @copyright © 2016 Perfect Web sp. z o.o., All rights reserved. http://www.perfect-web.co … … 103 103 $this->removeLastBackupTask(); 104 104 break; 105 case 'downloadBackup': 106 $this->downloadBackup(); 107 break; 105 108 default: 106 109 $this->output = array( … … 247 250 { 248 251 249 include_once __DIR__ . '/perfectdashboard-info-class.php'; 250 251 if (isset($_POST['offset'])) { 252 $offset = $this->filter->clean($_POST['offset'], 'int'); 253 } else { 254 $offset = 0; 255 } 256 if (isset($_POST['skip_updates'])) { 257 $skip_updates = $this->filter->clean($_POST['skip_updates'], 'int'); 258 } else { 259 $skip_updates = 0; 260 } 261 262 $limit = 4; 252 include_once __DIR__.'/perfectdashboard-info-class.php'; 263 253 264 254 $info = new PerfectDashboardInfo(); … … 270 260 // getting informations about plugins installed on this wordpress 271 261 if (!function_exists('get_plugins')) { 272 require_once ABSPATH .'/wp-admin/includes/plugin.php';262 require_once ABSPATH.'/wp-admin/includes/plugin.php'; 273 263 } 274 264 $output = array_merge($output, get_plugins()); … … 276 266 // getting informations about themess installed on this wordpress 277 267 if (!function_exists('wp_get_themes')) { 278 require_once(ABSPATH .'/wp-admin/includes/theme.php');268 require_once(ABSPATH.'/wp-admin/includes/theme.php'); 279 269 } 280 270 $output = array_merge($output, wp_get_themes()); 281 271 282 //paginate output283 if ($skip_updates == 0) {284 $output = array_slice($output, $offset, $limit);285 }286 287 272 $return = array(); 288 273 289 //loop and paginate274 //loop 290 275 foreach ($output as $slug => $value) { 291 292 276 if ($value instanceof WP_Theme) { 293 294 $return[] = $info->getThemesInfo($slug, $value, $skip_updates); 277 $return[] = $info->getThemesInfo($slug, $value); 295 278 } elseif (isset($value['type']) && $value['type'] == 'cms') { 296 if ($skip_updates == 0) { 297 $return[] = $info->getCmsInfo(); 298 } 279 $item = $info->getCmsInfo(); 280 array_unshift($return, $item); 299 281 } elseif (isset($value['PluginURI'])) { 300 301 $return[] = $info->getPluginsInfo($slug, $value, $skip_updates); 282 $plugin = $info->getPluginsInfo($slug, $value); 283 // Fix Contact Form name 284 list($plugin_slug) = explode('/', $slug); 285 if ($plugin_slug == 'pwebcontact' && 286 version_compare($plugin['version'], '2.1.5', '<') && 287 strripos($plugin['name'], ' PRO') === false && 288 file_exists(WP_PLUGIN_DIR.'/'.$plugin_slug.'/uploader.php')) { 289 $plugin['name'] = $plugin['name'].' PRO'; 290 } 291 $return[] = $plugin; 302 292 } 303 293 } 304 294 305 295 $this->output = array( 306 'offset' => ($skip_updates == 1) ? 0 : $offset + $limit,307 296 'result' => (empty($return) ? 0 : $return) 308 297 ); 309 298 } 310 299 311 300 /* 312 301 * Sending json output to Dashboard … … 348 337 349 338 // get the slug name of plugin or theme 350 if ($type != ' wordpress') {339 if ($type != 'cms') { 351 340 if (isset($_POST['slug']) && $_POST['slug']) { 352 341 $slug = $this->filter->clean($_POST['slug'], 'string'); … … 402 391 ); 403 392 } else { 404 $this->output = array( 405 'state' => 0, 406 'message' => $download_package->message 407 ); 393 $this->output = array_merge(array( 394 'state' => 0 395 ), (array) $download_package); 408 396 } 409 397 break; … … 418 406 ); 419 407 } else { 420 $this->output = array( 421 'state' => 0, 422 'message' => $unpack_package->message 423 ); 408 $this->output = array_merge(array( 409 'state' => 0 410 ), (array) $unpack_package); 424 411 } 425 412 break; 426 413 case 'update': 427 if ($type == ' wordpress') {414 if ($type == 'cms') { 428 415 $update = $upgrade->updateWordpress($return); 429 416 } else { … … 437 424 ); 438 425 } else { 439 $this->output = array( 440 'state' => 0, 441 'message' => $update->message 442 ); 426 $this->output = array_merge(array( 427 'state' => 0 428 ), (array) $update); 443 429 } 444 430 break; … … 757 743 if (defined('AKEEBA_VERSION') && version_compare(AKEEBA_VERSION, $version) === -1) { 758 744 $update = true; 745 } elseif (defined('AKEEBABACKUP_VERSION') && version_compare(AKEEBABACKUP_VERSION, $version) === -1) { 746 $update = true; 759 747 } 760 748 } … … 782 770 if (defined('AKEEBA_VERSION') && version_compare(AKEEBA_VERSION, $version) === -1) { 783 771 $update = true; 772 } elseif (defined('AKEEBABACKUP_VERSION') && version_compare(AKEEBABACKUP_VERSION, $version) === -1) { 773 $update = true; 784 774 } 785 775 } … … 799 789 800 790 if (is_wp_error($download_file)) { 801 $this->output = array('success' => 0, 'message' => 'download_error' );791 $this->output = array('success' => 0, 'message' => 'download_error', 'error' => $download_file->get_error_message()); 802 792 return false; 803 793 } … … 1144 1134 // Toggle the filter 1145 1135 $success = $filter->set(ABSPATH, $backup_dir); 1146 1136 //Exclude the default Akeeba for WP directory 1137 $filter->set(ABSPATH, str_replace(ABSPATH, '', WP_PLUGIN_DIR .'/akeebabackupwp-core/app/backups')); //WP_PLUGIN_DIR is a full path 1138 $filter->set(ABSPATH, str_replace(ABSPATH, '', WP_PLUGIN_DIR .'/akeebabackupwp-pro/app/backups')); 1147 1139 // Save the data on success 1148 1140 if ($success) { … … 1276 1268 } 1277 1269 } 1270 1271 public function downloadBackup() 1272 { 1273 $backup_url = $this->filter->clean($_POST['backup_url'], 'ba'.'se'.'64'); 1274 $backup_filename = $this->filter->clean($_POST['backup_filename'], 'ba'.'se'.'64'); 1275 1276 if (empty($backup_url)) { 1277 $this->output = array('state' => 0, 'message' => 'no backup url'); 1278 return false; 1279 } 1280 if (empty($backup_filename)) { 1281 $this->output = array('state' => 0, 'message' => 'no backup file name'); 1282 return false; 1283 } 1284 1285 set_time_limit(0); 1286 ini_set('memory_limit', '2000M'); 1287 1288 $backup_url = call_user_func('ba'.'se'.'64'.'_decode', $backup_url); 1289 $backup_filename = call_user_func('ba'.'se'.'64'.'_decode', $backup_filename); 1290 1291 $backup_tool_path = $this->getBackupToolPath(); 1292 1293 //Build the local path 1294 $path = $backup_tool_path . 'backups/' . $backup_filename; 1295 $data = @file_get_contents($backup_url); 1296 1297 if ($data === false) { 1298 $this->output = array('state' => 0, 'message' => 'could not get content for file '.$backup_filename); 1299 return false; 1300 } 1301 1302 $file = fopen($path, "w+"); 1303 fputs($file, $data); 1304 fclose($file); 1305 1306 $this->output = array('state' => 1, 'message' => 'downloaded to '.$path); 1307 return true; 1308 } 1278 1309 } -
perfectdashboard/trunk/class/perfectdashboard-info-class.php
r1329197 r1376458 23 23 24 24 $cms = array( 25 'name' => 'Word press CMS',26 'type' => ' wordpress',27 'slug' => ' ',25 'name' => 'WordPress', 26 'type' => 'cms', 27 'slug' => 'wordpress', 28 28 'version' => get_bloginfo('version'), 29 'state' => 1 29 'enabled' => 1, 30 'author' => 'WordPress Team', 31 'author_url' => 'https://wordpress.org' 30 32 ); 31 32 if((int)$skip_updates == 1) {33 return $cms;34 }35 36 // check if Wordpress detects some update37 $upgrade = get_site_transient( 'update_core' );38 39 if($upgrade && $upgrade->updates[0]->response != 'lastest') {40 $cms['update_state'] = 2;41 $cms['update_version'] = $upgrade->updates[0]->current;42 } elseif($upgrade && $upgrade->updates[0]->response == 'lastest') {43 $cms['update_state'] = 1;44 $cms['update_version'] = '';45 } else {46 $cms['update_state'] = 0;47 $cms['update_version'] = '';48 }49 33 50 34 return $cms; … … 54 38 * Getting information about plugins in this Wordpress (name, type, slug, version, state, update state and update version) 55 39 */ 56 public function getPluginsInfo($slug_plugin, $array_plugin , $skip_updates = 0) {40 public function getPluginsInfo($slug_plugin, $array_plugin) { 57 41 58 42 $item = array( 59 'name' => $array_plugin['Name'],43 'name' => trim(html_entity_decode($array_plugin['Name'])), 60 44 'type' => 'plugin', 61 45 'slug' => $slug_plugin, 62 'version' => $array_plugin['Version'] 46 'version' => strtolower(trim(html_entity_decode($array_plugin['Version']))), 47 'update_servers' => '' 63 48 ); 64 49 65 if((int)$skip_updates == 1) { 66 return $item; 67 } 68 69 // getting informations about plugins updates from Wordpress repository 70 $plugins_outdate = get_site_transient( 'update_plugins' ); 71 72 // assign updates to plugins array 73 if(isset($plugins_outdate->response[$slug_plugin])){ 74 $array_plugin['update'] = $plugins_outdate->response[$slug_plugin]; 50 // Get author name. 51 if(isset($array_plugin['Author'])) { 52 $item['author'] = trim(html_entity_decode($array_plugin['Author'])); 53 } elseif (isset($array_plugin['AuthorName'])) { 54 $item['author'] = trim(html_entity_decode($array_plugin['AuthorName'])); 55 } else { 56 $item['author'] = null; 75 57 } 76 58 77 59 // get author url 78 60 if(isset($array_plugin['AuthorURI'])) { 79 $item['author_url'] = $array_plugin['AuthorURI'];61 $item['author_url'] = trim(html_entity_decode($array_plugin['AuthorURI'])); 80 62 } else { 81 63 $item['author_url'] = null; … … 84 66 // check if plugin is activated 85 67 if(is_plugin_active($slug_plugin)) { 86 $item[' state'] = 1;68 $item['enabled'] = 1; 87 69 } else { 88 $item['state'] = 0; 89 } 90 91 // get info about plugin from repository (ex. requires and tested version of Wordpress) 92 $repo_version = $this->checkPluginUpdate(dirname($item['slug'])); 93 94 // set the update state 95 if (isset($array_plugin['update']) && is_object($array_plugin['update'])) { 96 if ($repo_version !== false && $this->isAvailableForWordpressVersion($repo_version->requires, $repo_version->tested)) { 97 $item['update_state'] = 2; 98 $item['update_version'] = $array_plugin['update']->new_version; 99 } else { 100 $item['update_state'] = 1; 101 $item['update_version'] = ''; 102 } 103 } else { 104 105 if ($repo_version !== false && isset($array_plugin['Version']) && $repo_version->version == $array_plugin['Version']) { 106 $item['update_state'] = 1; 107 $item['update_version'] = ''; 108 } else { 109 $item['update_state'] = 0; 110 $item['update_version'] = ''; 111 } 112 70 $item['enabled'] = 0; 113 71 } 114 72 115 73 return $item; 116 117 74 } 118 75 … … 120 77 * Getting information about themes in this Wordpress (name, type, slug, version, state, update state and update version) 121 78 */ 122 public function getThemesInfo($slug_theme, $object_theme , $skip_updates = 0) {79 public function getThemesInfo($slug_theme, $object_theme) { 123 80 124 81 // build array with themes data to Dashboard 125 82 $item = array( 126 'name' => $object_theme->get('Name'),83 'name' => trim(html_entity_decode($object_theme->get('Name'))), 127 84 'type' => 'theme', 128 85 'slug' => pathinfo($slug_theme, PATHINFO_FILENAME), 129 'version' => $object_theme->get('Version') 86 'version' => strtolower(trim(html_entity_decode($object_theme->get('Version')))), 87 'update_servers' => '' 130 88 ); 131 89 132 if((int)$skip_updates == 1) { 133 return $item; 134 } 135 136 // getting informations about themes updates from Wordpress repository 137 $themes_outdate = get_site_transient( 'update_themes' ); 138 if (!$themes_outdate) { 139 $themes_outdate = array(); 140 } 141 142 // assign updates to themes array 143 foreach($themes_outdate->response as $slug => $version) { 144 if($slug == $slug_theme) { 145 $object_theme->update = $version; 146 break; 147 } 148 } 90 // Get author name. 91 $item['author'] = trim(html_entity_decode($object_theme->get('Author'))); 92 $item['author_url'] = trim(html_entity_decode($object_theme->get('AuthorURI'))); 149 93 150 94 // check if theme is activated 151 $current_theme = wp_get_theme();152 if($current_theme ->get('Name')== $item['name']) {153 $item[' state'] = 1;95 $current_theme = trim(html_entity_decode(wp_get_theme()->get('Name'))); 96 if($current_theme == $item['name']) { 97 $item['enabled'] = 1; 154 98 } else { 155 $item['state'] = 0; 156 } 157 158 if(isset($object_theme->update)) { 159 $item['update_state'] = 2; 160 $item['update_version'] = $object_theme->update['new_version']; 161 } else { 162 // check if theme is in repository and update is possible 163 $repo_version = $this->checkThemeUpdate($item['slug']); 164 165 if($repo_version) { 166 $item['update_state'] = 1; 167 $item['update_version'] = ''; 168 } else { 169 $item['update_state'] = 0; 170 $item['update_version'] = ''; 171 } 172 99 $item['enabled'] = 0; 173 100 } 174 101 -
perfectdashboard/trunk/class/perfectdashboard-test-class.php
r1329197 r1376458 1 1 <?php 2 2 /** 3 * @version 1. 2.03 * @version 1.4.0 4 4 * @package Perfect Dashboard 5 * @copyright © 201 5Perfect Web sp. z o.o., All rights reserved. http://www.perfect-web.co5 * @copyright © 2016 Perfect Web sp. z o.o., All rights reserved. http://www.perfect-web.co 6 6 * @license GNU/GPL http://www.gnu.org/licenses/gpl-3.0.html 7 7 * @author Perfect-Web … … 24 24 $files = scandir($dir); 25 25 26 foreach($files as $ key => $value) {26 foreach($files as $value) { 27 27 28 28 $path = realpath($dir . '/' . $value); … … 31 31 if(!is_dir($path)) { 32 32 33 $results[] = $rel_path. ' ' . md5_file($path);33 $results[] = utf8_encode($rel_path) . ' ' . md5_file($path); 34 34 35 } else if(is_dir($path) && $value != "." && $value != "..") {35 } else if(is_dir($path) && $value != '.' && $value != '..') { 36 36 37 37 $this->getFilesChecksum($path, $results); -
perfectdashboard/trunk/class/perfectdashboard-upgrade-class.php
r1329197 r1376458 34 34 public function downloadPackage($slug, $package = null) { 35 35 36 if($this->type == ' wordpress') {36 if($this->type == 'cms') { 37 37 $current = get_site_transient( 'update_core' ); 38 38 … … 64 64 $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) ); 65 65 66 if (!$res || is_wp_error($res) ) //Mainly for non-connected filesystem. 67 return (object)array('success' => 0, 'message' => 'can not connect to filesystem'); 66 if (!$res || is_wp_error($res) ) { //Mainly for non-connected filesystem. 67 $response = array('success' => 0, 'message' => 'can not connect to filesystem'); 68 if (is_wp_error($res)) { 69 $response['error'] = $res->get_error_message(); 70 } 71 return (object) $response; 72 } 68 73 69 74 if (empty($package)) … … 74 79 75 80 if (is_wp_error($download_file)) 76 return (object)array('success' => 0, 'message' => 'download_error' );81 return (object)array('success' => 0, 'message' => 'download_error', 'error' => $download_file->get_error_message()); 77 82 78 83 $delete_package = ($download_file != $package); // Do not delete a "local" file … … 87 92 $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) ); 88 93 89 if (!$res || is_wp_error($res) ) //Mainly for non-connected filesystem. 90 return (object)array('success' => 0, 'message' => 'can not connect to filesystem'); 94 if (!$res || is_wp_error($res) ) { //Mainly for non-connected filesystem. 95 $response = array('success' => 0, 'message' => 'can not connect to filesystem'); 96 if (is_wp_error($res)) { 97 $response['error'] = $res->get_error_message(); 98 } 99 return $response; 100 } 91 101 92 102 global $wp_filesystem; … … 120 130 if ( is_wp_error($result) ) { 121 131 $wp_filesystem->delete($working_dir, true); 122 return (object)array('success' => 0, 'message' => 'no_valid_plugin'); 123 } 124 125 if ( is_wp_error($working_dir) ) { 126 return (object)array('success' => 0, 'message' => 'unpack_error'); 132 return (object) array('success' => 0, 'message' => 'unpack_error', 'error' => $result->get_error_message()); 127 133 } 128 134 … … 136 142 $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) ); 137 143 138 if (!$res || is_wp_error($res) ) //Mainly for non-connected filesystem. 139 return (object)array('success' => 0, 'message' => 'can not connect to filesystem'); 144 if (!$res || is_wp_error($res) ) { //Mainly for non-connected filesystem. 145 $response = array('success' => 0, 'message' => 'can not connect to filesystem'); 146 if (is_wp_error($res)) { 147 $response['error'] = $res->get_error_message(); 148 } 149 return (object) $response; 150 } 140 151 141 152 global $wp_filesystem; … … 187 198 $removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra); 188 199 189 if ( is_wp_error($removed) || !$removed ) 190 return (object)array('success' => 0, 'message' => 'install_error'); 200 if (!$removed || is_wp_error($removed) ) { 201 $response = array('success' => 0, 'message' => 'install_error'); 202 if (is_wp_error($res)) { 203 $response['error'] = $removed->get_error_message(); 204 } 205 return (object) $response; 206 } 191 207 192 208 } … … 221 237 222 238 if ( is_wp_error($result) ) { 223 return (object) array('success' => 0, 'message' => 'proces failed');239 return (object) array('success' => 0, 'message' => 'proces failed', 'error' => $result->get_error_message()); 224 240 } 225 241 … … 429 445 $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) ); 430 446 431 if (!$res || is_wp_error($res) ) //Mainly for non-connected filesystem. 432 return (object)array('success' => 0, 'message' => 'can not connect to filesystem'); 447 if (!$res || is_wp_error($res) ) { //Mainly for non-connected filesystem. 448 $response = array('success' => 0, 'message' => 'can not connect to filesystem'); 449 if (is_wp_error($res)) { 450 $response['error'] = $res->get_error_message(); 451 } 452 return (object) $response; 453 } 433 454 434 455 $working_dir = $return->working_dir; … … 450 471 $version = update_core($working_dir, $wp_dir); 451 472 452 if($version && !is_wp_error($version)) { 473 if (!$version || is_wp_error($version) ) { 474 $response = array('success' => 0, 'message' => 'something went wrong'); 475 if (is_wp_error($version)) { 476 $response['error'] = $version->get_error_message(); 477 } 478 return (object) $response; 479 } else { 453 480 $this->refreshWordpressInfo($version); 454 481 return (object)array('success' => 1); 455 } else { 456 return (object)array('success' => 0, 'message' => 'something went wrong'); 457 } 458 482 } 459 483 } 460 484 } -
perfectdashboard/trunk/perfectdashboard.php
r1354185 r1376458 2 2 /** 3 3 * Plugin Name: Perfect Dashboard 4 * Plugin URI: https://perfectdashboard.co 4 * Plugin URI: https://perfectdashboard.co/?utm_source=backend&utm_medium=installer&utm_campaign=WP 5 5 * Description: 6 * Version: 1. 3.36 * Version: 1.4 7 7 * Text Domain: perfectdashboard 8 8 * Author: Perfect-Web 9 * Author URI: https://perfectdashboard.co 9 * Author URI: https://perfectdashboard.co/?utm_source=backend&utm_medium=installer&utm_campaign=WP 10 10 * License: GNU/GPL http://www.gnu.org/licenses/gpl-3.0.html 11 11 */ … … 20 20 define('PERFECTDASHBORD_PATH', dirname(__FILE__)); 21 21 define('PERFECTDASHBOARD_VERSION', $data['Version']); 22 define('PERFECTDASHBOARD_ADDWEBSITE_URL', 'https://app.perfectdashboard.co/my-websites/site-addchild'); 22 23 23 24 require_once PERFECTDASHBORD_PATH . '/class/perfectdashboard-class.php'; -
perfectdashboard/trunk/readme.txt
r1362686 r1376458 5 5 Requires at least: 3.5.0 6 6 Tested up to: 4.4.2 7 Stable tag: 1. 3.37 Stable tag: 1.4 8 8 License: GNU/GPL 9 9 License URI: http://www.gnu.org/licenses/gpl-3.0.html … … 59 59 Perfect Dashboard can fit into any workflow. With git integration you can easily include it into any staging process you have. This way, you can enjoy the benefits of Perfect Dashboard without the necessity to change the way your work is organized. 60 60 61 62 61 == Installation == 63 62 … … 65 64 2. **Activate the Perfect Dashboard plugin** through the Plugins menu in WordPress. 66 65 3. Go to **Perfect Dashboard** menu and click on **Click here to add your website to Perfect Dashboard** button. 67 4. Verify that the site URLs on [Perfect Dashboard](http ://app.perfectdashboard.co/index.html?utm_source=backend&utm_medium=installer&utm_campaign=WP "Manage WordPress, Joomla & other websites") are correct and **Add website** button.66 4. Verify that the site URLs on [Perfect Dashboard](https://app.perfectdashboard.co/?utm_source=backend&utm_medium=installer&utm_campaign=WP "Manage WordPress, Joomla & other websites") are correct and **Add website** button. 68 67 69 68 == Frequently Asked Questions == … … 88 87 89 88 == Changelog == 89 90 = 1.4.0 / 22-03-2016 = 91 92 * minor bug fixes 90 93 91 94 = 1.3.3 / 19-02-2016 = -
perfectdashboard/trunk/tmpl/tmpl-admin.php
r1357348 r1376458 1 1 <?php 2 2 /** 3 * @version 1. 2.03 * @version 1.4.0 4 4 * @package Perfect Dashboard 5 * @copyright © 201 5Perfect Web sp. z o.o., All rights reserved. http://www.perfect-web.co5 * @copyright © 2016 Perfect Web sp. z o.o., All rights reserved. http://www.perfect-web.co 6 6 * @license GNU/GPL http://www.gnu.org/licenses/gpl-3.0.html 7 7 * @author Perfect-Web … … 98 98 <?php endif; ?> 99 99 100 <form action=" https://app.perfectdashboard.co/my-websites/site-addchild?utm_source=backend&utm_medium=installer&utm_campaign=WP" method="post" enctype="multipart/form-data" id="perfect-dashboard-install">100 <form action="<?php echo PERFECTDASHBOARD_ADDWEBSITE_URL; ?>?utm_source=backend&utm_medium=installer&utm_campaign=WP" method="post" enctype="multipart/form-data" id="perfect-dashboard-install"> 101 101 <input type="hidden" name="secure_key" value="<?php echo $key; ?>"> 102 102 <input type="hidden" name="user_email" value="<?php echo $user_email; ?>">
Note: See TracChangeset
for help on using the changeset viewer.