<!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>[8980] sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins: WordCamp Helpers: Rename to load earlier.</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/8980">8980</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/8980","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>iandunn</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-06-20 20:24:08 +0000 (Thu, 20 Jun 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'>WordCamp Helpers: Rename to load earlier.
Other mu-plugins depend on these, so they should load early to ensure they're always available, rather than relying on alphabetical happenstance.</pre>
<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmuplugins3helpersmiscphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/3-helpers-misc.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmuplugins4helperswcptphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/4-helpers-wcpt.php</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginshelpersmiscphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helpers-misc.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginshelperswcptphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helpers-wcpt.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmuplugins3helpersmiscphpfromrev8979sitestrunkwordcamporgpublic_htmlwpcontentmupluginshelpersmiscphp"></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/3-helpers-misc.php (from rev 8979, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helpers-misc.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/3-helpers-misc.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/3-helpers-misc.php 2019-06-20 20:24:08 UTC (rev 8980)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,131 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+defined( 'WPINC' ) or die();
+use function WordCamp\Logger\log;
+
+/*
+ * Miscellaneous helper functions.
+ */
+
+
+/**
+ * Determine if a specific feature should be skipped on the current site
+ *
+ * Warning: Pay careful attention to how things are named, since setting a flag here is typically done when you
+ * want a feature to be _enabled_ by default on new sites. In the cases where you want it _disabled_ by default
+ * on new sites, you can reverse the name (e.g., `local_terms` instead of `global_terms` for the
+ * `global_terms_enabled` callback).
+ *
+ * Often times we want to add new functionality to plugins and themes, but can't let it run on older sites
+ * because that would break backwards compatibility. To get around that, we set a flag on older sites to
+ * indicate that they should not have the new feature, and then setup the feature to run on sites that
+ * don't have the flag, i.e., to run by default.
+ *
+ * Doing it this way means that local development environments like the Meta Environment don't to have add any
+ * new filters in order to start using the new functionality.
+ *
+ * See WordCamp_CLI_Miscellaneous::set_skip_feature_flag() for how to set the flags.
+ *
+ * @param string $flag
+ *
+ * @return bool
+ */
+function wcorg_skip_feature( $flag ) {
+ $flags = get_option( 'wordcamp_skip_features', array() );
+
+ return isset( $flags[ $flag ] );
+}
+
+/**
+ * Get a user by the username or nicename
+ *
+ * Note: This intentionally doesn't lookup users by the display name or nickname, because those can be set by the
+ * user, which could result in false-positive matches.
+ *
+ * @param string $name
+ *
+ * @return false|WP_User
+ */
+function wcorg_get_user_by_canonical_names( $name ) {
+ if ( ! $user = get_user_by( 'login', $name ) ) { // user_login
+ $user = get_user_by( 'slug', $name ); // user_nicename
+ }
+
+ return $user;
+}
+
+/**
+ * Get ISO-3166 country names and codes
+ *
+ * @todo move the real functionality from get_valid_countries_iso3166() to here, then have the Budgets plugin,
+ * QBO, etc call this.
+ *
+ * @return array
+ */
+function wcorg_get_countries() {
+ require_once( WP_PLUGIN_DIR . '/wordcamp-payments/includes/wordcamp-budgets.php' );
+
+ return WordCamp_Budgets::get_valid_countries_iso3166();
+}
+
+/**
+ * Make a remote HTTP request, and retry if it fails
+ *
+ * Sometimes the HTTP request times out, or there's a temporary server-side error, etc. Some use cases require a
+ * successful request, like stats scripts, where the resulting data would be distorted by a failed response.
+ *
+ * @todo Add support for wp_remote_post() too
+ * @todo Remove this if https://github.com/rmccue/Requests/issues/222 is implemented
+ * @todo maybe `set_time_limit( absint( ini_get( 'max_execution_time' ) ) + $retry_after );` before sleep()'ing to
+ * avoid php timeout
+ *
+ * @param string $request_url
+ * @param array $request_args
+ *
+ * @return array|WP_Error
+ */
+function wcorg_redundant_remote_get( $request_url, $request_args = array() ) {
+ $attempt_count = 1;
+
+ while ( true ) {
+ $response = wp_remote_get( $request_url, $request_args );
+ $status_code = wp_remote_retrieve_response_code( $response );
+ $body = wp_remote_retrieve_body( $response );
+ $retry_after = wp_remote_retrieve_header( $response, 'retry-after' ) ?: 5;
+ $retry_after = min( $retry_after * $attempt_count, 30 );
+
+ if ( ! is_wp_error( $response ) && 200 === $status_code && $body ) {
+ break;
+ }
+
+ if ( $attempt_count < 3 ) {
+ log( 'request_failed_temporarily', compact( 'request_url', 'request_args', 'response', 'attempt_count', 'retry_after' ) );
+ sleep( $retry_after );
+ } else {
+ log( 'request_failed_permenantly', compact( 'request_url', 'request_args', 'response' ) );
+ break;
+ }
+
+ $attempt_count++;
+ }
+
+ return $response;
+}
+
+/**
+ * Display the indicator that marks a form field as required
+ */
+function wcorg_required_indicator() {
+ ?>
+
+ <span class="wcorg-required" aria-hidden="true">
+ <?php // translators: The symbol to indicate the form field is required ?>
+ <?php _e( '*', 'wordcamporg' ); ?>
+ </span>
+
+ <span class="screen-reader-text">
+ <?php _e( 'required field', 'wordcamporg' ); ?>
+ </span>
+
+ <?php
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmuplugins4helperswcptphpfromrev8979sitestrunkwordcamporgpublic_htmlwpcontentmupluginshelperswcptphp"></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/4-helpers-wcpt.php (from rev 8979, sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helpers-wcpt.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/4-helpers-wcpt.php (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/4-helpers-wcpt.php 2019-06-20 20:24:08 UTC (rev 8980)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,254 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+defined( 'WPINC' ) or die();
+
+/*
+ * Helper functions related to the `wordcamp` post type.
+ */
+
+
+/**
+ * Retrieve `wordcamp` posts and their metadata.
+ *
+ * @param array $args Optional. Extra arguments to pass to `get_posts()`.
+ *
+ * @return array
+ */
+function get_wordcamps( $args = array() ) {
+ $args = wp_parse_args( $args, array(
+ 'post_type' => WCPT_POST_TYPE_ID,
+ 'post_status' => 'any',
+ 'orderby' => 'ID',
+ 'numberposts' => -1,
+ 'perm' => 'readable',
+ ) );
+
+ $wordcamps = get_posts( $args );
+
+ foreach ( $wordcamps as &$wordcamp ) {
+ $wordcamp->meta = get_post_custom( $wordcamp->ID );
+ }
+
+ return $wordcamps;
+}
+
+/**
+ * Retrieves the `wordcamp` post and postmeta associated with the current site.
+ *
+ * `Site ID` is the most reliable way to associate a site with it's corresponding `wordcamp` post,
+ * but wasn't historically assigned when new sites are created. For older sites, we fallback to
+ * using the `URL` to associate them. That will only work if the site's site_url() exactly
+ * matches the `wordcamp` post's `URL` meta field, though. It could also fail if we ever migrate
+ * to a different URL structure.
+ *
+ * @return false|WP_Post
+ */
+function get_wordcamp_post() {
+ $current_site_id = get_current_blog_id();
+ $current_site_url = site_url();
+
+ switch_to_blog( BLOG_ID_CURRENT_SITE ); // central.wordcamp.org
+
+ $wordcamp = get_posts( array(
+ 'post_type' => 'wordcamp',
+ 'post_status' => 'any',
+
+ 'meta_query' => array(
+ 'relation' => 'OR',
+
+ array(
+ 'key' => '_site_id',
+ 'value' => $current_site_id,
+ ),
+
+ array(
+ 'key' => 'URL',
+ 'value' => $current_site_url,
+ ),
+ ),
+ ) );
+
+ if ( isset( $wordcamp[0]->ID ) ) {
+ $wordcamp = $wordcamp[0];
+ $wordcamp->meta = get_post_custom( $wordcamp->ID );
+ } else {
+ $wordcamp = false;
+ }
+
+ restore_current_blog();
+
+ return $wordcamp;
+}
+
+/**
+ * Find the site that corresponds to the given `wordcamp` post
+ *
+ * @param WP_Post $wordcamp_post
+ *
+ * @return mixed An integer if successful, or boolean false if failed
+ */
+function get_wordcamp_site_id( $wordcamp_post ) {
+ switch_to_blog( BLOG_ID_CURRENT_SITE ); // central.wordcamp.org
+
+ if ( ! $site_id = get_post_meta( $wordcamp_post->ID, '_site_id', true ) ) {
+ $url = parse_url( get_post_meta( $wordcamp_post->ID, 'URL', true ) );
+
+ if ( isset( $url['host'] ) && isset( $url['path'] ) ) {
+ if ( $site = get_site_by_path( $url['host'], $url['path'] ) ) {
+ $site_id = $site->blog_id;
+ }
+ }
+ }
+
+ restore_current_blog();
+
+ return $site_id;
+}
+
+/**
+ * Get a consistent WordCamp name in the 'WordCamp [Location] [Year]' format.
+ *
+ * The results of bloginfo( 'name' ) don't always contain the year, but the title of the site's corresponding
+ * `wordcamp` post is usually named 'WordCamp [Location]', so we can get a consistent name most of the time
+ * by using that and adding the year (if available).
+ *
+ * @param int $site_id Optionally, get the name for a site other than the current one.
+ *
+ * @return string
+ */
+function get_wordcamp_name( $site_id = 0 ) {
+ $name = false;
+
+ switch_to_blog( $site_id );
+
+ if ( $wordcamp = get_wordcamp_post() ) {
+ if ( ! empty( $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] ) ) {
+ $name = $wordcamp->post_title . ' ' . date( 'Y', $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] );
+ }
+ }
+
+ if ( ! $name ) {
+ $name = get_bloginfo( 'name' );
+ }
+
+ restore_current_blog();
+
+ return $name;
+}
+
+
+/**
+ * Extract pieces from a WordCamp.org URL
+ *
+ * @todo find other code that's doing this same task in an ad-hoc manner, and convert it to use this instead
+ *
+ * @param string $url
+ * @param string $part 'city', 'city-domain' (without the year, e.g. seattle.wordcamp.org), 'year'
+ *
+ * @return false|string|int False on errors; an integer for years; a string for city and city-domain
+ */
+function wcorg_get_url_part( $url, $part ) {
+ $url_parts = explode( '.', parse_url( $url, PHP_URL_HOST ) );
+ $result = false;
+
+ // Make sure it matches the typical year.city.wordcamp.org structure
+ if ( 4 !== count( $url_parts ) ) {
+ return $result;
+ }
+
+ switch ( $part ) {
+ case 'city':
+ $result = $url_parts[1];
+ break;
+
+ case 'city-domain':
+ $result = ltrim( strstr( $url, '.' ), '.' );
+ break;
+
+ case 'year':
+ $result = absint( $url_parts[0] );
+ break;
+ }
+
+ return $result;
+}
+
+
+/**
+ * Take the start and end dates for a WordCamp and calculate how many days it lasts.
+ *
+ * @param WP_Post $wordcamp
+ *
+ * @return int
+ */
+function wcorg_get_wordcamp_duration( WP_Post $wordcamp ) {
+ // @todo Make sure $wordcamp is the correct post type
+
+ $start = get_post_meta( $wordcamp->ID, 'Start Date (YYYY-mm-dd)', true );
+ $end = get_post_meta( $wordcamp->ID, 'End Date (YYYY-mm-dd)', true );
+
+ // Assume 1 day duration if there is no end date
+ if ( ! $end ) {
+ return 1;
+ }
+
+ $duration_raw = $end - $start;
+
+ // Add one second and round up to ensure the end date counts as a day as well
+ $duration_days = ceil( ( $duration_raw + 1 ) / DAY_IN_SECONDS );
+
+ return absint( $duration_days );
+}
+
+/**
+ * Get a <select> dropdown of `wordcamp` posts with a select2 UI.
+ *
+ * The calling plugin is responsible for validating and processing the form, this just outputs a single field.
+ *
+ * @param string $name Optional. The `name` attribute for the `select` element. Defaults to `wordcamp_id`.
+ * @param array $query_options Optional. Extra arguments to pass to `get_posts()`. Defaults to the values in `get_wordcamps()`.
+ * @param int $selected Optional. The list option to select. Defaults to not selecting any.
+ *
+ * @return string The HTML for the <select> list.
+ */
+function get_wordcamp_dropdown( $name = 'wordcamp_id', $query_options = array(), $selected = 0 ) {
+ $wordcamps = get_wordcamps( $query_options );
+
+ wp_enqueue_script( 'select2' );
+ wp_enqueue_style( 'select2' );
+
+ ob_start();
+
+ ?>
+
+ <select name="<?php echo esc_attr( $name ); ?>" class="select2">
+ <option value=""><?php _e( 'Select a WordCamp', 'wordcamporg' ); ?></option>
+ <option value=""></option>
+
+ <?php foreach ( $wordcamps as $wordcamp ) : ?>
+ <option
+ value="<?php echo esc_attr( $wordcamp->ID ); ?>"
+ <?php selected( $selected, $wordcamp->ID ); ?>
+ >
+ <?php
+
+ echo esc_html( $wordcamp->post_title );
+ if ( ! empty( $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] ) ) {
+ echo ' ' . esc_html( date( 'Y', $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] ) );
+ }
+
+ ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+
+ <script>
+ jQuery( document ).ready( function() {
+ jQuery( '.select2' ).select2();
+ } );
+ </script>
+
+ <?php
+
+ return ob_get_clean();
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginshelpersmiscphp"></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/helpers-misc.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/helpers-misc.php 2019-06-20 19:11:55 UTC (rev 8979)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helpers-misc.php 2019-06-20 20:24:08 UTC (rev 8980)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,131 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-defined( 'WPINC' ) or die();
-use function WordCamp\Logger\log;
-
-/*
- * Miscellaneous helper functions.
- */
-
-
-/**
- * Determine if a specific feature should be skipped on the current site
- *
- * Warning: Pay careful attention to how things are named, since setting a flag here is typically done when you
- * want a feature to be _enabled_ by default on new sites. In the cases where you want it _disabled_ by default
- * on new sites, you can reverse the name (e.g., `local_terms` instead of `global_terms` for the
- * `global_terms_enabled` callback).
- *
- * Often times we want to add new functionality to plugins and themes, but can't let it run on older sites
- * because that would break backwards compatibility. To get around that, we set a flag on older sites to
- * indicate that they should not have the new feature, and then setup the feature to run on sites that
- * don't have the flag, i.e., to run by default.
- *
- * Doing it this way means that local development environments like the Meta Environment don't to have add any
- * new filters in order to start using the new functionality.
- *
- * See WordCamp_CLI_Miscellaneous::set_skip_feature_flag() for how to set the flags.
- *
- * @param string $flag
- *
- * @return bool
- */
-function wcorg_skip_feature( $flag ) {
- $flags = get_option( 'wordcamp_skip_features', array() );
-
- return isset( $flags[ $flag ] );
-}
-
-/**
- * Get a user by the username or nicename
- *
- * Note: This intentionally doesn't lookup users by the display name or nickname, because those can be set by the
- * user, which could result in false-positive matches.
- *
- * @param string $name
- *
- * @return false|WP_User
- */
-function wcorg_get_user_by_canonical_names( $name ) {
- if ( ! $user = get_user_by( 'login', $name ) ) { // user_login
- $user = get_user_by( 'slug', $name ); // user_nicename
- }
-
- return $user;
-}
-
-/**
- * Get ISO-3166 country names and codes
- *
- * @todo move the real functionality from get_valid_countries_iso3166() to here, then have the Budgets plugin,
- * QBO, etc call this.
- *
- * @return array
- */
-function wcorg_get_countries() {
- require_once( WP_PLUGIN_DIR . '/wordcamp-payments/includes/wordcamp-budgets.php' );
-
- return WordCamp_Budgets::get_valid_countries_iso3166();
-}
-
-/**
- * Make a remote HTTP request, and retry if it fails
- *
- * Sometimes the HTTP request times out, or there's a temporary server-side error, etc. Some use cases require a
- * successful request, like stats scripts, where the resulting data would be distorted by a failed response.
- *
- * @todo Add support for wp_remote_post() too
- * @todo Remove this if https://github.com/rmccue/Requests/issues/222 is implemented
- * @todo maybe `set_time_limit( absint( ini_get( 'max_execution_time' ) ) + $retry_after );` before sleep()'ing to
- * avoid php timeout
- *
- * @param string $request_url
- * @param array $request_args
- *
- * @return array|WP_Error
- */
-function wcorg_redundant_remote_get( $request_url, $request_args = array() ) {
- $attempt_count = 1;
-
- while ( true ) {
- $response = wp_remote_get( $request_url, $request_args );
- $status_code = wp_remote_retrieve_response_code( $response );
- $body = wp_remote_retrieve_body( $response );
- $retry_after = wp_remote_retrieve_header( $response, 'retry-after' ) ?: 5;
- $retry_after = min( $retry_after * $attempt_count, 30 );
-
- if ( ! is_wp_error( $response ) && 200 === $status_code && $body ) {
- break;
- }
-
- if ( $attempt_count < 3 ) {
- log( 'request_failed_temporarily', compact( 'request_url', 'request_args', 'response', 'attempt_count', 'retry_after' ) );
- sleep( $retry_after );
- } else {
- log( 'request_failed_permenantly', compact( 'request_url', 'request_args', 'response' ) );
- break;
- }
-
- $attempt_count++;
- }
-
- return $response;
-}
-
-/**
- * Display the indicator that marks a form field as required
- */
-function wcorg_required_indicator() {
- ?>
-
- <span class="wcorg-required" aria-hidden="true">
- <?php // translators: The symbol to indicate the form field is required ?>
- <?php _e( '*', 'wordcamporg' ); ?>
- </span>
-
- <span class="screen-reader-text">
- <?php _e( 'required field', 'wordcamporg' ); ?>
- </span>
-
- <?php
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginshelperswcptphp"></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/helpers-wcpt.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/helpers-wcpt.php 2019-06-20 19:11:55 UTC (rev 8979)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helpers-wcpt.php 2019-06-20 20:24:08 UTC (rev 8980)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,254 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-defined( 'WPINC' ) or die();
-
-/*
- * Helper functions related to the `wordcamp` post type.
- */
-
-
-/**
- * Retrieve `wordcamp` posts and their metadata.
- *
- * @param array $args Optional. Extra arguments to pass to `get_posts()`.
- *
- * @return array
- */
-function get_wordcamps( $args = array() ) {
- $args = wp_parse_args( $args, array(
- 'post_type' => WCPT_POST_TYPE_ID,
- 'post_status' => 'any',
- 'orderby' => 'ID',
- 'numberposts' => -1,
- 'perm' => 'readable',
- ) );
-
- $wordcamps = get_posts( $args );
-
- foreach ( $wordcamps as &$wordcamp ) {
- $wordcamp->meta = get_post_custom( $wordcamp->ID );
- }
-
- return $wordcamps;
-}
-
-/**
- * Retrieves the `wordcamp` post and postmeta associated with the current site.
- *
- * `Site ID` is the most reliable way to associate a site with it's corresponding `wordcamp` post,
- * but wasn't historically assigned when new sites are created. For older sites, we fallback to
- * using the `URL` to associate them. That will only work if the site's site_url() exactly
- * matches the `wordcamp` post's `URL` meta field, though. It could also fail if we ever migrate
- * to a different URL structure.
- *
- * @return false|WP_Post
- */
-function get_wordcamp_post() {
- $current_site_id = get_current_blog_id();
- $current_site_url = site_url();
-
- switch_to_blog( BLOG_ID_CURRENT_SITE ); // central.wordcamp.org
-
- $wordcamp = get_posts( array(
- 'post_type' => 'wordcamp',
- 'post_status' => 'any',
-
- 'meta_query' => array(
- 'relation' => 'OR',
-
- array(
- 'key' => '_site_id',
- 'value' => $current_site_id,
- ),
-
- array(
- 'key' => 'URL',
- 'value' => $current_site_url,
- ),
- ),
- ) );
-
- if ( isset( $wordcamp[0]->ID ) ) {
- $wordcamp = $wordcamp[0];
- $wordcamp->meta = get_post_custom( $wordcamp->ID );
- } else {
- $wordcamp = false;
- }
-
- restore_current_blog();
-
- return $wordcamp;
-}
-
-/**
- * Find the site that corresponds to the given `wordcamp` post
- *
- * @param WP_Post $wordcamp_post
- *
- * @return mixed An integer if successful, or boolean false if failed
- */
-function get_wordcamp_site_id( $wordcamp_post ) {
- switch_to_blog( BLOG_ID_CURRENT_SITE ); // central.wordcamp.org
-
- if ( ! $site_id = get_post_meta( $wordcamp_post->ID, '_site_id', true ) ) {
- $url = parse_url( get_post_meta( $wordcamp_post->ID, 'URL', true ) );
-
- if ( isset( $url['host'] ) && isset( $url['path'] ) ) {
- if ( $site = get_site_by_path( $url['host'], $url['path'] ) ) {
- $site_id = $site->blog_id;
- }
- }
- }
-
- restore_current_blog();
-
- return $site_id;
-}
-
-/**
- * Get a consistent WordCamp name in the 'WordCamp [Location] [Year]' format.
- *
- * The results of bloginfo( 'name' ) don't always contain the year, but the title of the site's corresponding
- * `wordcamp` post is usually named 'WordCamp [Location]', so we can get a consistent name most of the time
- * by using that and adding the year (if available).
- *
- * @param int $site_id Optionally, get the name for a site other than the current one.
- *
- * @return string
- */
-function get_wordcamp_name( $site_id = 0 ) {
- $name = false;
-
- switch_to_blog( $site_id );
-
- if ( $wordcamp = get_wordcamp_post() ) {
- if ( ! empty( $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] ) ) {
- $name = $wordcamp->post_title . ' ' . date( 'Y', $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] );
- }
- }
-
- if ( ! $name ) {
- $name = get_bloginfo( 'name' );
- }
-
- restore_current_blog();
-
- return $name;
-}
-
-
-/**
- * Extract pieces from a WordCamp.org URL
- *
- * @todo find other code that's doing this same task in an ad-hoc manner, and convert it to use this instead
- *
- * @param string $url
- * @param string $part 'city', 'city-domain' (without the year, e.g. seattle.wordcamp.org), 'year'
- *
- * @return false|string|int False on errors; an integer for years; a string for city and city-domain
- */
-function wcorg_get_url_part( $url, $part ) {
- $url_parts = explode( '.', parse_url( $url, PHP_URL_HOST ) );
- $result = false;
-
- // Make sure it matches the typical year.city.wordcamp.org structure
- if ( 4 !== count( $url_parts ) ) {
- return $result;
- }
-
- switch ( $part ) {
- case 'city':
- $result = $url_parts[1];
- break;
-
- case 'city-domain':
- $result = ltrim( strstr( $url, '.' ), '.' );
- break;
-
- case 'year':
- $result = absint( $url_parts[0] );
- break;
- }
-
- return $result;
-}
-
-
-/**
- * Take the start and end dates for a WordCamp and calculate how many days it lasts.
- *
- * @param WP_Post $wordcamp
- *
- * @return int
- */
-function wcorg_get_wordcamp_duration( WP_Post $wordcamp ) {
- // @todo Make sure $wordcamp is the correct post type
-
- $start = get_post_meta( $wordcamp->ID, 'Start Date (YYYY-mm-dd)', true );
- $end = get_post_meta( $wordcamp->ID, 'End Date (YYYY-mm-dd)', true );
-
- // Assume 1 day duration if there is no end date
- if ( ! $end ) {
- return 1;
- }
-
- $duration_raw = $end - $start;
-
- // Add one second and round up to ensure the end date counts as a day as well
- $duration_days = ceil( ( $duration_raw + 1 ) / DAY_IN_SECONDS );
-
- return absint( $duration_days );
-}
-
-/**
- * Get a <select> dropdown of `wordcamp` posts with a select2 UI.
- *
- * The calling plugin is responsible for validating and processing the form, this just outputs a single field.
- *
- * @param string $name Optional. The `name` attribute for the `select` element. Defaults to `wordcamp_id`.
- * @param array $query_options Optional. Extra arguments to pass to `get_posts()`. Defaults to the values in `get_wordcamps()`.
- * @param int $selected Optional. The list option to select. Defaults to not selecting any.
- *
- * @return string The HTML for the <select> list.
- */
-function get_wordcamp_dropdown( $name = 'wordcamp_id', $query_options = array(), $selected = 0 ) {
- $wordcamps = get_wordcamps( $query_options );
-
- wp_enqueue_script( 'select2' );
- wp_enqueue_style( 'select2' );
-
- ob_start();
-
- ?>
-
- <select name="<?php echo esc_attr( $name ); ?>" class="select2">
- <option value=""><?php _e( 'Select a WordCamp', 'wordcamporg' ); ?></option>
- <option value=""></option>
-
- <?php foreach ( $wordcamps as $wordcamp ) : ?>
- <option
- value="<?php echo esc_attr( $wordcamp->ID ); ?>"
- <?php selected( $selected, $wordcamp->ID ); ?>
- >
- <?php
-
- echo esc_html( $wordcamp->post_title );
- if ( ! empty( $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] ) ) {
- echo ' ' . esc_html( date( 'Y', $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] ) );
- }
-
- ?>
- </option>
- <?php endforeach; ?>
- </select>
-
- <script>
- jQuery( document ).ready( function() {
- jQuery( '.select2' ).select2();
- } );
- </script>
-
- <?php
-
- return ob_get_clean();
-}
</del></span></pre>
</div>
</div>
</body>
</html>