<!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>[3274] sites/trunk/wordcamp.org/public_html/wp-content/plugins: WordCamp Docs: Move plugin to Meta from private repository.</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/3274">3274</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/3274","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>2016-05-31 16:39:47 +0000 (Tue, 31 May 2016)</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 Docs: Move plugin to Meta from private repository.</pre>

<h3>Added Paths</h3>
<ul>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/</li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocsclassesclasswordcampdocspdfgeneratorphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/class-wordcamp-docs-pdf-generator.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocsclassesclasswordcampdocstemplatephp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/class-wordcamp-docs-template.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocsclassesclasswordcampdocsphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/class-wordcamp-docs.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/</li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/assets/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocstemplatesassetslogopng">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/assets/logo.png</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocstemplatesspeakerinvitationphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/speaker-invitation.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocswordcampdocsphp">sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/wordcamp-docs.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocsclassesclasswordcampdocspdfgeneratorphp"></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-docs/classes/class-wordcamp-docs-pdf-generator.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-docs/classes/class-wordcamp-docs-pdf-generator.php                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/class-wordcamp-docs-pdf-generator.php 2016-05-31 16:39:47 UTC (rev 3274)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,168 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Helper class to generate PDFs from HTML strings or files using wkhtmltopdf.
+ *
+ * Thanks to Viper007Bond ( http://www.viper007bond.com )
+ */
+class WordCamp_Docs_PDF_Generator {
+
+       /**
+        * Full path to your tmp folder where files should be created. Include a trailing slash.
+        * You should probably just leave this as "/tmp/" as you should move your PDF on your own.
+        *
+        * @var string
+        */
+       public $tmp_folder_base = '/tmp/';
+
+       /**
+        * Stores a unique folder name that the class instance will work out of.
+        * Generated dynamically using uniqid().
+        *
+        * @var string
+        */
+       public $working_folder_name;
+
+       /**
+        * Constructor. No parameters.
+        */
+       function __construct() {
+               $this->working_folder_name = uniqid( 'wcdocs_' );
+       }
+
+       /**
+        * Generates a PDF from a string of HTML.
+        *
+        * @param string $string   A string of HTML.
+        * @param string $filename Filename of the PDF, including the extension.
+        * @param array  $args     Optional. An associative array of additional parameters.
+        *                         assets:  optional array of full paths to local assets (images for example).
+        *                         dpi:     optional integer to be passed directly to wkhtmltopdf.
+        *                         margins: optional array of 4 integers specifying PDF margins. Top, right, bottom, left.
+        *
+        * @return string The path to the generated PDF.
+        */
+       public function generate_pdf_from_string( $string, $filename, $args = array() ) {
+               $file = $this->write_file( $filename . '.html', $string );
+               return $this->generate_pdf_from_file( $file, $filename, $args );
+       }
+
+       /**
+        * Generates a PDF from an HTML file.
+        *
+        * @param string  $source_file Full path to the HTML file.
+        * @param  string $filename    Filename of the PDF, including the extension.
+        * @param array   $args        Optional. An associative array of additional parameters.
+        *                             assets:  optional array of full paths to local assets (images for example).
+        *                             dpi:     optional integer to be passed directly to wkhtmltopdf.
+        *                             margins: optional array of 4 integers specifying PDF margins. Top, right, bottom, left.
+        *
+        * @return string The path to the generated PDF.
+        */
+       public function generate_pdf_from_file( $source_file, $filename, $args = array() ) {
+               if ( ! empty( $args['assets'] ) && is_array( $args['assets'] ) ) {
+                       foreach ( $args['assets'] as $asset ) {
+                               copy( $asset, $this->get_tmp_folder( basename( $asset ) ) );
+                       }
+               }
+
+               $dpi = ( ! empty( $args['dpi'] ) ) ? absint( $args['dpi'] ) : 300;
+
+               $margins = ( ! empty( $args['margins'] ) && is_array( $args['margins'] ) && 4 == count( $args['margins'] ) ) ? $args['margins'] : array( 0, 0, 0, 0 );
+
+               $file = $this->get_tmp_folder( $filename );
+
+               $command = sprintf(
+                       'wkhtmltopdf -d %d -T %s -R %s -B %s -L %s %s %s',
+                       $dpi,
+                       escapeshellarg( $margins[0] ),
+                       escapeshellarg( $margins[1] ),
+                       escapeshellarg( $margins[2] ),
+                       escapeshellarg( $margins[3] ),
+                       escapeshellarg( $source_file ),
+                       escapeshellarg( $file )
+               );
+
+               exec( $command );
+
+               return $file;
+       }
+
+       /**
+        * Serves a file from the tmp folder up to the browser.
+        * Does NOT exit when finished so that you can still call
+        * A8C_PDF_Generator::delete_tmp_folder() when you're all done.
+        *
+        * @param string $filename The filename within this instance's temporary folder to serve up.
+        * @param bool $download Whether to prompt downloading or serve it natively within the browser.
+        */
+       public function serve_pdf_to_browser( $filename, $download = false ) {
+               $filename = basename( $filename );
+
+               $file = $this->get_tmp_folder( $filename );
+
+               nocache_headers();
+
+               if ( ! file_exists( $file ) ) {
+                       status_header( 404 );
+                       echo 'File not found.';
+               }
+
+               header( 'Content-Type: application/pdf' );
+
+               if ( $download ) {
+                       header( 'Content-Disposition: attachment; filename="' . esc_attr( $filename ) . '"' );
+               }
+
+               echo file_get_contents( $file );
+       }
+
+       /**
+        * Writes out a file to this instance's temporary file.
+        *
+        * @param string $filename The filename (not the path) that should be written to.
+        * @param string $data The contents of the file, such as HTML.
+        *
+        * @return string The full path to the newly created file.
+        */
+       public function write_file( $filename, $data ) {
+               if ( ! is_dir( $this->get_tmp_folder() ) ) {
+                       mkdir( $this->get_tmp_folder() );
+               }
+
+               $path = $this->get_tmp_folder( $filename );
+
+               file_put_contents( $path, $data );
+
+               return $path;
+       }
+
+       /**
+        * Returns the path to this instance's temporary folder.
+        * Optionally you can include a filename that will be relative to that path.
+        *
+        * @param string $filename Optional. Filename to be appended onto the end of the path.
+        *
+        * @return string Full path to the temporary folder or file.
+        */
+       public function get_tmp_folder( $filename = '' ) {
+               return trailingslashit( $this->tmp_folder_base ) . $this->working_folder_name . '/' . $filename;
+       }
+
+       /**
+        * Run this when you're all done. Deletes the instance's temporary folder and all files within it.
+        * You should make sure to move the generated PDF out of the folder first.
+        *
+        * @return bool True on success or false on failure.
+        */
+       public function delete_tmp_folder() {
+               $tmp_folder = $this->get_tmp_folder();
+
+               $files = array_diff( scandir( $tmp_folder ), array( '.', '..' ) );
+
+               foreach ( $files as $file ) {
+                       unlink( $tmp_folder . $file );
+               }
+
+               return rmdir( $tmp_folder );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocsclassesclasswordcampdocstemplatephp"></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-docs/classes/class-wordcamp-docs-template.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-docs/classes/class-wordcamp-docs-template.php                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/class-wordcamp-docs-template.php      2016-05-31 16:39:47 UTC (rev 3274)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,46 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Make sure your custom template implements this interface.
+ */
+interface WordCamp_Docs_Template {
+
+       /**
+        * This is the name that will be displayed in the WordCamp Docs UI.
+        */
+       public function get_name();
+
+       /**
+        * This is the PDF filename which will be used when serving the
+        * generated PDF file to the browser.
+        */
+       public function get_filename();
+
+       /**
+        * This function will be called with POST data. It should render a
+        * form for the WordCamp Docs UI.
+        *
+        * @param array $data POST-ed data (if any)
+        */
+       public function form( $data );
+
+       /**
+        * This function is called with the POST-ed data, should return
+        * clean input.
+        *
+        * @param array $input POST-ed data.
+        */
+       public function sanitize( $input );
+
+       /**
+        * This function is called when generating a PDF, should return
+        * HTML and CSS. You can use ob_* functions for convenience.
+        *
+        * @param array $input POST-ed and self::sanitized() data.
+        */
+       public function render( $data );
+
+       /**
+        * This function should return an array of absolute paths to assets.
+        */
+       public function get_assets();
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocsclassesclasswordcampdocsphp"></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-docs/classes/class-wordcamp-docs.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-docs/classes/class-wordcamp-docs.php                             (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/classes/class-wordcamp-docs.php       2016-05-31 16:39:47 UTC (rev 3274)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,186 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+class WordCamp_Docs {
+       private static $templates = null;
+       private static $errors = array();
+       private static $step = 0;
+
+       /**
+        * Runs at plugins_loaded
+        */
+       public static function load() {
+               add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) );
+               add_action( 'admin_init', array( __CLASS__, 'form_handler' ) );
+
+               add_filter( 'wcdocs_templates', array( __CLASS__, 'default_templates' ) );
+       }
+
+       /**
+        * To load additional templates just hook into wcdocs_template
+        * some time around plugins_loaded and add your own objects that
+        * implement the WordCamp_Docs_Template class.
+        *
+        * @return array An array of template objects.
+        */
+       private static function get_templates() {
+               if ( self::$templates === null )
+                       self::$templates = apply_filters( 'wcdocs_templates', array() );
+
+               return self::$templates;
+       }
+
+       /**
+        *
+        * Get template by key.
+        *
+        * @param string $key Template key.
+        * @return object|null The template object or null if not found.
+        */
+       private static function get_template( $key ) {
+               $templates = self::get_templates();
+               if ( empty( $templates[ $key ] ) )
+                       return null;
+
+               return $templates[ $key ];
+       }
+
+       /**
+        * Load default templates.
+        *
+        * @param array $templates An array of available templates.
+        * @return array Same array of templates with new ones added.
+        */
+       public static function default_templates( $templates ) {
+               require_once( WORDCAMP_DOCS__PLUGIN_DIR . 'templates/speaker-invitation.php' );
+               $templates['speaker-invitation'] = new WordCamp_Docs_Template_Speaker_Invitation;
+
+               return $templates;
+       }
+
+       /**
+        * Add a menu item.
+        */
+       public static function admin_menu() {
+               add_menu_page( __( 'WordCamp Docs', 'wordcamporg' ), __( 'Docs', 'wordcamporg' ), 'manage_options', 'wordcamporg', array( __CLASS__, 'render_menu_page' ), 'dashicons-portfolio', 58 );
+       }
+
+       /**
+        * Our main form handler, runs at admin_init.
+        */
+       public static function form_handler() {
+               if ( empty( $_POST['wcdocs_submit'] ) )
+                       return;
+
+               if ( empty( $_POST['_wpnonce'] ) )
+                       return self::error( __( 'Empty nonce', 'wordcamporg' ) );
+
+               $nonce = $_POST['_wpnonce'];
+               $step = absint( $_POST['wcdocs_submit'] );
+
+               if ( ! wp_verify_nonce( $nonce, 'wcdocs_step_' . $step ) )
+                       return self::error( __( 'Invalid nonce', 'wordcamporg' ) );
+
+               // Check selected template on any step.
+               $templates = self::get_templates();
+               $template = sanitize_text_field( $_POST['wcdocs_template'] );
+               if ( ! array_key_exists( $template, $templates ) )
+                       return self::error( __( 'Selected template does not exist', 'wordcamporg' ) );
+
+               $template = $templates[ $template ];
+
+               switch ( $step ) {
+                       case 1: // submitted step 1
+
+                               // Nothing else to check on this step.
+                               self::$step = 2;
+                               break;
+
+                       case 2: // submitted step 2
+
+                               require_once( WORDCAMP_DOCS__PLUGIN_DIR . 'classes/class-wordcamp-docs-pdf-generator.php' );
+                               $generator = new WordCamp_Docs_PDF_Generator;
+
+                               // Sanitize input
+                               $data = $template->sanitize( $_POST );
+                               $generator->generate_pdf_from_string(
+                                       $template->render( $data ),
+                                       sanitize_file_name( $template->get_filename() ),
+                                       array( 'assets' => $template->get_assets() ) );
+
+                               $generator->serve_pdf_to_browser( $template->get_filename(), true );
+                               $generator->delete_tmp_folder();
+                               die();
+                               break;
+
+               }
+       }
+
+       /**
+        * Append an error message to self::$errors
+        *
+        * @param string $message Error message contents.
+        */
+       private static function error( $message ) {
+               self::$errors[] = $message;
+       }
+
+       /**
+        * Render the contents of our admin section.
+        */
+       public static function render_menu_page() {
+               ?>
+               <div class="wrap">
+                       <h1><?php _e( 'WordCamp Docs', 'wordcamporg' ); ?></h1>
+
+                       <?php if ( ! empty( self::$errors ) ) : ?>
+                               <?php foreach ( self::$errors as $error ) : ?>
+                                       <div class="error">
+                                               <p><?php echo esc_html( $error ); ?></p>
+                                       </div>
+                               <?php endforeach; ?>
+                       <?php endif; ?>
+
+                       <?php if ( self::$step <= 1 ) : ?>
+
+                               <p><?php _e( 'This tool will help you generate various documents and forms for your WordCamp.', 'wordcamporg' ); ?></p>
+
+                               <form method="POST">
+                                       <input type="hidden" name="wcdocs_submit" value="1" />
+                                       <?php wp_nonce_field( 'wcdocs_step_1' ); ?>
+
+                                       <p><?php _e( 'Pick a template to get started:', 'wordcamporg' ); ?></p>
+                                       <select name="wcdocs_template">
+                                               <?php foreach ( self::get_templates() as $key => $template ) : ?>
+                                                       <option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $template->get_name() ); ?></option>
+                                               <?php endforeach; ?>
+                                       </select>
+                                       <p class="submit">
+                                               <input type="submit" class="button-primary" value="Next &rarr;">
+                                       </p>
+                               </form>
+
+                       <?php elseif ( self::$step == 2 ) : ?>
+
+                               <form method="POST">
+                                       <input type="hidden" name="wcdocs_submit" value="2" />
+                                       <input type="hidden" name="wcdocs_template" value="<?php echo esc_attr( $_POST['wcdocs_template'] ); ?>">
+                                       <?php wp_nonce_field( 'wcdocs_step_2' ); ?>
+
+                                       <?php
+                                               $template = self::get_template( $_POST['wcdocs_template'] );
+                                               $template->form( $_POST );
+                                       ?>
+
+                                       <p class="submit">
+                                               <input type="submit" class="button-primary" value="<?php esc_attr_e( 'Download PDF', 'wordcamporg' ); ?>">
+                                       </p>
+                               </form>
+
+                       <?php endif; ?>
+               </div>
+               <?php
+       }
+
+       private function __construct() {} // Not this time.
+}
+
+add_action( 'plugins_loaded', array( 'WordCamp_Docs', 'load' ) );
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocstemplatesassetslogopng"></a>
<div class="binary"><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-docs/templates/assets/logo.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/assets/logo.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/assets/logo.png      2016-05-30 18:15:50 UTC (rev 3273)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/assets/logo.png       2016-05-31 16:39:47 UTC (rev 3274)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/assets/logo.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocstemplatesspeakerinvitationphp"></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-docs/templates/speaker-invitation.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-docs/templates/speaker-invitation.php                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/templates/speaker-invitation.php      2016-05-31 16:39:47 UTC (rev 3274)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,200 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Speakers Invitation Template
+ *
+ * @see classes/class-wordcamp-docs.php for implementation details.
+ */
+class WordCamp_Docs_Template_Speaker_Invitation implements WordCamp_Docs_Template {
+       public function form( $data ) {
+
+               /**
+                * @todo Grab defaults from central and/or options, cpt, etc.
+                */
+               $data = wp_parse_args( $data, array(
+                       'name' => '',
+                       'gender' => '',
+                       'dates' => '',
+                       'city' => '',
+                       'country' => '',
+                       'venue_name' => '',
+                       'venue_address' => '',
+                       'signature' => '',
+               ) );
+               ?>
+               <style>
+               .wcorg-speaker-invitation-form label {
+                       display: block;
+                       clear: both;
+                       margin-top: 12px;
+               }
+
+               .wcorg-speaker-invitation-form input,
+               .wcorg-speaker-invitation-form textarea,
+               .wcorg-speaker-invitation-form select {
+                       width: 240px;
+               }
+
+               .wcorg-speaker-invitation-form textarea {
+                       height: 120px;
+               }
+
+               .wcorg-speaker-invitation-form .description {
+                       display: block;
+                       clear: both;
+               }
+               </style>
+
+               <div class="wcorg-speaker-invitation-form">
+                       <label><?php _e( 'Speaker Name:', 'wordcamporg' ); ?></label>
+                       <input name="name" value="<?php echo esc_attr( $data['name'] ); ?>" />
+
+                       <label><?php _e( 'Gender:', 'wordcamporg' ); ?></label>
+                       <select name="gender">
+                               <option value="male" <?php selected( $data['gender'], 'male' ); ?>><?php _e( 'Male', 'wordcamporg' ); ?></option>
+                               <option value="female" <?php selected( $data['gender'], 'female' ); ?>><?php _e( 'Female', 'wordcamporg' ); ?></option>
+                       </select>
+
+                       <label><?php _e( 'Travel Dates:', 'wordcamporg' ); ?></label>
+                       <input name="dates" value="<?php echo esc_attr( $data['dates'] ); ?>" />
+                       <span class="description"><?php _e( 'Ex: January 15-16, 2019', 'wordcamporg' ); ?></span>
+
+                       <label><?php _e( 'City:', 'wordcamporg' ); ?></label>
+                       <input name="city" value="<?php echo esc_attr( $data['city'] ); ?>" />
+
+                       <label><?php _e( 'Country:', 'wordcamporg' ); ?></label>
+                       <input name="country" value="<?php echo esc_attr( $data['country'] ); ?>" />
+
+                       <label><?php _e( 'Venue Name:', 'wordcamporg' ); ?></label>
+                       <input name="venue_name" value="<?php echo esc_attr( $data['venue_name'] ); ?>" />
+
+                       <label><?php _e( 'Venue Address:', 'wordcamporg' ); ?></label>
+                       <input name="venue_address" value="<?php echo esc_attr( $data['venue_address'] ); ?>" />
+
+                       <label><?php _e( 'Signature:', 'wordcamporg' ); ?></label>
+                       <textarea name="signature"><?php echo esc_textarea( $data['signature'] ); ?></textarea>
+                       <span class="description"><?php _e( 'Name, title, phone, e-mail address', 'wordcamporg' ); ?></span>
+               </div>
+
+               <?php
+       }
+
+       public function render( $data ) {
+               ob_start();
+               ?>
+<html>
+<head>
+<meta charset="UTF-8">
+<link href="http://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet" type="text/css" />
+<style type="text/css">
+body {
+       margin: 0;
+       padding: 0;
+       font-family: 'Open Sans', sans-serif;
+       font-size: 16px;
+       line-height: 1.5;
+       font-weight: 300;
+       color: #444;
+}
+
+p {
+       margin: 0 0 1.5em;
+}
+
+h1, h2, h3, h4, div, p, span {
+       font-family: 'Open Sans', sans-serif;
+}
+
+.wrap {
+       clear: both;
+       margin: 40px 40px;
+}
+
+.main {
+       float: left;
+       width: 100%;
+       margin-top: 40px;
+}
+
+.logo {
+       width: 300px;
+       height: 150px;
+       margin-bottom: 40px;
+}
+
+#footer {
+       position: absolute;
+       bottom: 0px;
+       left: 40px;
+       right: 40px;
+}
+</style>
+</head>
+
+<body>
+
+<div class="wrap">
+       <div class="main">
+               <img class="logo" src="logo.png" alt="WordPress Foundation">
+
+               <p><?php echo date( 'F j, Y' ); ?></p>
+               <p>To whom it may concern:</p>
+
+               <p>This letter is to confirm that <?php echo esc_html( $data['name'] ); ?> has been invited to speak at an international WordCamp conference in <?php echo esc_html( $data['city'] ) ; ?>, <?php echo esc_html( $data['country'] ) ; ?>. <?php echo $data['gender'] == 'male' ? 'His' : 'Her'; ?> participation in this conference will require <?php echo $data['gender'] == 'male' ? 'him' : 'her'; ?> to be in <?php echo esc_html( $data['city'] ); ?> from <?php echo esc_html( $data['dates'] ); ?>.<p>
+
+               <p>The conference will be held at <?php echo esc_html( $data['venue_name'] ); ?>, <?php echo esc_html( $data['venue_address'] ); ?>.</p>
+
+               <p>Please don't hesitate to contact me for any additional information regarding this invitation.</p>
+
+               <p>Sincerely,</p>
+               <p><?php echo nl2br( esc_html( $data['signature'] ) ); ?></p>
+
+       </div>
+
+       <div id="footer">
+               <p>WordPress Foundation, 200 Brannan Street Apt 239, San Francisco, CA 94107-6008, USA</p>
+       </div>
+</div>
+</body>
+</html>
+               <?php
+               return ob_get_clean();
+       }
+
+       public function sanitize( $input ) {
+               $output = array();
+               $input = wp_parse_args( $input, array(
+                       'name' => '',
+                       'gender' => '',
+                       'dates' => '',
+                       'city' => '',
+                       'country' => '',
+                       'venue_name' => '',
+                       'venue_address' => '',
+                       'signature' => '',
+               ) );
+
+               foreach ( array( 'name', 'dates', 'city', 'country', 'venue_name', 'venue_address' ) as $field )
+                       $output[ $field ] = sanitize_text_field( wp_strip_all_tags( $input[ $field ] ) );
+
+               $output['gender'] = 'male';
+               if ( in_array( $input['gender'], array( 'male', 'female' ) ) )
+                       $output['gender'] = $input['gender'];
+
+               $output['signature'] = wp_strip_all_tags( $input['signature'] );
+               return $output;
+       }
+
+       public function get_name() {
+               return __( 'Speaker Invitation', 'wordcamporg' );
+       }
+
+       public function get_filename() {
+               return 'speaker-invitation.pdf';
+       }
+
+       public function get_assets() {
+               return array(
+                       dirname( __FILE__ ) . '/assets/logo.png',
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentpluginswordcampdocswordcampdocsphp"></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-docs/wordcamp-docs.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-docs/wordcamp-docs.php                           (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-docs/wordcamp-docs.php     2016-05-31 16:39:47 UTC (rev 3274)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,14 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/*
+ * Plugin Name: WordCamp Docs
+ * Plugin URI: http://central.wordcamp.org/
+ * Description: Generate various WordCamp-related documents.
+ * Author: Konstantin Kovshenin
+ * Version: 1.0-dev
+ * License: GPL2+
+ */
+
+define( 'WORDCAMP_DOCS__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
+
+require_once( WORDCAMP_DOCS__PLUGIN_DIR . 'classes/class-wordcamp-docs.php' );
+require_once( WORDCAMP_DOCS__PLUGIN_DIR . 'classes/class-wordcamp-docs-template.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>