<!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>[8860] sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks: WC Blocks: Moved `php` files to `source` for logical consistency.</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 { white-space: pre-line; 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/8860">8860</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/8860","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>vedjain</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-05-23 18:11:59 +0000 (Thu, 23 May 2019)</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'>WC Blocks: Moved `php` files to `source` for logical consistency.

To follow class standard, it would be more logical to move the `php` source files for components in the same directory as their JavaScript counterparts.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksblocksphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontentjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontentjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentstylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizerscontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersviewphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/view.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionscontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsviewphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/view.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakerscontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersviewphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/view.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorscontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsviewphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/view.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentcontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagecontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlistcontrollerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/controller.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcestylesscss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/styles.scss</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksorganizersphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssessionsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksspeakersphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssponsorsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsblockcontentphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsfeaturedimagephp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentspostlistphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsstylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsorganizerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssessionphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsspeakerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssponsorphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksblocksphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.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/mu-plugins/blocks/blocks.php      2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.php        2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -12,7 +12,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * @return void
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> function load_includes() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $includes_dir = PLUGIN_DIR . 'includes/';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $includes_dir   = PLUGIN_DIR . 'includes/';
+       $blocks_dir     = PLUGIN_DIR . 'source/blocks/';
+       $components_dir = PLUGIN_DIR . 'source/components/';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        require_once $includes_dir . 'definitions.php';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -20,15 +22,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">        require_once $includes_dir . 'utilities/content.php';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Components.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        require_once $includes_dir . 'components/block-content.php';
-       require_once $includes_dir . 'components/featured-image.php';
-       require_once $includes_dir . 'components/post-list.php';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ require_once $components_dir . 'block-content/controller.php';
+       require_once $components_dir . 'image/controller.php';
+       require_once $components_dir . 'post-list/controller.php';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Blocks.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        require_once $includes_dir . 'blocks/organizers.php';
-       require_once $includes_dir . 'blocks/sessions.php';
-       require_once $includes_dir . 'blocks/speakers.php';
-       require_once $includes_dir . 'blocks/sponsors.php';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ require_once $blocks_dir . 'organizers/controller.php';
+       require_once $blocks_dir . 'sessions/controller.php';
+       require_once $blocks_dir . 'speakers/controller.php';
+       require_once $blocks_dir . 'sponsors/controller.php';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksorganizersphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.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/mu-plugins/blocks/includes/blocks/organizers.php  2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.php    2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,210 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Organizers;
-
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Components\{ render_post_list };
-use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-
-/**
- * Register block types and enqueue scripts.
- *
- * @return void
- */
-function init() {
-       register_block_type(
-               'wordcamp/organizers',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Render the block on the front end.
- *
- * @param array $attributes Block attributes.
- *
- * @return string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-
-       $organizers               = get_organizer_posts( $attributes );
-       $rendered_organizer_posts = [];
-
-       foreach ( $organizers as $organizer ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'views/organizer.php';
-               $rendered_organizer_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-organizers__posts',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_organizer_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['organizers'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Get the posts to display in the block.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_organizer_posts( array $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = [
-               'post_type'      => 'wcb_organizer',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-       ];
-
-       $sort = explode( '_', $attributes['sort'] );
-
-       if ( 2 === count( $sort ) ) {
-               $post_args['orderby'] = $sort[0];
-               $post_args['order']   = $sort[1];
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_organizer':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_organizer_team':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get the schema for the block's attributes.
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
-                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
-                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
-                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
-                       'mode'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'sort'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'title_asc',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all organizers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose organizers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_organizer',
-                               ],
-                               [
-                                       'label' => _x( 'Choose teams', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_organizer_team',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               return empty( $options[ $type ] ) ? [] : $options[ $type ];
-       }
-
-       return $options;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssessionsphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.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/mu-plugins/blocks/includes/blocks/sessions.php    2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.php      2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,302 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Sessions;
-
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Components\{ render_post_list };
-use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Register block types and enqueue scripts.
- *
- * @return void
- */
-function init() {
-       register_block_type(
-               'wordcamp/sessions',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Render the block on the front end.
- *
- * @param array $attributes Block attributes.
- *
- * @return string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-       $sessions   = get_session_posts( $attributes );
-
-       $speakers = [];
-       if ( ! empty( $sessions ) && true === $attributes['show_speaker'] ) {
-               $speakers = get_session_speakers( wp_list_pluck( $sessions, 'ID' ) );
-       }
-
-       $rendered_session_posts = [];
-
-       foreach ( $sessions as $session ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'views/session.php';
-               $rendered_session_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-sessions__posts',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_session_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['sessions'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Get the schema for the block's attributes.
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
-                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
-                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute' ),
-                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
-                       'mode'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_category'        => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'show_images'          => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'show_meta'            => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'show_speaker'         => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'sort'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'session_time',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all sessions', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose sessions', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_session',
-                               ],
-                               [
-                                       'label' => _x( 'Choose tracks', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_track',
-                               ],
-                               [
-                                       'label' => _x( 'Choose session categories', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_session_category',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               [
-                                       [
-                                               'label' => _x( 'Day and Time', 'sort option', 'wordcamporg' ),
-                                               'value' => 'session_time',
-                                       ],
-                               ],
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               if ( ! empty( $options[ $type ] ) ) {
-                       return $options[ $type ];
-               } else {
-                       return [];
-               }
-       }
-
-       return $options;
-}
-
-/**
- * Get the posts to display in the block.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_session_posts( array $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = [
-               'post_type'      => 'wcb_session',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-               'meta_query'     => [
-                       'relation' => 'AND',
-                       [
-                               'relation' => 'OR',
-                               [
-                                       'key'     => '_wcpt_session_type',
-                                       'value'   => 'session',
-                                       'compare' => '=',
-                               ],
-                               [
-                                       'key'     => '_wcpt_session_type',
-                                       'value'   => '',
-                                       'compare' => 'NOT EXISTS',
-                               ],
-                       ],
-               ],
-       ];
-
-       switch ( $attributes['sort'] ) {
-               case 'session_time':
-                       $post_args['meta_key'] = '_wcpt_session_time';
-                       $post_args['orderby']  = 'meta_value_num title';
-                       $post_args['order']    = 'asc';
-                       break;
-
-               case 'title_asc':
-               case 'title_desc':
-               case 'date_desc':
-               case 'date_asc':
-                       $sort = explode( '_', $attributes['sort'] );
-
-                       if ( 2 === count( $sort ) ) {
-                               $post_args['orderby'] = $sort[0];
-                               $post_args['order']   = $sort[1];
-                       }
-                       break;
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_session':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_track':
-               case 'wcb_session_category':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get speaker posts grouped by session.
- *
- * @param array $session_ids
- *
- * @return array
- */
-function get_session_speakers( array $session_ids ) {
-       $speakers_by_session = [];
-
-       $session_args = [
-               'post_type'      => 'wcb_session',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-               'post__in'       => $session_ids,
-       ];
-
-       $session_posts = get_posts( $session_args );
-
-       foreach ( $session_posts as $session ) {
-               $speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
-
-               if ( ! empty( $speaker_ids ) ) {
-                       $speaker_args = [
-                               'post_type'      => 'wcb_speaker',
-                               'post_status'    => 'publish',
-                               'posts_per_page' => -1,
-                               'post__in'       => $speaker_ids,
-                               'orderby'        => 'post__in',
-                               'order'          => 'ASC',
-                       ];
-
-                       $speakers_by_session[ $session->ID ] = get_posts( $speaker_args );
-               }
-       }
-
-       return $speakers_by_session;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksspeakersphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.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/mu-plugins/blocks/includes/blocks/speakers.php    2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.php      2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,260 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Speakers;
-
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Components\{ render_post_list };
-use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Register block types and enqueue scripts.
- *
- * @return void
- */
-function init() {
-       register_block_type(
-               'wordcamp/speakers',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Render the block on the front end.
- *
- * @param array $attributes Block attributes.
- *
- * @return string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-       $speakers   = get_speaker_posts( $attributes );
-
-       $sessions = [];
-       if ( ! empty( $speakers ) && true === $attributes['show_session'] ) {
-               $sessions = get_speaker_sessions( wp_list_pluck( $speakers, 'ID' ) );
-       }
-
-       $rendered_speaker_posts = [];
-
-       foreach ( $speakers as $speaker ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'views/speaker.php';
-               $rendered_speaker_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-speakers__posts',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_speaker_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['speakers'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Get the posts to display in the block.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_speaker_posts( array $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = [
-               'post_type'      => 'wcb_speaker',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-       ];
-
-       $sort = explode( '_', $attributes['sort'] );
-
-       if ( 2 === count( $sort ) ) {
-               $post_args['orderby'] = $sort[0];
-               $post_args['order']   = $sort[1];
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_speaker':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_speaker_group':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get session posts grouped by speaker.
- *
- * @param array $speaker_ids
- *
- * @return array
- */
-function get_speaker_sessions( array $speaker_ids ) {
-       $sessions_by_speaker = [];
-
-       $session_args = [
-               'post_type'      => 'wcb_session',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-               'meta_key'       => '_wcpt_session_time',
-               'orderby'        => 'meta_value_num',
-       ];
-
-       $session_posts = get_posts( $session_args );
-
-       foreach ( $session_posts as $session ) {
-               $session_speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
-
-               foreach ( $session_speaker_ids as $speaker_id ) {
-                       $speaker_id = absint( $speaker_id );
-
-                       if ( in_array( $speaker_id, $speaker_ids, true ) ) {
-                               if ( ! isset( $sessions_by_speaker[ $speaker_id ] ) ) {
-                                       $sessions_by_speaker[ $speaker_id ] = [];
-                               }
-
-                               $sessions_by_speaker[ $speaker_id ][] = $session;
-                       }
-               }
-       }
-
-       return $sessions_by_speaker;
-}
-
-/**
- * Get the schema for the block's attributes.
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
-                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
-                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
-                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
-                       'mode'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'show_session' => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'sort'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'title_asc',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all speakers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose speakers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_speaker',
-                               ],
-                               [
-                                       'label' => _x( 'Choose groups', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_speaker_group',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               if ( ! empty( $options[ $type ] ) ) {
-                       return $options[ $type ];
-               } else {
-                       return [];
-               }
-       }
-
-       return $options;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssponsorsphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.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/mu-plugins/blocks/includes/blocks/sponsors.php    2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.php      2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,214 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Sponsors;
-
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Components\{ render_post_list };
-use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Register sponsor block and enqueue scripts.
- */
-function init() {
-       register_block_type(
-               'wordcamp/sponsors',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Renders content of Sponsor block based on attributes.
- *
- * @param array $attributes
- *
- * @return false|string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-
-       $sponsors               = get_sponsor_posts( $attributes );
-       $rendered_sponsor_posts = [];
-
-       foreach ( $sponsors as $sponsor ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'views/sponsor.php';
-               $rendered_sponsor_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-sponsors__posts',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_sponsor_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['sponsors'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Return sponsor posts what will rendered based on attributes.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_sponsor_posts( $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = array(
-               'post_type'      => 'wcb_sponsor',
-               'post_status'    => 'publish',
-               'posts_per_page' => - 1,
-       );
-
-       $sort = explode( '_', $attributes['sort'] );
-
-       if ( 2 === count( $sort ) ) {
-               $post_args['orderby'] = $sort[0];
-               $post_args['order']   = $sort[1];
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_sponsor':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_sponsor_level':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get attribute schema for Sponsor block
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
-                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
-                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute', [ 'default' => 600 ] ),
-                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
-                       'mode'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_logo'            => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'show_name'            => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'sort'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'title_asc',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all sponsors', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose sponsors', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_sponsor',
-                               ],
-                               [
-                                       'label' => _x( 'Choose sponsor level', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_sponsor_level',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               if ( ! empty( $options[ $type ] ) ) {
-                       return $options[ $type ];
-               } else {
-                       return [];
-               }
-       }
-
-       return $options;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsblockcontentphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.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/mu-plugins/blocks/includes/components/block-content.php   2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.php     2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,101 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Components;
-
-use function WordCamp\Blocks\Utilities\{ render_class_string };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Render HTML for a title with specified heading level and optionally a link.
- *
- * @param string $title
- * @param string $link
- * @param int    $heading_level
- * @param array  $classes
- *
- * @return false|string
- */
-function render_item_title( $title, $link = '', $heading_level = 3, array $classes = [] ) {
-       $valid_heading_levels = [ 1, 2, 3, 4, 5, 6 ];
-
-       if ( ! in_array( $heading_level, $valid_heading_levels, true ) ) {
-               $heading_level = 3;
-       }
-
-       $tag = 'h' . $heading_level;
-
-       $classes = render_class_string( array_merge(
-               [ 'wordcamp-block__post-title' ],
-               $classes
-       ) );
-
-       ob_start();
-       ?>
-       <<?php echo esc_html( $tag ); ?> class="<?php echo esc_attr( $classes ); ?>">
-       <?php if ( $link ) : ?>
-               <a href="<?php echo esc_url( $link ); ?>">
-       <?php endif; ?>
-       <?php echo wp_kses_post( $title ); ?>
-       <?php if ( $link ) : ?>
-               </a>
-       <?php endif; ?>
-       </<?php echo esc_html( $tag ); ?>>
-       <?php
-
-       return ob_get_clean();
-}
-
-/**
- * Render arbitrary HTML content within a div container.
- *
- * @param string $content
- * @param array  $classes
- *
- * @return false|string
- */
-function render_item_content( $content, array $classes = [] ) {
-       $classes = render_class_string( array_merge(
-               [ 'wordcamp-block__post-content' ],
-               $classes
-       ) );
-
-       ob_start();
-       ?>
-       <div class="<?php echo esc_attr( $classes ); ?>">
-               <?php echo wp_kses_post( wpautop( $content ) ); ?>
-       </div>
-       <?php
-
-       return ob_get_clean();
-}
-
-/**
- * Render HTML for a permalink wrapped in its own paragraph.
- *
- * @param string $link
- * @param string $label
- * @param array  $classes
- *
- * @return false|string
- */
-function render_item_permalink( $link, $label = '', array $classes = [] ) {
-       if ( ! $label ) {
-               $label = __( 'Read more', 'wordcamporg' );
-       }
-
-       $classes = render_class_string( array_merge(
-               [ 'wordcamp-block__post-permalink' ],
-               $classes
-       ) );
-
-       ob_start();
-       ?>
-       <p class="<?php echo esc_attr( $classes ); ?>">
-               <a href="<?php echo esc_url( $link ); ?>">
-                       <?php echo esc_html( $label ); ?>
-               </a>
-       </p>
-       <?php
-
-       return ob_get_clean();
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsfeaturedimagephp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.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/mu-plugins/blocks/includes/components/featured-image.php  2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.php    2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,69 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Components;
-
-use WP_Post;
-
-defined( 'WPINC' ) || die();
-
-/**
- * Provides render backend for FeaturedImage component.
- *
- * @param WP_Post  $post        Current post object. This will be used to calculate srcset attribute.
- * @param int      $width       Width of the image.
- * @param array    $class_names Additional classes to add inside <img> tag.
- * @param string   $image_link  URL link. If provided, image will be linked to this URL.
- *
- * @return string Output markup for featured image.
- */
-function render_featured_image( $post, $width, $class_names = [], $image_link = '' ) {
-       $attachment_id = get_post_thumbnail_id( $post->ID );
-       $image_data    = wp_get_attachment_metadata( $attachment_id );
-
-       if ( ! isset( $image_data['width'], $image_data['height'] ) ) {
-               return '';
-       }
-
-       $aspect_ratio = $image_data['height'] / $image_data['width'];
-       $height       = round( $aspect_ratio * $width, 1 );
-       $size         = array( $width, $height );
-
-       $container_classes = array_merge(
-               [ 'wordcamp-image__featured-image-container' ],
-               $class_names
-       );
-       $container_classes = implode( ' ', $container_classes );
-
-       $image = render_featured_image_element( $post, $size );
-
-       ob_start();
-       ?>
-               <div class="<?php echo esc_attr( $container_classes ); ?>">
-                       <?php if ( '' !== $image_link ) { ?>
-                               <a href="<?php echo esc_html( $image_link ); ?>" class="wordcamp-image__featured-image-link">
-                                       <?php echo wp_kses_post( $image ); ?>
-                               </a>
-                       <?php } else { ?>
-                               <?php echo wp_kses_post( $image ); ?>
-                       <?php } ?>
-               </div>
-       <?php
-
-       return ob_get_clean();
-}
-
-/**
- * Helper method to render thumbnail image.
- *
- * @param \WP_Post     $post
- * @param string|array $size
- * @param string       $class_names
- *
- * @return string
- */
-function render_featured_image_element( $post, $size ) {
-       $attr = [
-               'class' => 'wordcamp-image__featured-image',
-       ];
-
-       return get_the_post_thumbnail( $post, $size, $attr );
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentspostlistphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.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/mu-plugins/blocks/includes/components/post-list.php       2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.php 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,54 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Components;
-
-use function WordCamp\Blocks\Utilities\{ render_class_string };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Render the containing HTML structures of a post list.
- *
- * @param array  $rendered_items    Array of rendered post list items.
- * @param string $layout            Whether the layout is `grid` or `list`.
- * @param int    $columns           Number of columns if layout is `grid`. Assumed to be 1 if layout is list.
- * @param array  $container_classes Array of classes that will be added to container.
- *
- * @return string Markup of output layout.
- */
-function render_post_list( array $rendered_items, $layout = 'list', $columns = 1, array $container_classes = [] ) {
-       if ( count( $rendered_items ) < 1 ) {
-               return '';
-       }
-
-       $container_classes = array_merge(
-               [
-                       'wordcamp-block',
-                       'wordcamp-post-list',
-                       'layout-' . sanitize_html_class( $layout )
-               ],
-               $container_classes
-       );
-
-       if ( 'grid' === $layout ) {
-               if ( $columns < 2 ) {
-                       $columns = 2;
-               }
-
-               $container_classes[] = 'grid-columns-' . absint( $columns );
-       }
-
-       $container_classes = render_class_string( $container_classes );
-
-       ob_start();
-       ?>
-               <ul class="<?php echo esc_attr( $container_classes ); ?>">
-                       <?php foreach ( $rendered_items as $item ) : ?>
-                               <li class="wordcamp-post-list__post wordcamp-clearfix">
-                                       <?php echo wp_kses_post( $item ); ?>
-                               </li>
-                       <?php endforeach; ?>
-               </ul>
-       <?php
-
-       return ob_get_clean();
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontentjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.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/mu-plugins/blocks/source/blocks/organizers/block-content.js       2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.js 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16,6 +16,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> import { PostList }                                   from '../../components/post-list';
</span><span class="cx" style="display: block; padding: 0 10px"> import { filterEntities }                             from '../../data';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Component for displaying the block content.
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.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/mu-plugins/blocks/source/blocks/organizers/block-controls.js      2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.js        2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,7 +13,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Internal dependencies
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { PlaceholderSpecificMode, EditModeOption } from '../../components/block-controls';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { PlaceholderSpecificMode } from '../../components/block-controls';
</ins><span class="cx" style="display: block; padding: 0 10px"> import { getOptionLabel }          from '../../components/item-select';
</span><span class="cx" style="display: block; padding: 0 10px"> import { BlockContent }            from './block-content';
</span><span class="cx" style="display: block; padding: 0 10px"> import { ContentSelect }           from './content-select';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -65,30 +65,26 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                icon={ icon }
</span><span class="cx" style="display: block; padding: 0 10px">                                                label={ LABEL }
</span><span class="cx" style="display: block; padding: 0 10px">                                        >
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <Button
-                                                                       isDefault
-                                                                       isLarge
-                                                                       onClick={ () => {
-                                                                               setAttributes( { mode : 'all' } );
-                                                                       } }
-                                                               >
-                                                                       { getOptionLabel( 'all', options.mode ) }
-                                                               </Button>
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' }>
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode : 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <ContentSelect
-                                                                       label={ __(
-                                                                               'Choose specific organizers or teams',
-                                                                               'wordcamporg' ) }
-                                                                       { ...this.props }
-                                                               />
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' }>
+                                                       <ContentSelect
+                                                               label={ __(
+                                                                       'Choose specific organizers or teams',
+                                                                       'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px">                                         </Placeholder>
</span><span class="cx" style="display: block; padding: 0 10px">                                );
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizerscontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksorganizersphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.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/mu-plugins/blocks/source/blocks/organizers/controller.php                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/controller.php   2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,210 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Organizers;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+
+/**
+ * Register block types and enqueue scripts.
+ *
+ * @return void
+ */
+function init() {
+       register_block_type(
+               'wordcamp/organizers',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Render the block on the front end.
+ *
+ * @param array $attributes Block attributes.
+ *
+ * @return string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+
+       $organizers               = get_organizer_posts( $attributes );
+       $rendered_organizer_posts = [];
+
+       foreach ( $organizers as $organizer ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'source/blocks/organizers/view.php';
+               $rendered_organizer_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-organizers__posts',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_organizer_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['organizers'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Get the posts to display in the block.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_organizer_posts( array $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = [
+               'post_type'      => 'wcb_organizer',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+       ];
+
+       $sort = explode( '_', $attributes['sort'] );
+
+       if ( 2 === count( $sort ) ) {
+               $post_args['orderby'] = $sort[0];
+               $post_args['order']   = $sort[1];
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_organizer':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_organizer_team':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get the schema for the block's attributes.
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
+                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
+                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
+                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
+                       'mode'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'sort'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'title_asc',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all organizers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose organizers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_organizer',
+                               ],
+                               [
+                                       'label' => _x( 'Choose teams', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_organizer_team',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               return empty( $options[ $type ] ) ? [] : $options[ $type ];
+       }
+
+       return $options;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersviewphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsorganizerphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/view.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.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/mu-plugins/blocks/source/blocks/organizers/view.php                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/view.php 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,53 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Organizers;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_item_title, render_item_content };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var WP_Post $organizer */
+
+// Note that organizer posts are not 'public', so there are no permalinks.
+
+setup_postdata( $organizer ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
+?>
+
+<div class="wordcamp-organizer wordcamp-organizers__post has-slug-<?php echo esc_attr( $organizer->post_name ); ?>">
+       <?php echo wp_kses_post(
+               render_item_title(
+                       get_the_title( $organizer ),
+                       '',
+                       3,
+                       [ 'wordcamp-organizers__title' ]
+               )
+       ); ?>
+
+       <?php if ( true === $attributes['show_avatars'] ) : ?>
+               <div class="wordcamp-image-container wordcamp-avatar-container align-<?php echo esc_attr( $attributes['avatar_align'] ); ?>">
+                       <?php echo get_avatar(
+                               $organizer->_wcpt_user_id,
+                               $attributes['avatar_size'],
+                               '',
+                               sprintf( __( 'Avatar of %s', 'wordcamporg'), get_the_title( $organizer ) ),
+                               [ 'force_display' => true ]
+                       ); ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $organizer ) )
+                                       : get_all_the_content( $organizer ),
+                               [ 'wordcamp-organizers__content', 'is-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontentjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.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/mu-plugins/blocks/source/blocks/sessions/block-content.js 2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.js   2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,7 +13,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Internal dependencies
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { ItemTitle, ItemHTMLContent, ItemPermalink, BlockNoContent, ItemMeta } from '../../components/block-content';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { ItemTitle, ItemHTMLContent, ItemPermalink, BlockNoContent } from '../../components/block-content';
</ins><span class="cx" style="display: block; padding: 0 10px"> import { FeaturedImage }                                             from '../../components/image';
</span><span class="cx" style="display: block; padding: 0 10px"> import { PostList }                                                  from '../../components/post-list';
</span><span class="cx" style="display: block; padding: 0 10px"> import { filterEntities }                                            from '../../data';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -58,12 +58,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        return (
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <ItemMeta
-                       className={ "wordcamp-sessions__speakers" }
-                       content={
-                               { speakers }
-                       }
-               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         <div className="wordcamp__post-meta wordcamp-sessions__speakers">
+                       { speakers }
+               </div>
</ins><span class="cx" style="display: block; padding: 0 10px">         );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -289,16 +286,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                { ( show_meta || show_category ) &&
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        <ItemMeta
-                                                               className="wordcamp-sessions__details"
-                                                               content={
-                                                                       show_meta &&
-                                                                       <SessionMeta session={ post }/>
-                                                                       +
-                                                                       show_category &&
-                                                                       <SessionCategory session={ post } />
-                                                               }
-                                                       />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div
+                                                       className="wordcamp__post-meta wordcamp-sessions__details">
+                                                       { show_meta &&
+                                                       <SessionMeta session={ post }/>
+                                                       }
+                                                       { show_category &&
+                                                       <SessionCategory session={ post }/>
+                                                       }
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                { ( 'full' === content ) &&
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.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/mu-plugins/blocks/source/blocks/sessions/block-controls.js        2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.js  2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,7 +13,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Internal dependencies
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { PlaceholderSpecificMode, EditModeOption } from '../../components/block-controls';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { PlaceholderSpecificMode } from '../../components/block-controls';
</ins><span class="cx" style="display: block; padding: 0 10px"> import { getOptionLabel }          from '../../components/item-select';
</span><span class="cx" style="display: block; padding: 0 10px"> import { BlockContent }            from './block-content';
</span><span class="cx" style="display: block; padding: 0 10px"> import { ContentSelect }           from './content-select';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -66,31 +66,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                icon={ icon }
</span><span class="cx" style="display: block; padding: 0 10px">                                                label={ LABEL }
</span><span class="cx" style="display: block; padding: 0 10px">                                        >
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <Button
-                                                                       isDefault
-                                                                       isLarge
-                                                                       onClick={ () => {
-                                                                               setAttributes( { mode : 'all' } );
-                                                                       } }
-                                                               >
-                                                                       { getOptionLabel( 'all', options.mode ) }
-                                                               </Button>
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' } >
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode : 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <ContentSelect
-                                                                       icon={ icon }
-                                                                       label={ __(
-                                                                               'Choose specific sessions, tracks, or categories',
-                                                                               'wordcamporg' ) }
-                                                                       { ...this.props }
-                                                               />
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' }>
+                                                       <ContentSelect
+                                                               icon={ icon }
+                                                               label={ __(
+                                                                       'Choose specific sessions, tracks, or categories',
+                                                                       'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px">                                         </Placeholder>
</span><span class="cx" style="display: block; padding: 0 10px">                                );
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionscontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssessionsphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.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/mu-plugins/blocks/source/blocks/sessions/controller.php                           (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/controller.php     2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,302 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sessions;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Register block types and enqueue scripts.
+ *
+ * @return void
+ */
+function init() {
+       register_block_type(
+               'wordcamp/sessions',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Render the block on the front end.
+ *
+ * @param array $attributes Block attributes.
+ *
+ * @return string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+       $sessions   = get_session_posts( $attributes );
+
+       $speakers = [];
+       if ( ! empty( $sessions ) && true === $attributes['show_speaker'] ) {
+               $speakers = get_session_speakers( wp_list_pluck( $sessions, 'ID' ) );
+       }
+
+       $rendered_session_posts = [];
+
+       foreach ( $sessions as $session ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'source/blocks/sessions/view.php';
+               $rendered_session_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-sessions__posts',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_session_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['sessions'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Get the schema for the block's attributes.
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
+                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
+                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute' ),
+                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
+                       'mode'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_category'        => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'show_images'          => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'show_meta'            => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'show_speaker'         => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'sort'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'session_time',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all sessions', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose sessions', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_session',
+                               ],
+                               [
+                                       'label' => _x( 'Choose tracks', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_track',
+                               ],
+                               [
+                                       'label' => _x( 'Choose session categories', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_session_category',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               [
+                                       [
+                                               'label' => _x( 'Day and Time', 'sort option', 'wordcamporg' ),
+                                               'value' => 'session_time',
+                                       ],
+                               ],
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               if ( ! empty( $options[ $type ] ) ) {
+                       return $options[ $type ];
+               } else {
+                       return [];
+               }
+       }
+
+       return $options;
+}
+
+/**
+ * Get the posts to display in the block.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_session_posts( array $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = [
+               'post_type'      => 'wcb_session',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+               'meta_query'     => [
+                       'relation' => 'AND',
+                       [
+                               'relation' => 'OR',
+                               [
+                                       'key'     => '_wcpt_session_type',
+                                       'value'   => 'session',
+                                       'compare' => '=',
+                               ],
+                               [
+                                       'key'     => '_wcpt_session_type',
+                                       'value'   => '',
+                                       'compare' => 'NOT EXISTS',
+                               ],
+                       ],
+               ],
+       ];
+
+       switch ( $attributes['sort'] ) {
+               case 'session_time':
+                       $post_args['meta_key'] = '_wcpt_session_time';
+                       $post_args['orderby']  = 'meta_value_num title';
+                       $post_args['order']    = 'asc';
+                       break;
+
+               case 'title_asc':
+               case 'title_desc':
+               case 'date_desc':
+               case 'date_asc':
+                       $sort = explode( '_', $attributes['sort'] );
+
+                       if ( 2 === count( $sort ) ) {
+                               $post_args['orderby'] = $sort[0];
+                               $post_args['order']   = $sort[1];
+                       }
+                       break;
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_session':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_track':
+               case 'wcb_session_category':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get speaker posts grouped by session.
+ *
+ * @param array $session_ids
+ *
+ * @return array
+ */
+function get_session_speakers( array $session_ids ) {
+       $speakers_by_session = [];
+
+       $session_args = [
+               'post_type'      => 'wcb_session',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+               'post__in'       => $session_ids,
+       ];
+
+       $session_posts = get_posts( $session_args );
+
+       foreach ( $session_posts as $session ) {
+               $speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
+
+               if ( ! empty( $speaker_ids ) ) {
+                       $speaker_args = [
+                               'post_type'      => 'wcb_speaker',
+                               'post_status'    => 'publish',
+                               'posts_per_page' => -1,
+                               'post__in'       => $speaker_ids,
+                               'orderby'        => 'post__in',
+                               'order'          => 'ASC',
+                       ];
+
+                       $speakers_by_session[ $session->ID ] = get_posts( $speaker_args );
+               }
+       }
+
+       return $speakers_by_session;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsviewphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssessionphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/view.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.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/mu-plugins/blocks/source/blocks/sessions/view.php                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/view.php   2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,138 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sessions;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_featured_image, render_item_title, render_item_content, render_item_permalink };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content, array_to_human_readable_list };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var array   $speakers */
+/** @var WP_Post $session */
+
+setup_postdata( $session );
+?>
+
+<div class="wordcamp-sessions__post has-slug-<?php echo sanitize_html_class( $session->post_name ); ?>">
+       <?php echo wp_kses_post(
+               render_item_title(
+                       get_the_title( $session ),
+                       get_permalink( $session ),
+                       3,
+                       [ 'wordcamp-sessions__title' ]
+               )
+       ); ?>
+
+       <?php if ( true === $attributes['show_speaker'] && ! empty( $speakers[ $session->ID ] ) ) :
+               $speaker_linked_names = array_map(
+                       function( $speaker ) {
+                               return sprintf(
+                                       '<a href="%s">%s</a>',
+                                       get_permalink( $speaker ),
+                                       get_the_title( $speaker )
+                               );
+                       },
+                       $speakers[ $session->ID ]
+               );
+               ?>
+
+               <div class="wordcamp__item-meta wordcamp-sessions__speakers">
+                       <?php
+                       printf(
+                               /* translators: %s is a list of names. */
+                               wp_kses_post( __( 'Presented by %s', 'wordcamporg' ) ),
+                               wp_kses_post( array_to_human_readable_list( $speaker_linked_names ) )
+                       );
+                       ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( true === $attributes['show_images'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_featured_image(
+                               $session,
+                               $attributes['featured_image_width'],
+                               [ 'wordcamp-sessions__featured-image', 'align-' . esc_attr( $attributes['image_align'] ) ],
+                               get_permalink( $session )
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $session ) )
+                                       : get_all_the_content( $session ),
+                               [ 'wordcamp-sessions__content-' . 'is-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( $attributes['show_meta'] || $attributes['show_category'] ) : ?>
+               <div class="wordcamp__item-meta wordcamp-sessions__details">
+                       <?php if ( $attributes['show_meta'] ) : ?>
+                               <?php $tracks = get_the_terms( $session, 'wcb_track' ); ?>
+
+                               <div class="wordcamp-sessions__time-location">
+                                       <?php if ( ! is_wp_error( $tracks ) && ! empty( $tracks ) ) :
+                                               printf(
+                                                       /* translators: 1: A date; 2: A time; 3: A location; */
+                                                       esc_html__( '%1$s at %2$s in %3$s', 'wordcamporg' ),
+                                                       esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                       esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) ),
+                                                       sprintf(
+                                                               '<span class="wordcamp-sessions__track has-slug-%s">%s</span>',
+                                                               esc_attr( $tracks[0]->slug ),
+                                                               esc_html( $tracks[0]->name )
+                                                       )
+                                               );
+
+                                       else :
+                                               printf(
+                                                       /* translators: 1: A date; 2: A time; */
+                                                       esc_html__( '%1$s at %2$s', 'wordcamporg' ),
+                                                       esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                       esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) )
+                                               );
+                                       endif; ?>
+                               </div>
+                       <?php endif; ?>
+
+                       <?php if ( $attributes['show_category'] && has_term( null, 'wcb_session_category', $session ) ) :
+                               $categories = array_map(
+                                       function( $category ) {
+                                               return sprintf(
+                                                       '<span class="wordcamp-sessions__category has-slug-%s">%s</span>',
+                                                       esc_attr( $category->slug ),
+                                                       esc_html( $category->name )
+                                               );
+                                       },
+                                       get_the_terms( $session, 'wcb_session_category' )
+                               );
+                               ?>
+
+                               <div class="wordcamp-sessions__categories">
+                                       <?php
+                                       /* translators: used between list items, there is a space after the comma */
+                                       echo wp_kses_post( implode( __( ', ', 'wordcamporg' ), $categories ) );
+                                       ?>
+                               </div>
+                       <?php endif; ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'full' === $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_permalink(
+                               get_permalink( $session ),
+                               __( 'Visit session page', 'wordcamporg' ),
+                               [ 'wordcamp-sessions__permalink' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.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/mu-plugins/blocks/source/blocks/speakers/block-controls.js        2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.js  2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,7 +13,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Internal dependencies
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { PlaceholderSpecificMode, EditModeOption } from '../../components/block-controls';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { PlaceholderSpecificMode } from '../../components/block-controls';
</ins><span class="cx" style="display: block; padding: 0 10px"> import { getOptionLabel }          from '../../components/item-select';
</span><span class="cx" style="display: block; padding: 0 10px"> import { BlockContent }            from './block-content';
</span><span class="cx" style="display: block; padding: 0 10px"> import { ContentSelect }           from './content-select';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -65,31 +65,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                icon={ icon }
</span><span class="cx" style="display: block; padding: 0 10px">                                                label={ LABEL }
</span><span class="cx" style="display: block; padding: 0 10px">                                        >
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <Button
-                                                                       isDefault
-                                                                       isLarge
-                                                                       onClick={ () => {
-                                                                               setAttributes( { mode : 'all' } );
-                                                                       } }
-                                                               >
-                                                                       { getOptionLabel( 'all', options.mode ) }
-                                                               </Button>
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' } >
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode : 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <ContentSelect
-                                                                       icon={ icon }
-                                                                       label={ __(
-                                                                               'Choose specific speakers or groups',
-                                                                               'wordcamporg' ) }
-                                                                       { ...this.props }
-                                                               />
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option'} >
+                                                       <ContentSelect
+                                                               icon={ icon }
+                                                               label={ __(
+                                                                       'Choose specific speakers or groups',
+                                                                       'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px">                                         </Placeholder>
</span><span class="cx" style="display: block; padding: 0 10px">                                );
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakerscontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksspeakersphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.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/mu-plugins/blocks/source/blocks/speakers/controller.php                           (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/controller.php     2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,260 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Speakers;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Register block types and enqueue scripts.
+ *
+ * @return void
+ */
+function init() {
+       register_block_type(
+               'wordcamp/speakers',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Render the block on the front end.
+ *
+ * @param array $attributes Block attributes.
+ *
+ * @return string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+       $speakers   = get_speaker_posts( $attributes );
+
+       $sessions = [];
+       if ( ! empty( $speakers ) && true === $attributes['show_session'] ) {
+               $sessions = get_speaker_sessions( wp_list_pluck( $speakers, 'ID' ) );
+       }
+
+       $rendered_speaker_posts = [];
+
+       foreach ( $speakers as $speaker ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'source/blocks/speakers/view.php';
+               $rendered_speaker_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-speakers__posts',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_speaker_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['speakers'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Get the posts to display in the block.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_speaker_posts( array $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = [
+               'post_type'      => 'wcb_speaker',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+       ];
+
+       $sort = explode( '_', $attributes['sort'] );
+
+       if ( 2 === count( $sort ) ) {
+               $post_args['orderby'] = $sort[0];
+               $post_args['order']   = $sort[1];
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_speaker':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_speaker_group':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get session posts grouped by speaker.
+ *
+ * @param array $speaker_ids
+ *
+ * @return array
+ */
+function get_speaker_sessions( array $speaker_ids ) {
+       $sessions_by_speaker = [];
+
+       $session_args = [
+               'post_type'      => 'wcb_session',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+               'meta_key'       => '_wcpt_session_time',
+               'orderby'        => 'meta_value_num',
+       ];
+
+       $session_posts = get_posts( $session_args );
+
+       foreach ( $session_posts as $session ) {
+               $session_speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
+
+               foreach ( $session_speaker_ids as $speaker_id ) {
+                       $speaker_id = absint( $speaker_id );
+
+                       if ( in_array( $speaker_id, $speaker_ids, true ) ) {
+                               if ( ! isset( $sessions_by_speaker[ $speaker_id ] ) ) {
+                                       $sessions_by_speaker[ $speaker_id ] = [];
+                               }
+
+                               $sessions_by_speaker[ $speaker_id ][] = $session;
+                       }
+               }
+       }
+
+       return $sessions_by_speaker;
+}
+
+/**
+ * Get the schema for the block's attributes.
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
+                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
+                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
+                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
+                       'mode'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'show_session' => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'sort'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'title_asc',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all speakers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose speakers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_speaker',
+                               ],
+                               [
+                                       'label' => _x( 'Choose groups', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_speaker_group',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               if ( ! empty( $options[ $type ] ) ) {
+                       return $options[ $type ];
+               } else {
+                       return [];
+               }
+       }
+
+       return $options;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersviewphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsspeakerphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/view.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.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/mu-plugins/blocks/source/blocks/speakers/view.php                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/view.php   2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,107 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Speakers;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_item_title, render_item_content, render_item_permalink };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var array   $sessions */
+/** @var WP_Post $speaker */
+
+setup_postdata( $speaker ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
+?>
+
+<div class="wordcamp-speakers__post has-slug-<?php echo esc_attr( $speaker->post_name ); ?>">
+       <?php echo wp_kses_post(
+               render_item_title(
+                       get_the_title( $speaker ),
+                       get_permalink( $speaker ),
+                       3,
+                       [ 'wordcamp-speakers__title' ]
+               )
+       ); ?>
+
+       <?php if ( true === $attributes['show_avatars'] ) : ?>
+               <div class="wordcamp-image-container wordcamp-avatar-container align-<?php echo esc_attr( $attributes['avatar_align'] ); ?>">
+                       <a href="<?php echo esc_url( get_permalink( $speaker ) ); ?>" class="wordcamp-image__avatar-link">
+                               <?php echo get_avatar(
+                                       $speaker->_wcb_speaker_email,
+                                       $attributes['avatar_size'],
+                                       '',
+                                       sprintf( __( 'Avatar of %s', 'wordcamporg'), get_the_title( $speaker ) ),
+                                       [ 'force_display' => true ]
+                               ); ?>
+                       </a>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $speaker ) )
+                                       : get_all_the_content( $speaker ),
+                               [ 'wordcamp-speakers__content is-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( true === $attributes['show_session'] && ! empty( $sessions[ $speaker->ID ] ) ) : ?>
+               <div class="wordcamp-item-meta wordcamp-speaker-sessions">
+                       <h4 class="wordcamp-speakers__sessions-heading">
+                               <?php echo esc_html( _n( 'Session', 'Sessions', count( $sessions[ $speaker->ID ] ), 'wordcamporg' ) ); ?>
+                       </h4>
+
+                       <ul class="wordcamp-speakers__sessions-list">
+                               <?php foreach ( $sessions[ $speaker->ID ] as $session ) : ?>
+                                       <?php $tracks = get_the_terms( $session, 'wcb_track' ); ?>
+                                       <li class="wordcamp-speakers__sessions-list-item">
+                                               <a class="wordcamp-speakers__session-link" href="<?php echo esc_url( get_permalink( $session ) ); ?>">
+                                                       <?php echo wp_kses_post( get_the_title( $session ) ); ?>
+                                               </a>
+
+                                               <span class="wordcamp-speakers__session-info">
+                                                       <?php if ( ! is_wp_error( $tracks ) && ! empty( $tracks ) ) : ?>
+                                                               <?php
+                                                                       printf(
+                                                                               /* translators: 1: A date; 2: A time; 3: A location; */
+                                                                               esc_html__( '%1$s at %2$s in %3$s', 'wordcamporg' ),
+                                                                               esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                                               esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) ),
+                                                                               esc_html( $tracks[0]->name )
+                                                                       );
+                                                               ?>
+
+                                                       <?php else : ?>
+                                                               <?php
+                                                                       printf(
+                                                                               /* translators: 1: A date; 2: A time; */
+                                                                               esc_html__( '%1$s at %2$s', 'wordcamporg' ),
+                                                                               esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                                               esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) )
+                                                                       );
+                                                               ?>
+                                                       <?php endif; ?>
+                                               </span>
+                                       </li>
+                               <?php endforeach; ?>
+                       </ul>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'full' === $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_permalink(
+                               get_permalink( $speaker ),
+                               __( 'Visit speaker page', 'wordcamporg' ),
+                               [ 'wordcamp-speaker-permalink' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsblockcontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.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/mu-plugins/blocks/source/blocks/sponsors/block-controls.js        2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.js  2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,7 +13,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Internal dependencies
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { PlaceholderSpecificMode, EditModeOption } from '../../components/block-controls';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { PlaceholderSpecificMode } from '../../components/block-controls';
</ins><span class="cx" style="display: block; padding: 0 10px"> import { getOptionLabel }          from '../../components/item-select';
</span><span class="cx" style="display: block; padding: 0 10px"> import { BlockContent }            from './block-content';
</span><span class="cx" style="display: block; padding: 0 10px"> import { ContentSelect }           from './content-select';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -65,31 +65,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                icon={ icon }
</span><span class="cx" style="display: block; padding: 0 10px">                                                label={ LABEL }
</span><span class="cx" style="display: block; padding: 0 10px">                                        >
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <Button
-                                                                       isDefault
-                                                                       isLarge
-                                                                       onClick={ () => {
-                                                                               setAttributes( { mode : 'all' } );
-                                                                       } }
-                                                               >
-                                                                       { getOptionLabel( 'all', options.mode ) }
-                                                               </Button>
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' }>
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode : 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                <EditModeOption
-                                                       content={
-                                                               <ContentSelect
-                                                                       icon={ icon }
-                                                                       label={ __(
-                                                                               'Choose specific sponsors or levels',
-                                                                               'wordcamporg' ) }
-                                                                       { ...this.props }
-                                                               />
-                                                       }
-                                               />
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         <div className={ 'wordcamp__edit-mode-option' }>
+                                                       <ContentSelect
+                                                               icon={ icon }
+                                                               label={ __(
+                                                                       'Choose specific sponsors or levels',
+                                                                       'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
</ins><span class="cx" style="display: block; padding: 0 10px">                                         </Placeholder>
</span><span class="cx" style="display: block; padding: 0 10px">                                );
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorscontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssponsorsphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.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/mu-plugins/blocks/source/blocks/sponsors/controller.php                           (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/controller.php     2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,214 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sponsors;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Register sponsor block and enqueue scripts.
+ */
+function init() {
+       register_block_type(
+               'wordcamp/sponsors',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Renders content of Sponsor block based on attributes.
+ *
+ * @param array $attributes
+ *
+ * @return false|string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+
+       $sponsors               = get_sponsor_posts( $attributes );
+       $rendered_sponsor_posts = [];
+
+       foreach ( $sponsors as $sponsor ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'source/blocks/sponsors/view.php';
+               $rendered_sponsor_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-sponsors__posts',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_sponsor_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['sponsors'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Return sponsor posts what will rendered based on attributes.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_sponsor_posts( $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = array(
+               'post_type'      => 'wcb_sponsor',
+               'post_status'    => 'publish',
+               'posts_per_page' => - 1,
+       );
+
+       $sort = explode( '_', $attributes['sort'] );
+
+       if ( 2 === count( $sort ) ) {
+               $post_args['orderby'] = $sort[0];
+               $post_args['order']   = $sort[1];
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_sponsor':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_sponsor_level':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get attribute schema for Sponsor block
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
+                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
+                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute', [ 'default' => 600 ] ),
+                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
+                       'mode'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_logo'            => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'show_name'            => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'sort'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'title_asc',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all sponsors', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose sponsors', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_sponsor',
+                               ],
+                               [
+                                       'label' => _x( 'Choose sponsor level', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_sponsor_level',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               if ( ! empty( $options[ $type ] ) ) {
+                       return $options[ $type ];
+               } else {
+                       return [];
+               }
+       }
+
+       return $options;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsviewphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssponsorphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/view.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.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/mu-plugins/blocks/source/blocks/sponsors/view.php                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/view.php   2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,62 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sponsors;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_featured_image, render_item_title, render_item_content, render_item_permalink };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var WP_Post $sponsor */
+
+setup_postdata( $sponsor ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
+?>
+
+<div class="wordcamp-sponsors__post has-slug-<?php echo esc_attr( $sponsor->post_name ); ?>">
+       <?php if ( true === $attributes['show_name'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_title(
+                               get_the_title( $sponsor ),
+                               get_permalink( $sponsor ),
+                               3,
+                               [ 'wordcamp-sponsors__title' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( true === $attributes['show_logo'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_featured_image(
+                               $sponsor,
+                               $attributes['featured_image_width'],
+                               [ 'wordcamp-sponsors__featured-image', 'wordcamp-sponsors__logo', 'align-' . esc_attr( $attributes['image_align'] ) ],
+                               get_permalink( $sponsor )
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $sponsor ) )
+                                       : get_all_the_content( $sponsor ),
+                               [ 'wordcamp-sponsors__content has-content-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( 'full' === $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_permalink(
+                               get_permalink( $sponsor ),
+                               __( 'Visit sponsor page', 'wordcamporg' ),
+                               [ 'wordcamp-sponsors__permalink' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.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/mu-plugins/blocks/source/blocks.js        2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.js  2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7,6 +7,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * Internal dependencies
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> import './_z-index.scss';           // Have z-index values, similar to https://github.com/WordPress/gutenberg/blob/master/assets/stylesheets/_z-index.scss
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import './styles.scss';               // Common styles for WordCamp Blocks.
</ins><span class="cx" style="display: block; padding: 0 10px"> import { BLOCKS } from './blocks/'; // Trailing slash required to differentiate the folder from the file.
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> BLOCKS.forEach( ( { NAME, SETTINGS } ) => {
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentcontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsblockcontentphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.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/mu-plugins/blocks/source/components/block-content/controller.php                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/controller.php    2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,101 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Components;
+
+use function WordCamp\Blocks\Utilities\{ render_class_string };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Render HTML for a title with specified heading level and optionally a link.
+ *
+ * @param string $title
+ * @param string $link
+ * @param int    $heading_level
+ * @param array  $classes
+ *
+ * @return false|string
+ */
+function render_item_title( $title, $link = '', $heading_level = 3, array $classes = [] ) {
+       $valid_heading_levels = [ 1, 2, 3, 4, 5, 6 ];
+
+       if ( ! in_array( $heading_level, $valid_heading_levels, true ) ) {
+               $heading_level = 3;
+       }
+
+       $tag = 'h' . $heading_level;
+
+       $classes = render_class_string( array_merge(
+               [ 'wordcamp-block__post-title' ],
+               $classes
+       ) );
+
+       ob_start();
+       ?>
+       <<?php echo esc_html( $tag ); ?> class="<?php echo esc_attr( $classes ); ?>">
+       <?php if ( $link ) : ?>
+               <a href="<?php echo esc_url( $link ); ?>">
+       <?php endif; ?>
+       <?php echo wp_kses_post( $title ); ?>
+       <?php if ( $link ) : ?>
+               </a>
+       <?php endif; ?>
+       </<?php echo esc_html( $tag ); ?>>
+       <?php
+
+       return ob_get_clean();
+}
+
+/**
+ * Render arbitrary HTML content within a div container.
+ *
+ * @param string $content
+ * @param array  $classes
+ *
+ * @return false|string
+ */
+function render_item_content( $content, array $classes = [] ) {
+       $classes = render_class_string( array_merge(
+               [ 'wordcamp-block__post-content' ],
+               $classes
+       ) );
+
+       ob_start();
+       ?>
+       <div class="<?php echo esc_attr( $classes ); ?>">
+               <?php echo wp_kses_post( wpautop( $content ) ); ?>
+       </div>
+       <?php
+
+       return ob_get_clean();
+}
+
+/**
+ * Render HTML for a permalink wrapped in its own paragraph.
+ *
+ * @param string $link
+ * @param string $label
+ * @param array  $classes
+ *
+ * @return false|string
+ */
+function render_item_permalink( $link, $label = '', array $classes = [] ) {
+       if ( ! $label ) {
+               $label = __( 'Read more', 'wordcamporg' );
+       }
+
+       $classes = render_class_string( array_merge(
+               [ 'wordcamp-block__post-permalink' ],
+               $classes
+       ) );
+
+       ob_start();
+       ?>
+       <p class="<?php echo esc_attr( $classes ); ?>">
+               <a href="<?php echo esc_url( $link ); ?>">
+                       <?php echo esc_html( $label ); ?>
+               </a>
+       </p>
+       <?php
+
+       return ob_get_clean();
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentstylescss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss      2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss        2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6,7 +6,3 @@
</span><span class="cx" style="display: block; padding: 0 10px">                float: none;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-.wordcamp-item-meta {
-       margin: 0 0 1.5em;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsindexjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.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/mu-plugins/blocks/source/components/block-controls/index.js       2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.js 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10,11 +10,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> const { Fragment }    = wp.element;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Internal dependencies
- */
-import './style.scss';
-
-/**
</del><span class="cx" style="display: block; padding: 0 10px">  * Component for block controls when the block has a specific mode selected.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @param {Object} props {
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsstylescss"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss     2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss       2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,4 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.wordcamp-block-edit-mode-option {
-       flex-basis: 100%;
-       padding: 0.5em;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagecontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsfeaturedimagephp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.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/mu-plugins/blocks/source/components/image/controller.php                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/controller.php    2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,69 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Components;
+
+use WP_Post;
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Provides render backend for FeaturedImage component.
+ *
+ * @param WP_Post  $post        Current post object. This will be used to calculate srcset attribute.
+ * @param int      $width       Width of the image.
+ * @param array    $class_names Additional classes to add inside <img> tag.
+ * @param string   $image_link  URL link. If provided, image will be linked to this URL.
+ *
+ * @return string Output markup for featured image.
+ */
+function render_featured_image( $post, $width, $class_names = [], $image_link = '' ) {
+       $attachment_id = get_post_thumbnail_id( $post->ID );
+       $image_data    = wp_get_attachment_metadata( $attachment_id );
+
+       if ( ! isset( $image_data['width'], $image_data['height'] ) ) {
+               return '';
+       }
+
+       $aspect_ratio = $image_data['height'] / $image_data['width'];
+       $height       = round( $aspect_ratio * $width, 1 );
+       $size         = array( $width, $height );
+
+       $container_classes = array_merge(
+               [ 'wordcamp-image__featured-image-container' ],
+               $class_names
+       );
+       $container_classes = implode( ' ', $container_classes );
+
+       $image = render_featured_image_element( $post, $size );
+
+       ob_start();
+       ?>
+               <div class="<?php echo esc_attr( $container_classes ); ?>">
+                       <?php if ( '' !== $image_link ) { ?>
+                               <a href="<?php echo esc_html( $image_link ); ?>" class="wordcamp-image__featured-image-link">
+                                       <?php echo wp_kses_post( $image ); ?>
+                               </a>
+                       <?php } else { ?>
+                               <?php echo wp_kses_post( $image ); ?>
+                       <?php } ?>
+               </div>
+       <?php
+
+       return ob_get_clean();
+}
+
+/**
+ * Helper method to render thumbnail image.
+ *
+ * @param \WP_Post     $post
+ * @param string|array $size
+ * @param string       $class_names
+ *
+ * @return string
+ */
+function render_featured_image_element( $post, $size ) {
+       $attr = [
+               'class' => 'wordcamp-image__featured-image',
+       ];
+
+       return get_the_post_thumbnail( $post, $size, $attr );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlistcontrollerphpfromrev8859sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentspostlistphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/controller.php (from rev 8859, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.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/mu-plugins/blocks/source/components/post-list/controller.php                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/controller.php        2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,54 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Components;
+
+use function WordCamp\Blocks\Utilities\{ render_class_string };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Render the containing HTML structures of a post list.
+ *
+ * @param array  $rendered_items    Array of rendered post list items.
+ * @param string $layout            Whether the layout is `grid` or `list`.
+ * @param int    $columns           Number of columns if layout is `grid`. Assumed to be 1 if layout is list.
+ * @param array  $container_classes Array of classes that will be added to container.
+ *
+ * @return string Markup of output layout.
+ */
+function render_post_list( array $rendered_items, $layout = 'list', $columns = 1, array $container_classes = [] ) {
+       if ( count( $rendered_items ) < 1 ) {
+               return '';
+       }
+
+       $container_classes = array_merge(
+               [
+                       'wordcamp-block',
+                       'wordcamp-post-list',
+                       'layout-' . sanitize_html_class( $layout )
+               ],
+               $container_classes
+       );
+
+       if ( 'grid' === $layout ) {
+               if ( $columns < 2 ) {
+                       $columns = 2;
+               }
+
+               $container_classes[] = 'grid-columns-' . absint( $columns );
+       }
+
+       $container_classes = render_class_string( $container_classes );
+
+       ob_start();
+       ?>
+               <ul class="<?php echo esc_attr( $container_classes ); ?>">
+                       <?php foreach ( $rendered_items as $item ) : ?>
+                               <li class="wordcamp-post-list__post wordcamp-clearfix">
+                                       <?php echo wp_kses_post( $item ); ?>
+                               </li>
+                       <?php endforeach; ?>
+               </ul>
+       <?php
+
+       return ob_get_clean();
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcestylesscss"></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/mu-plugins/blocks/source/styles.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/styles.scss                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/styles.scss        2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,8 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp__edit-mode-option {
+       flex-basis: 100%;
+       padding: 0.5em;
+}
+
+.wordcamp__post-meta {
+       margin: 0 0 1.5em;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsorganizerphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.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/mu-plugins/blocks/views/organizer.php     2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.php       2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,53 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Organizers;
-
-use WP_Post;
-use function WordCamp\Blocks\Components\{ render_item_title, render_item_content };
-use function WordCamp\Blocks\Utilities\{ get_all_the_content };
-
-defined( 'WPINC' ) || die();
-
-/** @var array   $attributes */
-/** @var WP_Post $organizer */
-
-// Note that organizer posts are not 'public', so there are no permalinks.
-
-setup_postdata( $organizer ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
-?>
-
-<div class="wordcamp-organizer wordcamp-organizers__post has-slug-<?php echo esc_attr( $organizer->post_name ); ?>">
-       <?php echo wp_kses_post(
-               render_item_title(
-                       get_the_title( $organizer ),
-                       '',
-                       3,
-                       [ 'wordcamp-organizers__title' ]
-               )
-       ); ?>
-
-       <?php if ( true === $attributes['show_avatars'] ) : ?>
-               <div class="wordcamp-image-container wordcamp-avatar-container align-<?php echo esc_attr( $attributes['avatar_align'] ); ?>">
-                       <?php echo get_avatar(
-                               $organizer->_wcpt_user_id,
-                               $attributes['avatar_size'],
-                               '',
-                               sprintf( __( 'Avatar of %s', 'wordcamporg'), get_the_title( $organizer ) ),
-                               [ 'force_display' => true ]
-                       ); ?>
-               </div>
-       <?php endif; ?>
-
-       <?php if ( 'none' !== $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_content(
-                               'excerpt' === $attributes['content']
-                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $organizer ) )
-                                       : get_all_the_content( $organizer ),
-                               [ 'wordcamp-organizers__content', 'is-' . $attributes['content'] ]
-                       )
-               ); ?>
-       <?php endif; ?>
-</div>
-
-<?php
-wp_reset_postdata();
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssessionphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.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/mu-plugins/blocks/views/session.php       2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.php 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,138 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Sessions;
-
-use WP_Post;
-use function WordCamp\Blocks\Components\{ render_featured_image, render_item_title, render_item_content, render_item_permalink };
-use function WordCamp\Blocks\Utilities\{ get_all_the_content, array_to_human_readable_list };
-
-defined( 'WPINC' ) || die();
-
-/** @var array   $attributes */
-/** @var array   $speakers */
-/** @var WP_Post $session */
-
-setup_postdata( $session );
-?>
-
-<div class="wordcamp-sessions__post has-slug-<?php echo sanitize_html_class( $session->post_name ); ?>">
-       <?php echo wp_kses_post(
-               render_item_title(
-                       get_the_title( $session ),
-                       get_permalink( $session ),
-                       3,
-                       [ 'wordcamp-sessions__title' ]
-               )
-       ); ?>
-
-       <?php if ( true === $attributes['show_speaker'] && ! empty( $speakers[ $session->ID ] ) ) :
-               $speaker_linked_names = array_map(
-                       function( $speaker ) {
-                               return sprintf(
-                                       '<a href="%s">%s</a>',
-                                       get_permalink( $speaker ),
-                                       get_the_title( $speaker )
-                               );
-                       },
-                       $speakers[ $session->ID ]
-               );
-               ?>
-
-               <div class="wordcamp__item-meta wordcamp-sessions__speakers">
-                       <?php
-                       printf(
-                               /* translators: %s is a list of names. */
-                               wp_kses_post( __( 'Presented by %s', 'wordcamporg' ) ),
-                               wp_kses_post( array_to_human_readable_list( $speaker_linked_names ) )
-                       );
-                       ?>
-               </div>
-       <?php endif; ?>
-
-       <?php if ( true === $attributes['show_images'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_featured_image(
-                               $session,
-                               $attributes['featured_image_width'],
-                               [ 'wordcamp-sessions__featured-image', 'align-' . esc_attr( $attributes['image_align'] ) ],
-                               get_permalink( $session )
-                       )
-               ); ?>
-       <?php endif; ?>
-
-       <?php if ( 'none' !== $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_content(
-                               'excerpt' === $attributes['content']
-                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $session ) )
-                                       : get_all_the_content( $session ),
-                               [ 'wordcamp-sessions__content-' . 'is-' . $attributes['content'] ]
-                       )
-               ); ?>
-       <?php endif; ?>
-
-       <?php if ( $attributes['show_meta'] || $attributes['show_category'] ) : ?>
-               <div class="wordcamp__item-meta wordcamp-sessions__details">
-                       <?php if ( $attributes['show_meta'] ) : ?>
-                               <?php $tracks = get_the_terms( $session, 'wcb_track' ); ?>
-
-                               <div class="wordcamp-sessions__time-location">
-                                       <?php if ( ! is_wp_error( $tracks ) && ! empty( $tracks ) ) :
-                                               printf(
-                                                       /* translators: 1: A date; 2: A time; 3: A location; */
-                                                       esc_html__( '%1$s at %2$s in %3$s', 'wordcamporg' ),
-                                                       esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
-                                                       esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) ),
-                                                       sprintf(
-                                                               '<span class="wordcamp-sessions__track has-slug-%s">%s</span>',
-                                                               esc_attr( $tracks[0]->slug ),
-                                                               esc_html( $tracks[0]->name )
-                                                       )
-                                               );
-
-                                       else :
-                                               printf(
-                                                       /* translators: 1: A date; 2: A time; */
-                                                       esc_html__( '%1$s at %2$s', 'wordcamporg' ),
-                                                       esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
-                                                       esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) )
-                                               );
-                                       endif; ?>
-                               </div>
-                       <?php endif; ?>
-
-                       <?php if ( $attributes['show_category'] && has_term( null, 'wcb_session_category', $session ) ) :
-                               $categories = array_map(
-                                       function( $category ) {
-                                               return sprintf(
-                                                       '<span class="wordcamp-sessions__category has-slug-%s">%s</span>',
-                                                       esc_attr( $category->slug ),
-                                                       esc_html( $category->name )
-                                               );
-                                       },
-                                       get_the_terms( $session, 'wcb_session_category' )
-                               );
-                               ?>
-
-                               <div class="wordcamp-sessions__categories">
-                                       <?php
-                                       /* translators: used between list items, there is a space after the comma */
-                                       echo wp_kses_post( implode( __( ', ', 'wordcamporg' ), $categories ) );
-                                       ?>
-                               </div>
-                       <?php endif; ?>
-               </div>
-       <?php endif; ?>
-
-       <?php if ( 'full' === $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_permalink(
-                               get_permalink( $session ),
-                               __( 'Visit session page', 'wordcamporg' ),
-                               [ 'wordcamp-sessions__permalink' ]
-                       )
-               ); ?>
-       <?php endif; ?>
-</div>
-
-<?php
-wp_reset_postdata();
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsspeakerphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.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/mu-plugins/blocks/views/speaker.php       2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.php 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,107 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Speakers;
-
-use WP_Post;
-use function WordCamp\Blocks\Components\{ render_item_title, render_item_content, render_item_permalink };
-use function WordCamp\Blocks\Utilities\{ get_all_the_content };
-
-defined( 'WPINC' ) || die();
-
-/** @var array   $attributes */
-/** @var array   $sessions */
-/** @var WP_Post $speaker */
-
-setup_postdata( $speaker ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
-?>
-
-<div class="wordcamp-speakers__post has-slug-<?php echo esc_attr( $speaker->post_name ); ?>">
-       <?php echo wp_kses_post(
-               render_item_title(
-                       get_the_title( $speaker ),
-                       get_permalink( $speaker ),
-                       3,
-                       [ 'wordcamp-speakers__title' ]
-               )
-       ); ?>
-
-       <?php if ( true === $attributes['show_avatars'] ) : ?>
-               <div class="wordcamp-image-container wordcamp-avatar-container align-<?php echo esc_attr( $attributes['avatar_align'] ); ?>">
-                       <a href="<?php echo esc_url( get_permalink( $speaker ) ); ?>" class="wordcamp-image__avatar-link">
-                               <?php echo get_avatar(
-                                       $speaker->_wcb_speaker_email,
-                                       $attributes['avatar_size'],
-                                       '',
-                                       sprintf( __( 'Avatar of %s', 'wordcamporg'), get_the_title( $speaker ) ),
-                                       [ 'force_display' => true ]
-                               ); ?>
-                       </a>
-               </div>
-       <?php endif; ?>
-
-       <?php if ( 'none' !== $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_content(
-                               'excerpt' === $attributes['content']
-                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $speaker ) )
-                                       : get_all_the_content( $speaker ),
-                               [ 'wordcamp-speakers__content is-' . $attributes['content'] ]
-                       )
-               ); ?>
-       <?php endif; ?>
-
-       <?php if ( true === $attributes['show_session'] && ! empty( $sessions[ $speaker->ID ] ) ) : ?>
-               <div class="wordcamp-item-meta wordcamp-speaker-sessions">
-                       <h4 class="wordcamp-speakers__sessions-heading">
-                               <?php echo esc_html( _n( 'Session', 'Sessions', count( $sessions[ $speaker->ID ] ), 'wordcamporg' ) ); ?>
-                       </h4>
-
-                       <ul class="wordcamp-speakers__sessions-list">
-                               <?php foreach ( $sessions[ $speaker->ID ] as $session ) : ?>
-                                       <?php $tracks = get_the_terms( $session, 'wcb_track' ); ?>
-                                       <li class="wordcamp-speakers__sessions-list-item">
-                                               <a class="wordcamp-speakers__session-link" href="<?php echo esc_url( get_permalink( $session ) ); ?>">
-                                                       <?php echo wp_kses_post( get_the_title( $session ) ); ?>
-                                               </a>
-
-                                               <span class="wordcamp-speakers__session-info">
-                                                       <?php if ( ! is_wp_error( $tracks ) && ! empty( $tracks ) ) : ?>
-                                                               <?php
-                                                                       printf(
-                                                                               /* translators: 1: A date; 2: A time; 3: A location; */
-                                                                               esc_html__( '%1$s at %2$s in %3$s', 'wordcamporg' ),
-                                                                               esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
-                                                                               esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) ),
-                                                                               esc_html( $tracks[0]->name )
-                                                                       );
-                                                               ?>
-
-                                                       <?php else : ?>
-                                                               <?php
-                                                                       printf(
-                                                                               /* translators: 1: A date; 2: A time; */
-                                                                               esc_html__( '%1$s at %2$s', 'wordcamporg' ),
-                                                                               esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
-                                                                               esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) )
-                                                                       );
-                                                               ?>
-                                                       <?php endif; ?>
-                                               </span>
-                                       </li>
-                               <?php endforeach; ?>
-                       </ul>
-               </div>
-       <?php endif; ?>
-
-       <?php if ( 'full' === $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_permalink(
-                               get_permalink( $speaker ),
-                               __( 'Visit speaker page', 'wordcamporg' ),
-                               [ 'wordcamp-speaker-permalink' ]
-                       )
-               ); ?>
-       <?php endif; ?>
-</div>
-
-<?php
-wp_reset_postdata();
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssponsorphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.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/mu-plugins/blocks/views/sponsor.php       2019-05-23 18:11:32 UTC (rev 8859)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.php 2019-05-23 18:11:59 UTC (rev 8860)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,62 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-namespace WordCamp\Blocks\Sponsors;
-
-use WP_Post;
-use function WordCamp\Blocks\Components\{ render_featured_image, render_item_title, render_item_content, render_item_permalink };
-use function WordCamp\Blocks\Utilities\{ get_all_the_content };
-
-defined( 'WPINC' ) || die();
-
-/** @var array   $attributes */
-/** @var WP_Post $sponsor */
-
-setup_postdata( $sponsor ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
-?>
-
-<div class="wordcamp-sponsors__post has-slug-<?php echo esc_attr( $sponsor->post_name ); ?>">
-       <?php if ( true === $attributes['show_name'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_title(
-                               get_the_title( $sponsor ),
-                               get_permalink( $sponsor ),
-                               3,
-                               [ 'wordcamp-sponsors__title' ]
-                       )
-               ); ?>
-       <?php endif; ?>
-
-       <?php if ( true === $attributes['show_logo'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_featured_image(
-                               $sponsor,
-                               $attributes['featured_image_width'],
-                               [ 'wordcamp-sponsors__featured-image', 'wordcamp-sponsors__logo', 'align-' . esc_attr( $attributes['image_align'] ) ],
-                               get_permalink( $sponsor )
-                       )
-               ); ?>
-       <?php endif; ?>
-
-       <?php if ( 'none' !== $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_content(
-                               'excerpt' === $attributes['content']
-                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $sponsor ) )
-                                       : get_all_the_content( $sponsor ),
-                               [ 'wordcamp-sponsors__content has-content-' . $attributes['content'] ]
-                       )
-               ); ?>
-       <?php endif; ?>
-
-       <?php if ( 'full' === $attributes['content'] ) : ?>
-               <?php echo wp_kses_post(
-                       render_item_permalink(
-                               get_permalink( $sponsor ),
-                               __( 'Visit sponsor page', 'wordcamporg' ),
-                               [ 'wordcamp-sponsors__permalink' ]
-                       )
-               ); ?>
-       <?php endif; ?>
-</div>
-
-<?php
-wp_reset_postdata();
</del></span></pre>
</div>
</div>

</body>
</html>