<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[1715] sites/trunk/wordcamp.org/public_html/wp-content/plugins: WordCamp Site Cloner: Initial commit.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/1715">1715</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/1715","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>iandunn</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-07-08 22:57:41 +0000 (Wed, 08 Jul 2015)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>WordCamp Site Cloner: Initial commit.
Imported from https://github.com/ryelle/WordCamp-Style-Import/
Props ryelle, iandunn</pre>
<h3>Added Paths</h3>
<ul>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/</li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerincludessitecontrolphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/site-control.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerincludessitessectionphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/sites-section.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerincludessourcesiteidsettingphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/source-site-id-setting.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonertemplatessitecontrolphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/site-control.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonertemplatessitessectionphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/sites-section.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerwordcampsiteclonercss">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.css</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerwordcampsiteclonerjs">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerwordcampsiteclonerphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerincludessitecontrolphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/site-control.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/site-control.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/site-control.php 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,37 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+namespace WordCamp\Site_Cloner;
+
+defined( 'WPINC' ) or die();
+
+/**
+ * Custom Customizer Control for a WordCamp site
+ */
+class Site_Control extends \WP_Customize_Control {
+ public $site_id, $site_name, $screenshot_url, $theme_slug;
+ public $settings = 'wcsc_source_site_id';
+ public $section = 'wcsc_sites';
+
+ /**
+ * Enqueue scripts and styles
+ */
+ public function enqueue() {
+ wp_enqueue_style( 'wordcamp-site-cloner' );
+ wp_enqueue_script( 'wordcamp-site-cloner' );
+ }
+
+ /**
+ * Render the control's content
+ */
+ public function render_content() {
+ $preview_url = add_query_arg(
+ array(
+ 'theme' => rawurlencode( $this->theme_slug ),
+ 'wcsc_source_site_id' => rawurlencode( $this->site_id ),
+ ),
+ admin_url( 'customize.php' )
+ );
+
+ require( dirname( __DIR__ ) . '/templates/site-control.php' );
+ }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerincludessitessectionphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/sites-section.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/sites-section.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/sites-section.php 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,19 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+namespace WordCamp\Site_Cloner;
+
+defined( 'WPINC' ) or die();
+
+/**
+ * Custom Customizer Section for WordCamp sites
+ */
+class Sites_Section extends \WP_Customize_Section {
+ public $type = 'wcsc-sites';
+
+ /**
+ * Render the section's content
+ */
+ protected function render() {
+ require_once( dirname( __DIR__ ) . '/templates/sites-section.php' );
+ }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerincludessourcesiteidsettingphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/source-site-id-setting.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/source-site-id-setting.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/includes/source-site-id-setting.php 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,136 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+namespace WordCamp\Site_Cloner;
+
+defined( 'WPINC' ) or die();
+
+/**
+ * Customizer Setting for source site ID
+ *
+ * This isn't an actual setting that gets stored in the database, it's just a temporary value to track the ID of
+ * the site that that will be cloned. There are actually many data points that we'll import, but they don't fit
+ * into the default model that the Customizer expects.
+ */
+class Source_Site_ID_Setting extends \WP_Customize_Setting {
+ public $type = 'wcsc-source-site-id';
+ public $default = 0;
+ public $sanitize_callback = 'absint';
+ protected $preview_source_site_id;
+
+ /**
+ * Preview another site before it's imported
+ */
+ public function preview() {
+ if ( ! $this->preview_source_site_id = $this->manager->post_value( $this ) ) {
+ return;
+ }
+
+ add_action( 'wp_head', array( $this, 'preview_source_site_css' ), 99 ); // wp_print_styles is too early; the theme's stylesheet would get enqueued later and take precedence
+ add_filter( 'get_post_metadata', array( $this, 'preview_jetpack_postmeta' ), 10, 4 );
+ add_filter( 'safecss_skip_stylesheet', array( $this, 'preview_skip_stylesheet' ) );
+ }
+
+ /**
+ * Print the source site's custom CSS in an inline style block
+ *
+ * It can't be easily enqueued as an external stylesheet because Jetpack_Custom_CSS::link_tag() returns early
+ * in the Customizer if the theme being previewed is different from the live theme.
+ */
+ public function preview_source_site_css() {
+ if ( method_exists( '\Jetpack', 'get_module_path' ) ) {
+ require_once( \Jetpack::get_module_path( 'custom-css' ) );
+ } else {
+ return;
+ }
+
+ switch_to_blog( $this->preview_source_site_id );
+ printf( '<style id="wcsc-source-site-custom-css">%s</style>', \Jetpack_Custom_CSS::get_css( true ) );
+ restore_current_blog();
+ }
+
+ /**
+ * Overwrite the previewing site's Custom CSS settings with values from the source site
+ *
+ * @param mixed $pre_filter_value
+ * @param int $post_id
+ * @param string $meta_key
+ * @param bool $return_single_value
+ *
+ * @return mixed
+ */
+ public function preview_jetpack_postmeta( $pre_filter_value, $post_id, $meta_key, $return_single_value ) {
+ if ( ! in_array( $meta_key, array( 'content_width' ) ) ) {
+ return $pre_filter_value;
+ }
+
+ remove_filter( 'get_post_metadata', array( $this, 'preview_jetpack_postmeta' ), 10, 4 ); // avoid infinite recursion
+ switch_to_blog( $this->preview_source_site_id );
+
+ if ( $source_cite_css_post = \Jetpack_Custom_CSS::get_current_revision() ) {
+ $pre_filter_value = get_post_meta( $source_cite_css_post['ID'], $meta_key, $return_single_value );
+ }
+
+ restore_current_blog();
+ add_filter( 'get_post_metadata', array( $this, 'preview_jetpack_postmeta' ), 10, 4 );
+
+ return $pre_filter_value;
+ }
+
+ /**
+ * Determine whether or not to skip the primary stylesheet
+ *
+ * When the Custom CSS value for `Mode` is `Replacement`, Jetpack will prevent the primary stylesheet from
+ * being enqueued. We need to trigger that behavior based on the value on the source site, rather than the
+ * current site.
+ *
+ * This could be actually handled along with other Jetpack options in preview_jetpack_postmeta(), if it
+ * weren't for the fact that Jetpack_Custom_CSS::skip_stylesheet always returns false in the Previewer.
+ *
+ * @param bool $skip
+ *
+ * @return bool
+ */
+ public function preview_skip_stylesheet( $skip ) {
+ switch_to_blog( $this->preview_source_site_id );
+
+ if ( $source_cite_css_post = \Jetpack_Custom_CSS::get_current_revision() ) {
+ $skip = 'no' === get_post_meta( $source_cite_css_post['ID'], 'custom_css_add', true );
+ }
+
+ restore_current_blog();
+
+ return $skip;
+ }
+
+ /**
+ * Clone the source site into the current site
+ *
+ * If the theme needs to be switched, Core will do that for us because we added the `?theme=` parameter
+ * to the URL.
+ *
+ * @param int $source_site_id
+ */
+ protected function update( $source_site_id ) {
+ switch_to_blog( $source_site_id );
+
+ if ( ! $source_cite_css_post = \Jetpack_Custom_CSS::get_current_revision() ) {
+ restore_current_blog();
+ return;
+ }
+
+ $source_site_css = \Jetpack_Custom_CSS::get_css( false );
+ $source_site_preprocessor = get_post_meta( $source_cite_css_post['ID'], 'custom_css_preprocessor', true );
+ $source_site_mode = get_post_meta( $source_cite_css_post['ID'], 'custom_css_add', true );
+ $source_site_content_width = get_post_meta( $source_cite_css_post['ID'], 'content_width', true );
+
+ restore_current_blog();
+
+ \Jetpack_Custom_CSS::save( array(
+ 'css' => $source_site_css,
+ 'is_preview' => false,
+ 'preprocessor' => $source_site_preprocessor,
+ 'add_to_existing' => 'yes' === $source_site_mode ? true : false,
+ 'content_width' => $source_site_content_width,
+ ) );
+ }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonertemplatessitecontrolphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/site-control.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/site-control.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/site-control.php 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,15 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php defined( 'WPINC' ) or die(); ?>
+
+<div id="wcsc-site-<?php echo esc_attr( $this->site_id ); ?>" class="wcscSite" data-preview-url="<?php echo esc_url( $preview_url ); ?>">
+ <div class="wcsc-site-screenshot">
+ <img src="<?php echo esc_url( $this->screenshot_url ); ?>" alt="<?php echo esc_attr( $this->site_name ); ?>" />
+ </div>
+
+ <h3 class="wcsc-site-name">
+ <?php echo esc_html( $this->site_name ); ?>
+ </h3>
+
+ <span id="live-preview-label-<?php echo esc_attr( $this->site_id ); ?>" class="wcsc-live-preview-label">
+ <?php _e( 'Live Preview', 'wordcamporg' ); ?>
+ </span>
+</div>
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonertemplatessitessectionphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/sites-section.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/sites-section.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/templates/sites-section.php 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,15 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php defined( 'WPINC' ) or die(); ?>
+
+<li id="section-<?php echo esc_attr( $this->id ); ?>" class="accordion-section control-section control-section-<?php echo esc_attr( $this->type ); ?>">
+ <h3>
+ <?php esc_html_e( 'WordCamp Sites' ); ?>
+
+ <span class="title-count wcsc-sites-count">
+ <?php echo count( $this->controls ); ?>
+ </span>
+ </h3>
+
+ <div class="wcsc-sites-section-content">
+ <ul id="wcsc-sites"></ul>
+ </div>
+</li>
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerwordcampsiteclonercss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.css (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.css 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,43 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.control-section-wcsc-sites {
+ padding: 0 8px;
+}
+
+ #wcsc-sites {
+ overflow: auto;
+ }
+
+ .wcscSite {
+ position: relative;
+ cursor: pointer;
+ border: 1px solid #DEDEDE;
+ box-shadow: 0 1px 1px -1px rgba( 0, 0, 0, 0.1 );
+ }
+
+ .wcsc-site-screenshot {
+ transition: opacity 0.2s ease-in-out 0s;
+ }
+
+ .wcscSite:hover .wcsc-site-screenshot {
+ opacity: 0.4;
+ }
+
+ .wcsc-live-preview-label {
+ opacity: 0;
+ position: absolute;
+ top: 35%;
+ right: 25%;
+ left: 25%;
+ background: rgba( 0, 0, 0, 0.7 ) none repeat scroll 0 0;
+ color: #FFF;
+ font-size: 15px;
+ text-shadow: 0 1px 0 rgba( 0, 0, 0, 0.6 );
+ font-weight: 600;
+ padding: 15px 12px;
+ text-align: center;
+ border-radius: 3px;
+ transition: opacity 0.1s ease-in-out 0s;
+ }
+
+ .wcscSite:hover .wcsc-live-preview-label {
+ opacity: 1;
+ }
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerwordcampsiteclonerjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.js (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.js 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,99 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+( function( wp, $ ) {
+ 'use strict';
+
+ if ( ! wp || ! wp.customize ) {
+ return;
+ }
+
+ var api = wp.customize;
+
+ /**
+ * The Clone Another WordCamp panel
+ */
+ api.panelConstructor.wcscPanel = api.Panel.extend( {
+ /**
+ * Initialize the panel after it's loaded
+ *
+ * Ideally, the Previewer would be set to the requested site ID during the initial PHP request, rather than
+ * loading the host site in the Previewer, and then refreshing it to use the requested site. That became a
+ * rabbit hole, though, so it's done this way instead.
+ */
+ ready : function() {
+ var urlParams = getUrlParams( window.location.href );
+
+ if ( urlParams.hasOwnProperty( 'wcsc_source_site_id' ) ) {
+ this.expand();
+ api( 'wcsc_source_site_id' ).set( urlParams.wcsc_source_site_id );
+ }
+ }
+ } );
+
+ /**
+ * Custom control representing a site that can be previewed/imported
+ */
+ api.controlConstructor.wcscSite = api.Control.extend( {
+ /**
+ * Initialize the control after it's loaded
+ */
+ ready : function() {
+ this.container.on( 'click', '.wcscSite', this.previewSite );
+ },
+
+ /**
+ * Preview the selected site
+ *
+ * If the site is using a different theme, then reload the entire Customizer with the theme URL parameter
+ * set, so that the Theme Switcher will handle previewing the new theme for us. Otherwise just set the ID
+ * to refresh the Previewer with the current theme and the new site's CSS, etc.
+ *
+ * @param {object} event
+ */
+ previewSite : function( event ) {
+ var previewUrl = $( this ).data( 'preview-url' ),
+ previewUrlParams = getUrlParams( previewUrl );
+
+ if ( api( 'wcsc_source_site_id' ).get() == previewUrlParams.wcsc_source_site_id ) {
+ return;
+ }
+
+ if ( api.settings.theme.stylesheet === previewUrlParams.theme ) {
+ api( 'wcsc_source_site_id' ).set( previewUrlParams.wcsc_source_site_id );
+ } else {
+ window.parent.location = previewUrl;
+ }
+ }
+ } );
+
+ /**
+ * Parse the URL parameters
+ *
+ * Based on https://stackoverflow.com/a/2880929/450127
+ *
+ * @param {string} url
+ *
+ * @returns {object}
+ */
+ function getUrlParams( url ) {
+ var match, questionMarkIndex, query,
+ urlParams = {},
+ pl = /\+/g, // Regex for replacing addition symbol with a space
+ search = /([^&=]+)=?([^&]*)/g,
+ decode = function ( s ) {
+ return decodeURIComponent( s.replace( pl, " " ) );
+ };
+
+ questionMarkIndex = url.indexOf( '?' );
+
+ if ( -1 === questionMarkIndex ) {
+ return urlParams;
+ } else {
+ query = url.substring( questionMarkIndex + 1 );
+ }
+
+ while ( match = search.exec( query ) ) {
+ urlParams[ decode( match[ 1 ] ) ] = decode( match[ 2 ] );
+ }
+
+ return urlParams;
+ }
+} )( window.wp, jQuery );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampsiteclonerwordcampsiteclonerphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.php 2015-07-08 22:57:41 UTC (rev 1715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,176 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+namespace WordCamp\Site_Cloner;
+
+defined( 'WPINC' ) or die();
+
+/*
+Plugin Name: WordCamp Site Cloner
+Description: Allows organizers to clone another WordCamp's theme and custom CSS as a starting point for their site.
+Version: 0.1
+Author: WordCamp.org
+Author URI: http://wordcamp.org
+License: GPLv2 or later
+*/
+
+add_action( 'plugins_loaded', __NAMESPACE__ . '\get_wordcamp_sites' );
+add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\register_scripts' );
+add_action( 'customize_register', __NAMESPACE__ . '\register_customizer_components' );
+
+/**
+ * Register scripts and styles
+ */
+function register_scripts() {
+ wp_register_style(
+ 'wordcamp-site-cloner',
+ plugin_dir_url( __FILE__ ) . 'wordcamp-site-cloner.css',
+ array(),
+ 1
+ );
+
+ wp_register_script(
+ 'wordcamp-site-cloner',
+ plugin_dir_url( __FILE__ ) . 'wordcamp-site-cloner.js',
+ array( 'jquery', 'customize-controls' ),
+ 1,
+ true
+ );
+}
+
+/**
+ * Register our Customizer settings, panels, sections, and controls
+ *
+ * @param \WP_Customize_Manager $wp_customize
+ */
+function register_customizer_components( $wp_customize ) {
+ require_once( __DIR__ . '/includes/source-site-id-setting.php' );
+ require_once( __DIR__ . '/includes/sites-section.php' );
+ require_once( __DIR__ . '/includes/site-control.php' );
+
+ $wp_customize->register_control_type( __NAMESPACE__ . '\Site_Control' );
+
+ $wp_customize->add_setting( new Source_Site_ID_Setting(
+ $wp_customize,
+ 'wcsc_source_site_id',
+ array()
+ ) );
+
+ $wp_customize->add_panel(
+ 'wordcamp_site_cloner',
+ array(
+ 'type' => 'wcscPanel',
+ 'title' => __( 'Clone Another WordCamp', 'wordcamporg' ),
+ 'description' => __( "Clone another WordCamp's theme and custom CSS as a starting point for your site.", 'wordcamporg' ),
+ )
+ );
+
+ $wp_customize->add_section( new Sites_Section(
+ $wp_customize,
+ 'wcsc_sites',
+ array(
+ 'panel' => 'wordcamp_site_cloner',
+ 'title' => __( 'WordCamp Sites', 'wordcamporg' ),
+ )
+ ) );
+
+ foreach( get_wordcamp_sites() as $wordcamp ) {
+ if ( get_current_blog_id() == $wordcamp['site_id'] ) {
+ continue;
+ }
+
+ $wp_customize->add_control( new Site_Control(
+ $wp_customize,
+ 'wcsc_site_id_' . $wordcamp['site_id'],
+ array(
+ 'type' => 'wcscSite', // todo should be able to set this in control instead of here, but if do that then control contents aren't rendered
+ 'site_id' => $wordcamp['site_id'],
+ 'site_name' => $wordcamp['name'],
+ 'theme_slug' => $wordcamp['theme_slug'],
+ 'screenshot_url' => $wordcamp['screenshot_url'],
+ )
+ ) );
+ }
+}
+
+/**
+ * Get required data for relevant WordCamp sites
+ *
+ * This isn't actually used until register_customizer_components(), but it's called during `plugins_loaded` in
+ * order to prime the cache. That has to be done before `setup_theme`, because the Theme Switcher will override
+ * the current theme when `?theme=` is present in the URL parameters, and it's safer to just avoid that than to
+ * muck with the internals and try to reverse it on the fly.
+ *
+ * @return array
+ */
+function get_wordcamp_sites() {
+ // plugins_loaded is runs on every screen, but we only need this when loading the Customizer and Previewer
+ if ( 'customize.php' != basename( $_SERVER['SCRIPT_NAME'] ) && empty( $_REQUEST['wp_customize'] ) ) {
+ return array();
+ }
+
+ $transient_key = 'wcsc_sites';
+
+ if ( $sites = get_site_transient( $transient_key ) ) {
+ return $sites;
+ }
+
+ switch_to_blog( BLOG_ID_CURRENT_SITE ); // central.wordcamp.org
+
+ $sites = array();
+ $wordcamps = get_posts( array(
+ 'post_type' => 'wordcamp',
+ 'post_status' => 'publish',
+ 'posts_per_page' => 50, // todo temporary workaround until able to add filters to make hundreds of sites manageable
+ 'meta_key' => 'Start Date (YYYY-mm-dd)',
+ 'orderby' => 'meta_value_num',
+
+ 'meta_query' => array(
+ array(
+ 'key' => 'Start Date (YYYY-mm-dd)',
+ 'value' => strtotime( 'now - 1 month' ),
+ 'compare' => '<'
+ ),
+ ),
+ ) );
+
+ foreach( $wordcamps as $wordcamp ) {
+ $site_id = get_wordcamp_site_id( $wordcamp );
+ $site_url = get_post_meta( $wordcamp->ID, 'URL', true );
+
+ if ( ! $site_id || ! $site_url ) {
+ continue;
+ }
+
+ switch_to_blog( $site_id );
+
+ $sites[] = array(
+ 'site_id' => $site_id,
+ 'name' => get_wordcamp_name(),
+ 'theme_slug' => get_stylesheet(),
+ 'screenshot_url' => get_screenshot_url( $site_url ),
+ );
+
+ restore_current_blog();
+ }
+
+ restore_current_blog();
+
+ set_site_transient( $transient_key, $sites, DAY_IN_SECONDS );
+
+ return $sites;
+}
+
+/**
+ * Get the mShot URL for the given site URL
+ *
+ * Allow it to be filtered so that production URLs can be changed to match development URLs in local environments.
+ *
+ * @param string $site_url
+ *
+ * @return string
+ */
+function get_screenshot_url( $site_url ) {
+ $screenshot_url = add_query_arg( 'w', 275, 'https://www.wordpress.com/mshots/v1/' . rawurlencode( $site_url ) );
+
+ return apply_filters( 'wcsc_site_screenshot_url', $screenshot_url );
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-site-cloner/wordcamp-site-cloner.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:executable</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+*
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span></div>
</body>
</html>