PageRenderTime 25ms CodeModel.GetById 2ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

/wp-content/plugins/one-click-child-theme/one-click-child-theme.php

https://gitlab.com/eita/encontre-consumo-responsavel
PHP | 686 lines | 450 code | 25 blank | 211 comment | 30 complexity | 0ef8befb1406140309034384df494845 MD5 | raw file
  1<?php
  2/*
  3**************************************************************************
  4
  5Plugin Name:  One-Click Child Theme
  6Plugin URI:   http://terrychay.com/wordpress-plugins/one-click-child-theme
  7Version:      1.6
  8Description:  Easily child theme any theme from wp-admin wp-admin without going into shell or using FTP.
  9Author:       tychay
 10Author URI:   http://terrychay.com/
 11License:      GPLv2 or later
 12License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 13Text Domain:  one-click-child-theme
 14Domain Path: /languages
 15
 16**************************************************************************/
 17/*  Copyright 2011-2015  terry chay  (email : tychay@php.net)
 18
 19    This program is free software; you can redistribute it and/or modify
 20    it under the terms of the GNU General Public License, version 2, as 
 21    published by the Free Software Foundation.
 22
 23    This program is distributed in the hope that it will be useful,
 24    but WITHOUT ANY WARRANTY; without even the implied warranty of
 25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 26    GNU General Public License for more details.
 27
 28    You should have received a copy of the GNU General Public License
 29    along with this program; if not, write to the Free Software
 30    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 31*/
 32/*
 33 * Performance: One-Click Child Theme is only active in admin page
 34 */
 35if (!is_admin()) { return; }
 36/**
 37* Load textdomain
 38 */
 39function _load_textdomain() {
 40	load_plugin_textdomain( 'one-click-child-theme', false, basename(dirname(__FILE__)) . '/languages' );
 41}
 42add_action( 'init', '_load_textdomain' );
 43/**
 44 * The namespace for the One-Click Child Theme Plugin
 45 */
 46class OneClickChildTheme {
 47	/**
 48	 * @const string Used for id generation and language text domain.
 49	 */
 50	const _SLUG = 'one-click-child-theme';
 51	/**
 52	 * Used for loading in files
 53	 * @var string
 54	 */
 55	private $_pluginDir = '';
 56	/**
 57	 * This plugin's theme page
 58	 */
 59	private $_themePageUrl = '';	
 60	/**
 61	 * Theme page name (menu slug)
 62	 * @var string
 63	 */
 64	private $_menuId = '';
 65	/**
 66	 * action for Create Child form
 67	 */
 68	private $_createChildFormId = '';
 69	/**
 70	 * action for Repair Child form
 71	 */
 72	private $_repairChildFormId = '';
 73	/**
 74	 * action for Copy Template form
 75	 */
 76	private $_copyTemplateFormId = '';
 77	/**
 78	 * action for screenshot generation
 79	 */
 80	private $_mshotSiteFormId = '';
 81
 82	public function __construct() {
 83		$this->_pluginDir          = dirname(__FILE__);
 84		$this->_menuId             = self::_SLUG . '-page';
 85		$this->_themePageUrl       = admin_url('themes.php?page='.$this->_menuId);
 86		$this->_createChildFormId  = self::_SLUG.'-create-child';
 87		$this->_repairChildFormId  = self::_SLUG.'-repair-child';
 88		$this->_copyTemplateFormId = self::_SLUG.'-copy-template';
 89		$this->_mshotSiteFormId    = self::_SLUG.'-mshot-site';
 90
 91		// it has to be buried like this or you get an error:
 92		//  "You do not have sufficient permissions to access this page"
 93		add_action( 'admin_menu', array($this,'createAdminMenu') );
 94
 95		// form handling code	
 96		add_action( 'admin_post_'.$this->_createChildFormId, array($this,'processCreateForm') );
 97		add_action( 'admin_post_'.$this->_repairChildFormId, array($this,'processRepairChildForm') );
 98		add_action( 'admin_post_'.$this->_copyTemplateFormId, array($this,'processCopyTemplateForm') );
 99		add_action( 'admin_post_'.$this->_mshotSiteFormId, array($this,'processMShotSiteForm') );
100		// TODO: I could also use the $pagenow global, but is it still there?
101		if ( basename($_SERVER['PHP_SELF']) == 'themes.php' && !empty($_REQUEST['occt_error']) ) {
102			add_action( 'admin_notices', array($this,'showErrorNotice'));
103		}
104	}
105	/**
106	 * Handle error and update notices for this theme
107	 *
108	 * There are now four types of notices: success (green), warning (orange), error (red),
109	 * and info (blue).
110	 * 
111	 * Put here because there is a redirect between all forms and error notifications and
112	 * add_settings_error() only covers options API errors.
113	 */
114	public function showErrorNotice()
115	{
116		switch ($_GET['occt_error']) {
117			case 'child_created': //SUCCESS: child theme created
118				$type = 'updated'; //fade?
119				$msg = sprintf(
120					__('Theme switched! <a href="%s">Click here to edit the child stylesheet</a>.', self::_SLUG),
121					add_query_arg(
122						urlencode_deep(array(
123							'file'  => 'style.css',
124							'theme' => get_stylesheet(),
125						)),
126						admin_url('theme-editor.php')
127					)
128				);
129				break;
130			case 'create_failed': //ERROR: create file failed (probably due to permissions)
131				$type = 'error';
132				$msg = sprintf(
133					__('Failed to create file: %s', self::_SLUG),
134					esc_html($_GET['filename'])
135				);
136				break;
137			case 'edit_failed': //ERROR: edit file failed (probably do to permissions)
138				$type = 'error';
139				$msg = sprintf(
140					__('Failed to edit file: %s', self::_SLUG),
141					esc_html($_GET['filename'])
142				);
143				break;
144			case 'repair_success': //SUCCESS: repaired child theme
145				$type = 'updated fade';
146				$msg = __('Repaired child theme.', self::_SLUG);
147				break;
148			case 'no_template': //ERROR: template file not specified
149				$type = 'error';
150				$msg = __('No template file specified.', self::_SLUG);
151			case 'missing_template': //ERROR: parent theme doesn't have template
152				$type = 'error';
153				$msg = sprintf(
154					__('Template file %s does not exist in parent theme!', self::_SLUG),
155					esc_html($_GET['filename'])
156				);
157				break;
158			case 'already_template': //ERROR: child theme already has template
159				$type = 'error';
160				$msg = sprintf(
161					__('Template file %s already exists in child theme!', self::_SLUG),
162					esc_html($_GET['filename'])
163				);
164				break;
165			case 'copy_failed': //ERROR: couldn't duplicate file for some reason
166				$type = 'error';
167				$msg = sprintf(
168					__('Failed to duplicate file %s!', self::_SLUG),
169					esc_html($_GET['filename'])
170				);
171				break;
172			case 'copy_success': //SUCCESS: template file created
173				$type = 'updated'; //fade?
174				$msg = sprintf(
175					__('<a href="%s">File %s created!</a>', self::_SLUG),
176					add_query_arg(
177						urlencode_deep(array(
178							'file'  => $_GET['filename'],
179							'theme' => get_stylesheet(),
180						)),
181						admin_url('theme-editor.php')
182					),
183					esc_html($_GET['filename'])
184				);
185				break;
186			case 'delete_failed': //ERROR: couldn't delete file for some reason
187				$type = 'error';
188				$msg = sprintf(
189					__('Failed to delete file %s!', self::_SLUG),
190					esc_html($_GET['filename'])
191				);
192				break;
193			case 'mshot_404': //ERROR: couldn't find mshot
194				$type = 'error';
195				$msg = sprintf(
196					__('404 File not found at %s!', self::_SLUG),
197					esc_html($_GET['url'])
198				);
199				break;
200			case 'mshot_mime_wrong': //ERROR: couldn't find mshot
201				$type = 'error';
202				$msg = sprintf(
203					__('Unrecognized mimetype at %s!', self::_SLUG),
204					esc_html($_GET['url'])
205				);
206				break;
207			case 'mshot_nocreate': //ERROR: couldn't find mshot
208				$type = 'error';
209				$msg = sprintf(
210					__('Failed to create file %s!', self::_SLUG),
211					esc_html($_GET['filename'])
212				);
213				break;
214			case 'mshot_success': //SUCCESS: screenshot generated
215				$type = 'updated fade'; //fade?
216				$msg = __('Successfully changed screenshot.', self::_SLUG);
217				break;
218			default: //ERROR: it is a generic error message
219				$type = 'error';
220				$msg = esc_html($_GET['occt_error']);
221		}
222		printf(
223			'<div class="%s"><p>%s</p></div>',
224			$type,
225			$msg
226		);
227	}
228	/**
229	 * Adds an admin menu for One Click Child Theme in Appearances
230	 */
231	public function createAdminMenu() {
232		add_theme_page(
233			__('Make a Child Theme', self::_SLUG), //page title
234			__('Child Theme', self::_SLUG), //menu title
235			'install_themes', //capability needed to view
236			$this->_menuId, //menu slug (and page query url)
237			array( $this, 'showThemePage' ) //callback function
238			);
239	}
240	//
241	// SHOW THEME PAGE
242	// 
243	/**
244	 * Show the theme page which has a form allowing you to child theme
245	 * currently selected theme.
246	 *
247	 */
248	public function showThemePage()
249	{
250		// Form is processed in the admin_post_* hooks
251		
252		// Handle case where current theme is already a child
253		if ( is_child_theme() ) {
254			$this->_showFormAlreadyChild( $this->_child_theme_needs_repair() );
255			return;
256		}
257
258		// Default behavior: We are not a child theme, but interested in creating one.
259		// Grab default values from a form fail
260		$theme_name = ( !empty($_GET['theme_name']) ) ? $_GET['theme_name'] : '';
261		$description = ( !empty($_GET['description']) ) ? $_GET['description'] : '';
262		if ( !empty($_GET['author_name']) ) {
263			$author = $_GET['author_name'];
264		} else {
265			global $current_user;
266			get_currentuserinfo();
267			$author = $current_user->display_name;
268		}
269		// render default behaivor
270		require $this->_pluginDir.'/templates/create_child_form.php';
271	}
272
273	/**
274	 * Show the "is child already" template.
275	 * @param  boolean $child_needs_repair whether or not child theme needs repair
276	 * @todo  handle grandchildren
277	 */
278	private function _showFormAlreadyChild($child_needs_repair) {
279		// set template parameters
280		$current_theme = wp_get_theme();
281		$child_theme_screenshot_url = ( $screenshot_filename = $this->_scanForScreenshot( get_stylesheet_directory() ) )
282			? get_stylesheet_directory_uri().'/'.$screenshot_filename
283			: '';
284		$mshot_url = $this->_mshotUrl();
285		// Search for template files.
286		// Note: since there can be files like {mimetype}.php, we must assume
287		// that any root level .php files in the template directory are
288		// templates.
289		$template_files = glob ( get_template_directory().'/*.php' );
290		foreach ( $template_files as $index=>$file ) {
291			$template_files[$index] = basename( $file );
292		}
293		// Filter out any files in child already created
294		$child_theme_dir = get_stylesheet_directory();
295		foreach ( $template_files as $index=>$filename ) {
296			if ( file_exists($child_theme_dir.'/'.$filename) ) {
297				unset($template_files[$index]);
298			}
299		}
300		require $this->_pluginDir.'/templates/is_child_already.php';
301	}
302	//
303	// FORM HANDLING
304	// 
305	/**
306	 * Handle the create child form.
307	 */
308	public function processCreateForm() {
309		check_admin_referer( $this->_createChildFormId . '-verify' );
310		$theme_name = $_POST['theme_name'];
311		$description = ( empty($_POST['description']) )
312			? ''
313			: $_POST['description'];
314		$author_name = ( empty($_POST['author_name']) )
315			? ''
316			: $_POST['author_name'];
317		$result = $this->_make_child_theme( $theme_name, $description, $author_name );
318		if ( is_wp_error( $result ) ) {
319			// should show create child form again
320			$this->_redirect(
321				$this->_themePageUrl,
322				$result->get_error_message(),
323				array(
324					'theme_name'  => $theme_name,
325					'description' => $description,
326					'author_name' => $author_name,
327				)
328			);
329			return;
330		} else {
331			switch_theme( $result['parent_template'], $result['new_theme'] );
332			// Redirect to themes page on success
333			$this->_redirect(
334				admin_url('themes.php'),
335				'child_created'
336			);
337		}
338	}
339	/**
340	 * Handle the repair_child_form form.
341	 */
342	public function processRepairChildForm()
343	{
344		check_admin_referer( $this->_repairChildFormId . '-verify' );
345		$child_theme_dir = get_stylesheet_directory();
346		$functions_file = $child_theme_dir.'/functions.php';
347		$style_file = $child_theme_dir.'/style.css';
348
349		// create functions.php if it doesn't exist yet
350		if ( !file_exists($functions_file) ) {
351			if ( !touch($functions_file) ) {
352				// fixing is hopeless if we can't create the file :-(
353				$this->_redirect(
354					$this->_themePageUrl,
355					'create_failed',
356					array( 'filename' => $functions_file )
357				);
358				return;
359			}
360		}
361
362		// read in style.css
363		$style_text = file_get_contents( $style_file );
364		// prune out old rules
365		$style_text = preg_replace(
366			'!@import\s+url\(\s?["\']\.\./.*/style.css["\']\s?\);!ims',
367			'',
368			$style_text
369		);
370		$style_text = preg_replace(
371			'!@import\s+url\(\s?["\']'.get_template_directory_uri().'/style.css["\']\s?\);!ims',
372			'',
373			$style_text
374		);
375		if ( file_put_contents( $style_file, $style_text) === false )	 {
376			$this->_redirect(
377				$this->_themePageUrl,
378				'edit_failed',
379				array( 'filename' => $style_file )
380			);
381			return;
382		}
383
384		// modify functions.php to prepend new rules
385		$functions_text = file_get_contents( $this->_pluginDir.'/templates/functions.php' );
386		// ^^^ above file has no final carriage return and ending comment so it should
387		// "smash" the starting '<?php' string in any existing functions.php.
388		$functions_text .= file_get_contents( $functions_file );
389		if ( file_put_contents( $functions_file, $functions_text ) === false ) {
390			$this->_redirect(
391				$this->_themePageUrl,
392				'edit_failed',
393				array( 'filename' => $functions_file )
394			);
395			return;
396		}
397		$this->_redirect(
398			$this->_themePageUrl,
399			'repair_success'
400		);
401	}
402	/**
403	 * Handle the Copy Template form.
404	 */
405	public function processCopyTemplateForm() {
406		check_admin_referer( $this->_copyTemplateFormId . '-verify' );
407		$filename = ( empty($_POST['filename']) )
408			? ''
409			: $_POST['filename'];
410		if ( !$filename ) {
411			$this->_redirect(
412				$this->_themePageUrl,
413				'no_template'
414			);
415			return;
416		}
417		$child_theme_dir = get_stylesheet_directory();
418		$template_dir = get_template_directory();
419				var_dump('bar');
420		if ( !file_exists($template_dir.'/'.$filename) ) {
421			$this->_redirect(
422				$this->_themePageUrl,
423				'missing_template',
424				array( 'filename' => $filename )
425			);
426			return;
427		}
428		if ( file_exists($child_theme_dir.'/'.$filename) ) {
429			$this->_redirect(
430				$this->_themePageUrl,
431				'already_template',
432				array( 'filename' => $filename )
433			);
434			return;
435		}
436		if ( !copy( $template_dir.'/'.$filename, $child_theme_dir.'/'.$filename ) ) {
437			$this->_redirect(
438				$this->_themePageUrl,
439				'copy_failed',
440				array( 'filename' => $filename )
441			);
442		}
443		$this->_redirect(
444			$this->_themePageUrl,
445			'copy_success',
446			array( 'filename' => $filename )
447		);
448	}
449	/**
450	 * Handle the mshot Screenshot form
451	 */
452	public function processMShotSiteForm()
453	{
454		check_admin_referer( $this->_mshotSiteFormId . '-verify' );
455
456		// delete existing screenshot if it exists
457		$child_theme_dir = get_stylesheet_directory();
458		if ( $screenshot_filename = $this->_scanForScreenshot($child_theme_dir) ) {
459			$screenshot_path = $child_theme_dir.'/'.$screenshot_filename;
460			if ( !unlink($screenshot_path) ) {
461				// most likely a directory problem Fail with an error
462				$this->_redirect(
463					$this->_themePageUrl,
464					'delete_failed',
465					array( 'filename' => $screenshot_path )
466				);
467				return;
468			}
469		}
470
471		$mshot_url = $this->_mshotUrl();
472		// Get the mshot
473		$response = wp_remote_get($mshot_url);
474
475		if ( $response['code'] == 404 ) {
476			// The 404 image is gorgeous nowadays, but (if wp.com correctly handled error
477			// codes for image generation) we'd not let them use it as a theme screenshot.
478			$this->_redirect(
479				$this->_themePageUrl,
480				'mshot_404',
481				array( 'url' => $mshot_url )
482			);
483		}
484		// Should be 'image/jpeg', but let's hedge our bets
485		switch ($response['headers']['content-type']) {
486			case 'image/jpeg':
487				$screenshot_filename = 'screenshot.jpg';
488				break;
489			case 'image/png':
490				$screenshot_filename = 'screenshot.png';
491				break;
492			case 'image/gif':
493				$screenshot_filename = 'screenshot.gif';
494				break;
495			default:
496				$this->_redirect(
497					$this->_themePageUrl,
498					'mshot_mime_wrong',
499					array( 'url' => $mshot_url )
500				);
501				return;
502		}
503		$screenshot_path = $child_theme_dir.'/'.$screenshot_filename;
504		if ( file_put_contents($screenshot_path, $response['body']) === false ) {
505			$this->_redirect(
506				$this->_themePageUrl,
507				'mshot_nocreate',
508				array( 'filename' => $screenshot_path )
509			);
510			return;
511		}
512
513		$this->_redirect(
514			$this->_themePageUrl,
515			'mshot_success'
516		);
517	}
518
519	//
520	// PRIVATE METHOD
521	//
522	/**
523	 * Does the work to make a child theme based on the current theme.
524	 *
525	 * This currently supports the following files:
526	 *
527	 * 1. style.css: Follows the rules outlined in {@link http://codex.wordpress.org/Child_Themes the Codex}
528	 * 2. functions.php: Followed the updated rules outlined in the Codex. Note
529	 * 	  that since WordPress ?.? functions.php hierarchy is automatically
530	 * 	  included.
531	 * 3. rtl.css: right to left language support, if not avaialble in parent, it
532	 *    uses TwentyFifteen's rtl
533	 * 4. screenshot.png: screenshot if available in the parent
534	 *
535	 * @author terry chay <tychay@autoamttic.com>
536	 * @author Chris Robinson <http://contempographicdesign.com/> (for screenshot support).
537	 * @return array|WP_Error If successful, it returns a hash contianing
538	 * - new_theme: (directory) name of new theme
539	 * - parent_template: (directory) name of parent template
540	 * - parent_theme: (directory) name of parent theme
541	 * - new_theme_path: full path to the directory cotnaining the new theme
542	 * - new_theme_title: the name of the new theme
543	 */
544	private function _make_child_theme( $new_theme_title, $new_theme_description, $new_theme_author ) {
545		$parent_theme_title = get_current_theme();
546		$parent_theme_template = get_template(); //Doesn't play nice with the grandkids
547		$parent_theme_name = get_stylesheet();
548		$parent_theme_dir = get_stylesheet_directory();
549
550		// Turn a theme name into a directory name
551		$new_theme_name = sanitize_title( $new_theme_title );
552		$theme_root = get_theme_root();
553
554		// Validate theme name
555		$new_theme_path = $theme_root.'/'.$new_theme_name;
556		if ( file_exists( $new_theme_path ) ) {
557			return new WP_Error( 'exists', __( 'Theme directory already exists!', self::_SLUG ) );
558		}
559
560		mkdir( $new_theme_path );
561
562		// Make style.css
563		ob_start();
564		require $this->_pluginDir.'/templates/child-theme-css.php';
565		$css = ob_get_clean();
566		file_put_contents( $new_theme_path.'/style.css', $css );
567
568		// "Generate" functions.php 
569		copy( $this->_pluginDir.'/templates/functions.php', $new_theme_path.'/functions.php' );
570
571		// RTL support
572		$rtl_theme = ( file_exists( $parent_theme_dir.'/rtl.css' ) )
573			? $parent_theme_name
574			: 'twentyfifteen'; //use the latest default theme rtl file
575		ob_start();
576		require $this->_pluginDir.'/templates/rtl-css.php';
577		$css = ob_get_clean();
578		file_put_contents( $new_theme_path.'/rtl.css', $css );
579
580		// Copy screenshot
581		if ( $screenshot_filename = $this->_scanForScreenshot( $parent_theme_dir ) ) {
582			copy(
583				$parent_theme_dir.'/'.$screenshot_filename,
584				$new_theme_path.'/'.$screenshot_filename
585			);
586		} // removed grandfather screenshot check (use mshot instead, rly)
587
588		// Make child theme an allowed theme (network enable theme)
589		$allowed_themes = get_site_option( 'allowedthemes' );
590		$allowed_themes[ $new_theme_name ] = true;
591		update_site_option( 'allowedthemes', $allowed_themes );
592
593		return array(
594			'parent_template'    => $parent_theme_template,
595			'parent_theme'       => $parent_theme_name,
596			'new_theme'          => $new_theme_name,
597			'new_theme_path'     => $new_theme_path,
598			'new_theme_title'	 => $new_theme_title,
599		);
600	}
601	//
602	// PRIVATE UTILITY FUNCTIONS
603	// 
604	/**
605	 * Detect if child theme needs repair.
606	 *
607	 * A child theme needs repair if it is missing a functions.php or the
608	 * style.css still has a rule that points to the parent.
609	 */
610	private function _child_theme_needs_repair()
611	{
612		$child_theme_dir = get_stylesheet_directory();
613		if ( !file_exists($child_theme_dir.'/functions.php') ) {
614			return true;
615		}
616		$style_text = file_get_contents( $child_theme_dir.'/style.css' );
617		// look for relative match (dificult to extract parent theme directory
618		// so I'll assume any in this path is parent theme)
619		if ( preg_match(
620			'!@import\s+url\(\s?["\']\.\./.*/style.css["\']\s?\);!ims',
621			$style_text
622			) ) {
623			return true;
624		}
625		// look for absolute match
626		if ( preg_match(
627			'!@import\s+url\(\s?["\']'.get_template_directory_uri().'/style.css["\']\s?\);!ims',
628			$style_text
629			) ) {
630			return true;
631		}
632		return false;
633	}
634	/**
635	 * Handle error redirects (for admin_notices generated by plugin)
636	 *
637	 * Note add_query_arg() is written like shit. Here are it's problems:
638	 * 
639	 * 1. doesn't take advantage of built-in parse_url()
640	 * 2. uses urlencode_deep() instead of an array_merge and built-in http_build_query()
641	 * 3. doesn't urlencode() if $arg[0] is an array.
642	 * 
643	 * The 3rd one is extremely non-intuitive, but fixing it, would break backward
644	 * compatibility due to double-escaping. I'm hacking around that. :-(
645	 * 
646	 * @param  string $url   The (base) url to redirect to, usually admin_url()
647	 * @param  string $error the error code to use
648	 * @param  string $args  other arguments to add to the query string
649	 * @return null
650	 */
651	private function _redirect($url, $error, $args = array()) {
652		$args['occt_error'] = $error;
653		$args = urlencode_deep($args);
654		wp_redirect( add_query_arg( $args, $url ) );
655	}
656	/**
657	 * Searches directory for a theme screenshot
658	 * 
659	 * @param  string $directory directory to search (a theme directory)
660	 * @return string|false 'screenshot.png' (or whatever) or false if there is no screenshot
661	 */
662	private function _scanForScreenshot($directory)
663	{
664		$screenshots = glob( $directory.'/screenshot.{png,jpg,jpeg,gif}', GLOB_BRACE );
665		return (empty($screenshots)) 
666			? false
667			: basename($screenshots[0]);
668	}
669	/**
670	 * Generate mshot of wordpress homepage.
671	 *
672	 * Recommende image dimensions from https://codex.wordpress.org/Theme_Development#Screenshot
673	 * @todo  probably won't work correctly in multisite installs
674	 * @todo  remove debugging code
675	 */
676	private function _mshotUrl()
677	{
678		$scheme = (is_ssl()) ? 'https' : 'http';
679		return $scheme . '://s.wordpress.com/mshots/v1/'. urlencode(get_site_url()) . '?w=880&h=660';
680	}
681
682}
683
684new OneClickChildTheme();
685// Start this plugin
686//add_action( 'admin_init', array('OneClickChildTheme','init'), 12 );