diff --git a/assets/css/meta-box.css b/assets/css/meta-box.css index 6e1da55..cfcd9ed 100644 --- a/assets/css/meta-box.css +++ b/assets/css/meta-box.css @@ -2,62 +2,62 @@ * Styles for the NPR Story API meta box */ #ds_npr_document_meta ul ul { - margin-top: 6px; + argin-top: 6px; } #ds_npr_document_meta ul ul ul { - padding-left: 24px; + padding-left: 24px; } #nprone-expiry { - border-top: 1px solid #eee; - padding-top: 6px; + border-top: 1px solid #eee; + padding-top: 6px; } #nprone-expiry-form, #nprone-expiry-form select, #nprone-expiry-form input { - font-size: 12px; - padding-left: 0; - padding-right: 0; + font-size: 12px; + padding-left: 0; + padding-right: 0; } #nprone-expiry-form .row { - clear: both; - margin-top: 6px; - line-height: 28px; + clear: both; + margin-top: 6px; + line-height: 28px; } button.link-effect { - border: none; - color: #0073aa; - text-decoration: underline; + border: none; + color: #0073aa; + text-decoration: underline; } #nprone-expiry-month { - vertical-align: baseline; - margin: 0; + vertical-align: baseline; + margin: 0; } /* * Minimal Datepicker styles */ #ui-datepicker-div { - background: #fff; - border: 1px solid #e5e5e5; - padding: 6px; - box-shadow: 0 3px 5px rgba(0,0,0,.2); + background: #fff; + border: 1px solid #e5e5e5; + padding: 6px; + box-shadow: 0 3px 5px rgba(0,0,0,.2); } .ui-datepicker .ui-datepicker-header { - border: none; + order: none; } .ui-datepicker-calendar .ui-state-default { - text-decoration: none; - background-color: transparent; + text-decoration: none; + background-color: transparent; } .ui-datepicker .ui-datepicker-current-day a { - border-color: #0073aa #006799 #006799; - background: #0085ba; - color: #fff; - font-weight: bold; + border-color: #0073aa #006799 #006799; + background: #0085ba; + color: #fff; + font-weight: bold; } .ui-datepicker .ui-datepicker-today a { - background: #fff; - border: 1px solid #c5c5c5; - font-weight: bold; - color: #000; + background: #fff; + border: 1px solid #c5c5c5; + font-weight: bold; + color: #000; } diff --git a/assets/js/meta-box.js b/assets/js/meta-box.js index 387b818..86fad2a 100644 --- a/assets/js/meta-box.js +++ b/assets/js/meta-box.js @@ -69,14 +69,14 @@ document.addEventListener('DOMContentLoaded', () => { d.setMinutes(timeinput[1]); var string = d.toLocaleString("en-us", { month: "short" }) - + " " - + d.getDate() - + ", " - + d.getFullYear() - + " @ " - + d.getHours() - + ":" - + (d.getMinutes() < 10? '0' : '') + d.getMinutes(); + + " " + + d.getDate() + + ", " + + d.getFullYear() + + " @ " + + d.getHours() + + ":" + + (d.getMinutes() < 10? '0' : '') + d.getMinutes(); $( '#nprone-expiry-display time' ).text( string ); }); diff --git a/classes/NPRAPI.php b/classes/NPRAPI.php index e4c4ef7..f083634 100644 --- a/classes/NPRAPI.php +++ b/classes/NPRAPI.php @@ -10,287 +10,273 @@ */ class NPRAPI { - // HTTP status code = OK - const NPRAPI_STATUS_OK = 200; - - // Default URL for pulling stories - const NPRAPI_PULL_URL = 'https://api.npr.org'; - - // NPRML CONSTANTS - const NPRML_DATA = ''; - const NPRML_NAMESPACE = 'xmlns:nprml=https://api.npr.org/nprml'; - const NPRML_VERSION = '0.92.2'; - - /** - * Initializes an NPRML object. - */ - function __construct() { - $this->request = new stdClass; - $this->request->method = NULL; - $this->request->params = NULL; - $this->request->data = NULL; - $this->request->path = NULL; - $this->request->base = NULL; - $this->request->request_url = NULL; - - - $this->response = new stdClass; - $this->response->id = NULL; - $this->response->code = NULL; - } - - function request() { - - } - - function prepare_request() { - - } - - /** - * This function will send the push request to the NPR API to add/update a story. - * - * @see NPRAPI::send_request() - * - * @param string $nprml - * @param int $ID - */ - function send_request ( $nprml, $ID ) { - - } - - function parse_response() { - $xml = simplexml_load_string($this->response->data); - if (!empty($xml->list->story)) { - $id = $this->get_attribute($xml->list->story, 'id'); - } - $this->response->id = $id ? $id : NULL; - } - - function flatten() { - - } - - /** - * Create NPRML from wordpress post. - * - * @param object $object - - * @return string - * An NPRML string. - */ - function create_NPRML( $object ) { - return ''; - } - - /** - * Parses object. Turns raw XML(NPRML) into various object properties. - */ - function parse() { - if (!empty($this->xml)) { - $xml = $this->xml; - } - - else { - $this->notices[] = 'No XML to parse.'; - return; - } - - $object = simplexml_load_string($xml); - $this->add_simplexml_attributes($object, $this); - - if (!empty($object->message)) { - $this->message->id = $this->get_attribute($object->message, 'id'); - $this->message->level = $this->get_attribute($object->message, 'level'); - } - - if (!empty($object->list->story)) { - foreach ($object->list->story as $story) { - $parsed = new NPRMLEntity(); - $this->add_simplexml_attributes($story, $parsed); - - //Iterate trough the XML document and list all the children - $xml_iterator = new SimpleXMLIterator($story->asXML()); - $key = NULL; - $current = NULL; - for($xml_iterator->rewind(); $xml_iterator->valid(); $xml_iterator->next()) { - $current = $xml_iterator->current(); - $key = $xml_iterator->key(); - - if ($key == 'image' || $key == 'audio' || $key == 'link') { - // images - if ($key == 'image') { - $parsed->{$key}[] = $this->parse_simplexml_element($current); - } - - // audio - if ($key == 'audio') { - $parsed->{$key}[] = $this->parse_simplexml_element($current); - } - - // links - if ($key == 'link') { - $type = $this->get_attribute($current, 'type'); - $parsed->{$key}[$type] = $this->parse_simplexml_element($current); - } - - } - else { - //if ->$key exist, see if it's an array. if it is, add the next child. - if (!empty($parsed->{$key})){ - //if it's not an array, make an array, add the existing element to it - if (!is_array($parsed->{$key})){ - $parsed->{$key} = array( $parsed->{$key} ); - } - // then add the new child. - $parsed->{$key}[] = $this->parse_simplexml_element($current); - } - else { - //The key wasn't parsed already, so just add the current element. - $parsed->{$key} = $this->parse_simplexml_element($current); - } - } - } - $body =''; - if (!empty($parsed->textWithHtml->paragraphs)) { - foreach ($parsed->textWithHtml->paragraphs as $paragraph) { - $body = $body . $paragraph->value . "\n\n"; - } - } - $parsed->body = $body; - $this->stories[] = $parsed; - } - //if the query didn't have a sort parameter, reverse the order so that we end up with - //stories in reverse-chron order. - //there are no params and 'sort=' is not in the URL - if (empty($this->request->params) && !stristr($this->request->request_url, 'sort=')){ - $this->stories = array_reverse($this->stories); - } - //there are params, and sort is not one of them - if (!empty($this->request->params) && !array_key_exists('sort', $this->request->params)){ - $this->stories = array_reverse($this->stories); - } - - } - } - - /** - * Converts SimpleXML element into NPRMLElement. - * - * @param object $element - * A SimpleXML element. - * - * @return object - * An NPRML element. - */ - function parse_simplexml_element($element) { - $NPRMLElement = new NPRMLElement(); - $this->add_simplexml_attributes($element, $NPRMLElement); - if (count($element->children())) { // works for PHP5.2 - foreach ($element->children() as $i => $child) { - if ($i == 'paragraph' || $i == 'mp3') { - if ($i == 'paragraph') { - $paragraph = $this->parse_simplexml_element($child); - $NPRMLElement->paragraphs[$paragraph->num] = $paragraph; - } - if ($i == 'mp3') { - $mp3 = $this->parse_simplexml_element($child); - $NPRMLElement->mp3[$mp3->type] = $mp3; - } - } - else { - //if ->$i exist, see if it's an array. if it is, add the next child. - if (!empty($NPRMLElement->$i)){ - //if it's not an array, make an array, add the existing element to it - if (!is_array($NPRMLElement->$i)) { - $NPRMLElement->$i = array( $NPRMLElement->$i ); - } - // then add the new child. - $NPRMLElement->{$i}[] = $this->parse_simplexml_element($child); - } - else { - $NPRMLElement->$i = $this->parse_simplexml_element($child); - } - } - } - } - else { - $NPRMLElement->value = (string)$element; - } - return $NPRMLElement; - } - - /** - * Extracts value of a given attribute from a SimpleXML element. - * - * @param object $element - * A SimpleXML element. - * - * @param string $attribute - * The name of an attribute of the element. - * - * @return string - * The value of the attribute (if it exists in element). - */ - function get_attribute($element, $attribute) { - foreach ($element->attributes() as $k => $v) { - if ($k == $attribute) { - return (string)$v; - } - } - } - - /** - * Generates basic report of NPRML object. - * - * @return array - * Various messages (strings) . - */ - function report() { - $msg = array(); - $params = ''; - if (isset($this->request->params)) { - foreach ($this->request->params as $k => $v) { - $params .= " [$k => $v]"; - } - $msg[] = 'Request params were: ' . $params; - } - - else { - $msg[] = 'Request had no parameters.'; - } - - if ($this->response->code == self::NPRAPI_STATUS_OK) { - $msg[] = 'Response code was ' . $this->response->code . '.'; - if (isset($this->stories)) { - $msg[] = ' Request returned ' . count($this->stories) . ' stories.'; - } - } - elseif ($this->response->code != self::NPRAPI_STATUS_OK) { - $msg[] = 'Return code was ' . $this->response->code . '.'; - } - else { - $msg[] = 'No info available.'; - } - return $msg; - } - - /** - * Takes attributes of a SimpleXML element and adds them to an object (as properties). - * - * @param object $element - * A SimpleXML element. - * - * @param object $object - * Any PHP object. - */ - function add_simplexml_attributes($element, $object) { - if (count($element->attributes())) { - foreach ($element->attributes() as $attr => $value) { - $object->$attr = (string)$value; - } - } - } + // HTTP status code = OK + const NPRAPI_STATUS_OK = 200; + + // Default URL for pulling stories + const NPRAPI_PULL_URL = 'https://api.npr.org'; + + // NPRML CONSTANTS + const NPRML_DATA = ''; + const NPRML_NAMESPACE = 'xmlns:nprml=https://api.npr.org/nprml'; + const NPRML_VERSION = '0.92.2'; + + /** + * Initializes an NPRML object. + */ + function __construct() { + $this->request = new stdClass; + $this->request->method = NULL; + $this->request->params = NULL; + $this->request->data = NULL; + $this->request->path = NULL; + $this->request->base = NULL; + $this->request->request_url = NULL; + + + $this->response = new stdClass; + $this->response->id = NULL; + $this->response->code = NULL; + } + + function request() { + + } + + function prepare_request() { + + } + + /** + * This function will send the push request to the NPR API to add/update a story. + * + * @see NPRAPI::send_request() + * + * @param string $nprml + * @param int $ID + */ + function send_request( $nprml, $ID ) { + + } + + function parse_response() { + $xml = simplexml_load_string( $this->response->data ); + if ( !empty( $xml->list->story ) ) { + $id = $this->get_attribute( $xml->list->story, 'id' ); + } + $this->response->id = $id ? $id : NULL; + } + + function flatten() { + + } + + /** + * Create NPRML from wordpress post. + * + * @param object $object + * @return string n NPRML string. + */ + function create_NPRML( $object ) { + return ''; + } + + /** + * Parses object. Turns raw XML(NPRML) into various object properties. + */ + function parse() { + if ( !empty( $this->xml ) ) { + $xml = $this->xml; + } else { + $this->notices[] = 'No XML to parse.'; + return; + } + + $object = simplexml_load_string( $xml ); + $this->add_simplexml_attributes( $object, $this ); + + if ( !empty( $object->message ) ) { + $this->message->id = $this->get_attribute( $object->message, 'id' ); + $this->message->level = $this->get_attribute( $object->message, 'level' ); + } + + if ( !empty( $object->list->story ) ) { + foreach ( $object->list->story as $story ) { + $parsed = new NPRMLEntity(); + $this->add_simplexml_attributes( $story, $parsed ); + + //Iterate trough the XML document and list all the children + $xml_iterator = new SimpleXMLIterator( $story->asXML() ); + $key = NULL; + $current = NULL; + for( $xml_iterator->rewind(); $xml_iterator->valid(); $xml_iterator->next() ) { + $current = $xml_iterator->current(); + $key = $xml_iterator->key(); + + if ( $key == 'image' || $key == 'audio' || $key == 'link' ) { + // images + if ( $key == 'image' ) { + $parsed->{ $key }[] = $this->parse_simplexml_element( $current ); + } + + // audio + if ( $key == 'audio' ) { + $parsed->{ $key }[] = $this->parse_simplexml_element( $current ); + } + + // links + if ( $key == 'link' ) { + $type = $this->get_attribute( $current, 'type' ); + $parsed->{ $key }[ $type ] = $this->parse_simplexml_element( $current ); + } + + } else { + //if ->$key exist, see if it's an array. if it is, add the next child. + if ( !empty( $parsed->{ $key } ) ) { + //if it's not an array, make an array, add the existing element to it + if ( !is_array( $parsed->{ $key } ) ) { + $parsed->{ $key } = [ $parsed->{ $key } ]; + } + // then add the new child. + $parsed->{ $key }[] = $this->parse_simplexml_element( $current ); + } else { + //The key wasn't parsed already, so just add the current element. + $parsed->{ $key } = $this->parse_simplexml_element( $current ); + } + } + } + $body =''; + if ( !empty( $parsed->textWithHtml->paragraphs ) ) { + foreach ( $parsed->textWithHtml->paragraphs as $paragraph ) { + $body = $body . $paragraph->value . "\n\n"; + } + } + $parsed->body = $body; + $this->stories[] = $parsed; + } + // if the query didn't have a sort parameter, reverse the order so that we end up with + // stories in reverse-chron order. + // there are no params and 'sort=' is not in the URL + if ( empty( $this->request->params ) && !stristr( $this->request->request_url, 'sort=' ) ) { + $this->stories = array_reverse( $this->stories ); + } + // there are params, and sort is not one of them + if ( !empty( $this->request->params ) && !array_key_exists( 'sort', $this->request->params ) ) { + $this->stories = array_reverse( $this->stories ); + } + } + } + + /** + * Converts SimpleXML element into NPRMLElement. + * + * @param object $element + * A SimpleXML element. + * + * @return object + * An NPRML element. + */ + function parse_simplexml_element( $element ) { + $NPRMLElement = new NPRMLElement(); + $this->add_simplexml_attributes( $element, $NPRMLElement ); + if ( count( $element->children() ) ) { // works for PHP5.2 + foreach ( $element->children() as $i => $child ) { + if ( $i == 'paragraph' || $i == 'mp3' ) { + if ( $i == 'paragraph' ) { + $paragraph = $this->parse_simplexml_element( $child ); + $NPRMLElement->paragraphs[ $paragraph->num ] = $paragraph; + } + if ( $i == 'mp3' ) { + $mp3 = $this->parse_simplexml_element( $child ); + $NPRMLElement->mp3[ $mp3->type ] = $mp3; + } + } else { + //if ->$i exist, see if it's an array. if it is, add the next child. + if ( !empty( $NPRMLElement->$i ) ) { + //if it's not an array, make an array, add the existing element to it + if ( !is_array( $NPRMLElement->$i ) ) { + $NPRMLElement->$i = [ $NPRMLElement->$i ]; + } + // then add the new child. + $NPRMLElement->{ $i }[] = $this->parse_simplexml_element( $child ); + } else { + $NPRMLElement->$i = $this->parse_simplexml_element( $child ); + } + } + } + } else { + $NPRMLElement->value = (string)$element; + } + return $NPRMLElement; + } + + /** + * Extracts value of a given attribute from a SimpleXML element. + * + * @param object $element + * A SimpleXML element. + * + * @param string $attribute + * The name of an attribute of the element. + * + * @return string + * The value of the attribute (if it exists in element). + */ + function get_attribute( $element, $attribute ) { + foreach ( $element->attributes() as $k => $v ) { + if ( $k == $attribute ) { + return (string)$v; + } + } + } + + /** + * Generates basic report of NPRML object. + * + * @return array + * Various messages (strings) . + */ + function report() { + $msg = []; + $params = ''; + if ( isset( $this->request->params ) ) { + foreach ( $this->request->params as $k => $v ) { + $params .= " [$k => $v]"; + } + $msg[] = 'Request params were: ' . $params; + } else { + $msg[] = 'Request had no parameters.'; + } + + if ( $this->response->code == self::NPRAPI_STATUS_OK ) { + $msg[] = 'Response code was ' . $this->response->code . '.'; + if ( isset( $this->stories ) ) { + $msg[] = ' Request returned ' . count( $this->stories ) . ' stories.'; + } + } elseif ( $this->response->code != self::NPRAPI_STATUS_OK ) { + $msg[] = 'Return code was ' . $this->response->code . '.'; + } else { + $msg[] = 'No info available.'; + } + return $msg; + } + + /** + * Takes attributes of a SimpleXML element and adds them to an object (as properties). + * + * @param object $element + * A SimpleXML element. + * + * @param object $object + * Any PHP object. + */ + function add_simplexml_attributes( $element, $object ) { + if ( count( $element->attributes() ) ) { + foreach ( $element->attributes() as $attr => $value ) { + $object->$attr = (string)$value; + } + } + } } /** @@ -304,7 +290,7 @@ class NPRMLEntity { * Basic OOP container for NPRML element. */ class NPRMLElement { - function __toString() { - return $this->value; - } -} + function __toString() { + return $this->value; + } +} \ No newline at end of file diff --git a/classes/NPRAPIWordpress.php b/classes/NPRAPIWordpress.php index 3a0f328..b53a3f3 100644 --- a/classes/NPRAPIWordpress.php +++ b/classes/NPRAPIWordpress.php @@ -14,654 +14,965 @@ */ class NPRAPIWordpress extends NPRAPI { - /** - * Makes HTTP request to NPR API. - * - * @param array $params - * Key/value pairs to be sent (within the request's query string). - * - * - * @param string $path - * The path part of the request URL (i.e., https://example.com/PATH). - * - * @param string $base - * The base URL of the request (i.e., HTTP://EXAMPLE.COM/path) with no trailing slash. - */ - function request( $params = array(), $path = 'query', $base = self::NPRAPI_PULL_URL ) { - - $this->request->params = $params; - $this->request->path = $path; - $this->request->base = $base; - - $queries = array(); - foreach ( $this->request->params as $k => $v ) { - $queries[] = "$k=$v"; - } - $request_url = $this->request->base . '/' . $this->request->path . '?' . implode('&', $queries); - $this->request->request_url = $request_url; - $this->query_by_url($request_url); - } - - /** - * - * Query a single url. If there is not an API Key in the query string, append one, but otherwise just do a straight query - * - * @param string $url -- the full url to query. - */ - function query_by_url( $url ) { - //check to see if the API key is included, if not, add the one from the options - if ( ! stristr( $url, 'apiKey=' ) ) { - $url .= '&apiKey='. get_option( 'ds_npr_api_key' ); - } - - $this->request->request_url = $url; - - //fill out the $this->request->param array so we can know what params were sent - $parsed_url = parse_url( $url ); - if ( ! empty( $parsed_url['query'] ) ) { - $params = explode( '&', $parsed_url['query'] ); - if ( ! empty( $params ) ){ - foreach ( $params as $p ){ - $attrs = explode( '=', $p ); - $this->request->param[$attrs[0]] = $attrs[1]; - } - } - } - $response = wp_remote_get( $url ); - if ( !is_wp_error( $response ) ) { - $this->response = $response; - if ( $response['response']['code'] == self::NPRAPI_STATUS_OK ) { - if ( $response['body'] ) { - $this->xml = $response['body']; - } else { - $this->notice[] = __( 'No data available.' ); - } - } else { - nprstory_show_message( 'An error occurred pulling your story from the NPR API. The API responded with message =' . $response['response']['message'], TRUE ); - } - } else { - $error_text = ''; - if ( ! empty( $response->errors['http_request_failed'][0] ) ) { - $error_text = '
HTTP Error response = '. $response->errors['http_request_failed'][0]; - } - nprstory_show_message( 'Error pulling story for url='.$url . $error_text, TRUE ); - nprstory_error_log( 'Error retrieving story for url='.$url ); - } - } - - /** - * - * This function will go through the list of stories in the object and check to see if there are updates - * available from the NPR API if the pubDate on the API is after the pubDate originally stored locally. - * - * @param bool $publish - * @return int|null $post_id or null - */ - function update_posts_from_stories( $publish = TRUE, $qnum = false ) { + /** + * Makes HTTP request to NPR API. + * + * @param array $params + * Key/value pairs to be sent (within the request's query string). + * + * + * @param string $path + * The path part of the request URL (i.e., https://example.com/PATH). + * + * @param string $base + * The base URL of the request (i.e., HTTP://EXAMPLE.COM/path) with no trailing slash. + */ + function request( $params = [], $path = 'query', $base = self::NPRAPI_PULL_URL ) { + + $this->request->params = $params; + $this->request->path = $path; + $this->request->base = $base; + + $queries = []; + foreach ( $this->request->params as $k => $v ) { + $queries[] = "$k=$v"; + } + $request_url = $this->request->base . '/' . $this->request->path . '?' . implode( '&', $queries ); + $this->request->request_url = $request_url; + $this->query_by_url( $request_url ); + } + + /** + * + * Query a single url. If there is not an API Key in the query string, append one, but otherwise just do a straight query + * + * @param string $url -- the full url to query. + */ + function query_by_url( $url ) { + //check to see if the API key is included, if not, add the one from the options + if ( !stristr( $url, 'apiKey=' ) ) { + $url .= '&apiKey='. get_option( 'ds_npr_api_key' ); + } + + $this->request->request_url = $url; + + //fill out the $this->request->param array so we can know what params were sent + $parsed_url = parse_url( $url ); + if ( !empty( $parsed_url['query'] ) ) { + $params = explode( '&', $parsed_url['query'] ); + if ( !empty( $params ) ) { + foreach ( $params as $p ){ + $attrs = explode( '=', $p ); + $this->request->param[ $attrs[0] ] = $attrs[1]; + } + } + } + $response = wp_remote_get( $url ); + if ( !is_wp_error( $response ) ) { + $this->response = $response; + if ( $response['response']['code'] == self::NPRAPI_STATUS_OK ) { + if ( $response['body'] ) { + $this->xml = $response['body']; + } else { + $this->notice[] = __( 'No data available.' ); + } + } else { + nprstory_show_message( 'An error occurred pulling your story from the NPR API. The API responded with message =' . $response['response']['message'], TRUE ); + } + } else { + $error_text = ''; + if ( !empty( $response->errors['http_request_failed'][0] ) ) { + $error_text = '
HTTP Error response = ' . $response->errors['http_request_failed'][0]; + } + nprstory_show_message( 'Error pulling story for url=' . $url . $error_text, TRUE ); + nprstory_error_log( 'Error retrieving story for url=' . $url ); + } + } + + /** + * + * This function will go through the list of stories in the object and check to see if there are updates + * available from the NPR API if the pubDate on the API is after the pubDate originally stored locally. + * + * @param bool $publish + * @return int|null $post_id or null + */ + function update_posts_from_stories( $publish = TRUE, $qnum = false ) { $pull_post_type = get_option( 'ds_npr_pull_post_type' ); if ( empty( $pull_post_type ) ) { $pull_post_type = 'post'; } + $use_npr_layout = ( !empty( get_option( 'dp_npr_query_use_layout' ) ) ? TRUE : FALSE ); - $post_id = null; + $post_id = null; - if ( ! empty( $this->stories ) ) { + if ( !empty( $this->stories ) ) { $single_story = TRUE; - if ( sizeof( $this->stories ) > 1) { + if ( sizeof( $this->stories ) > 1 ) { $single_story = FALSE; } foreach ( $this->stories as $story ) { - $exists = new WP_Query( - array( 'meta_key' => NPR_STORY_ID_META_KEY, - 'meta_value' => $story->id, - 'post_type' => $pull_post_type, - 'post_status' => 'any' - ) - ); - - //set the mod_date and pub_date to now so that for a new story we will fail the test below and do the update - $post_mod_date = strtotime(date('Y-m-d H:i:s')); - $post_pub_date = $post_mod_date; - - if ( $exists->found_posts ) { - $existing = $exists->post; - $post_id = $existing->ID; - $existing_status = $exists->posts[0]->post_status; - $post_mod_date_meta = get_post_meta( $existing->ID, NPR_LAST_MODIFIED_DATE_KEY ); - if ( ! empty( $post_mod_date_meta[0] ) ) { - $post_mod_date = strtotime( $post_mod_date_meta[0] ); - } - $post_pub_date_meta = get_post_meta( $existing->ID, NPR_PUB_DATE_META_KEY ); - if ( ! empty( $post_pub_date_meta[0] ) ) { - $post_pub_date = strtotime($post_pub_date_meta[0]); - } - } else { - $existing = $existing_status = null; - } - - //add the transcript - $story->body .= $this->get_transcript_body($story); - - $story_date = new DateTime($story->storyDate->value); - $post_date = $story_date->format('Y-m-d H:i:s'); - - //set the story as draft, so we don't try ingesting it - $args = array( - 'post_title' => $story->title, - 'post_excerpt' => $story->teaser, - 'post_content' => $story->body, - 'post_status' => 'draft', - 'post_type' => $pull_post_type, - 'post_date' => $post_date, - ); - if( false !== $qnum ) { - $args['tags_input'] = get_option('ds_npr_query_tags_'.$qnum); - } - //check the last modified date and pub date (sometimes the API just updates the pub date), if the story hasn't changed, just go on - if ( $post_mod_date != strtotime( $story->lastModifiedDate->value ) || $post_pub_date != strtotime( $story->pubDate->value ) ) { - - $by_line = ''; - $byline_link = ''; - $multi_by_line = ''; - //continue to save single byline into npr_byline as is, but also set multi to false - if ( isset( $story->byline->name->value ) ) { //fails if there are multiple bylines or no bylines - $by_line = $story->byline->name->value; - $multi_by_line = 0; //only single author, set multi to false - if ( ! empty( $story->byline->link ) ) { - $links = $story->byline->link; - if ( is_string( $links ) ) { - $byline_link = $links; - } else if ( is_array( $links ) ) { - foreach ( $links as $link ) { - if ( empty( $link->type ) ) { - continue; - } - if ( 'html' === $link->type ) { - $byline_link = $link->value; - } - } - } else if ( $links instanceof NPRMLElement && ! empty( $links->value ) ) { - $byline_link = $links->value; - } - } - } - - //construct delimited string if there are multiple bylines - if ( ! empty( $story->byline ) ) { - $i = 0; - foreach ( (array) $story->byline as $single ) { - if ( ! empty( $single->name->value ) ) { - if ( $i == 0 ) { - $multi_by_line .= $single->name->value; //builds multi byline string without delimiter on first pass - } else { - $multi_by_line .= '|' . $single->name->value; //builds multi byline string with delimiter - } - $by_line = $single->name->value; //overwrites so as to save just the last byline for previous single byline themes - } - if ( ! empty( $single->link ) ) { - foreach( (array) $single->link as $link ) { - if ( empty( $link->type ) ) { - continue; - } - if ( 'html' === $link->type ) { - $byline_link = $link->value; //overwrites so as to save just the last byline link for previous single byline themes - $multi_by_line .= '~' . $link->value; //builds multi byline string links - } - } - } - $i++; - } - } - //set the meta RETRIEVED so when we publish the post, we dont' try ingesting it - $metas = array( - NPR_STORY_ID_META_KEY => $story->id, - NPR_API_LINK_META_KEY => $story->link['api']->value, - NPR_HTML_LINK_META_KEY => $story->link['html']->value, - //NPR_SHORT_LINK_META_KEY => $story->link['short']->value, - NPR_STORY_CONTENT_META_KEY => $story->body, - NPR_BYLINE_META_KEY => $by_line, - NPR_BYLINE_LINK_META_KEY => $byline_link, - NPR_MULTI_BYLINE_META_KEY => $multi_by_line, - NPR_RETRIEVED_STORY_META_KEY => 1, - NPR_PUB_DATE_META_KEY => $story->pubDate->value, - NPR_STORY_DATE_MEATA_KEY => $story->storyDate->value, - NPR_LAST_MODIFIED_DATE_KEY => $story->lastModifiedDate->value, - ); - //get audio - if ( isset($story->audio) ) { - $mp3_array = array(); - $m3u_array = array(); - foreach ( (array) $story->audio as $n => $audio ) { - if ( ! empty( $audio->format->mp3['mp3']) && $audio->permissions->download->allow == 'true' ) { - if ($audio->format->mp3['mp3']->type == 'mp3' ) { - $mp3_array[] = $audio->format->mp3['mp3']->value; - } - if ($audio->format->mp3['m3u']->type == 'm3u' ) { - $m3u_array[] = $audio->format->mp3['m3u']->value; - } - } - } - $metas[NPR_AUDIO_META_KEY] = implode( ',', $mp3_array ); - $metas[NPR_AUDIO_M3U_META_KEY] = implode( ',', $m3u_array ); - } - if ( $existing ) { - $created = false; - $args[ 'ID' ] = $existing->ID; - } else { - $created = true; - } - - /** - * Filters the $args passed to wp_insert_post() - * - * Allow a site to modify the $args passed to wp_insert_post() prior to post being inserted. - * - * @since 1.7 - * - * @param array $args Parameters passed to wp_insert_post() - * @param int $post_id Post ID or NULL if no post ID. - * @param NPRMLEntity $story Story object created during import - * @param bool $created true if not pre-existing, false otherwise - */ - $args = apply_filters( 'npr_pre_insert_post', $args, $post_id, $story, $created ); - - $post_id = wp_insert_post( $args ); - - //now that we have an id, we can add images - //this is the way WP seems to do it, but we couldn't call media_sideload_image or media_ because that returned only the URL - //for the attachment, and we want to be able to set the primary image, so we had to use this method to get the attachment ID. - if ( ! empty( $story->image ) && is_array( $story->image ) && count( $story->image ) ) { - - //are there any images saved for this post, probably on update, but no sense looking of the post didn't already exist - if ( $existing ) { - $image_args = array( - 'order'=> 'ASC', - 'post_mime_type' => 'image', - 'post_parent' => $post_id, - 'post_status' => null, - 'post_type' => 'attachment', - 'post_date' => $post_date, - ); - $attached_images = get_children( $image_args ); - } - foreach ( (array) $story->image as $image ) { - $image_url = ''; - //check the and then the crops, in this order "enlargement", "standard" if they don't exist, just get the image->src - if ( ! empty( $image->enlargement ) ) { - $image_url = $image->enlargement->src; - } else { - if ( ! empty( $image->crop ) && is_array( $image->crop ) ) { - foreach ( $image->crop as $crop ) { - if ( empty( $crop->type ) ) { - continue; - } - if ( 'enlargement' === $crop->type ) { - $image_url = $crop->src; - } - } - if ( empty( $image_url ) ) { - foreach ( $image->crop as $crop ) { - if ( empty( $crop->type ) ) { - continue; - } - if ( 'standard' === $crop->type ) { - $image_url = $crop->src; - } - } - } - } - } - - if ( empty( $image_url ) && ! empty( $image->src ) ) { - $image_url = $image->src; - } - nprstory_error_log( 'Got image from: ' . $image_url ); - // Download file to temp location - $tmp = download_url( $image_url ); - - // Set variables for storage - // fix file filename for query strings - preg_match( '/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $image_url, $matches ); - $file_array['name'] = basename( $matches[0] ); - $file_array['tmp_name'] = $tmp; - - $file_OK = TRUE; - // If error storing temporarily, unlink - if ( is_wp_error( $tmp ) ) { - @unlink($file_array['tmp_name']); - $file_array['tmp_name'] = ''; - $file_OK = FALSE; - } - - // do the validation and storage stuff - require_once( ABSPATH . 'wp-admin/includes/image.php'); // needed for wp_read_image_metadata used by media_handle_sideload during cron - $id = media_handle_sideload( $file_array, $post_id, $image->title->value ); - // If error storing permanently, unlink - if ( is_wp_error($id) ) { - @unlink( $file_array['tmp_name'] ); - $file_OK = FALSE; - } else { - $image_post = get_post( $id ); - if ( ! empty( $attached_images ) ) { - foreach( $attached_images as $att_image ) { - //see if the filename is very similar - $att_guid = explode( '.', $att_image->guid ); - //so if the already attached image name is part of the name of the file - //coming in, ignore the new/temp file, it's probably the same - if ( strstr ( $image_post->guid, $att_guid[0] ) ) { - @unlink( $file_array['tmp_name'] ); - wp_delete_attachment( $id ); - $file_OK = FALSE; - } - } - } - } - - //set the primary image - if ( $image->type == 'primary' && $file_OK ) { - add_post_meta( $post_id, '_thumbnail_id', $id, true ); - //get any image meta data and attatch it to the image post - $image_metas = array( - NPR_IMAGE_CREDIT_META_KEY =>$image->producer->value, - NPR_IMAGE_AGENCY_META_KEY =>$image->provider->value, - NPR_IMAGE_CAPTION_META_KEY =>$image->caption->value, - ); - foreach ( $image_metas as $k => $v ) { - update_post_meta( $post_id, $k, $v ); - } - } - } - } - - /** - * Filters the post meta before series of update_post_meta() calls - * - * Allow a site to modify the post meta values prior to - * passing each element via update_post_meta(). - * - * @since 1.7 - * - * @param array $metas Array of key/value pairs to be updated - * @param int $post_id Post ID or NULL if no post ID. - * @param NPRMLEntity $story Story object created during import - * @param bool $created true if not pre-existing, false otherwise - */ - $metas = apply_filters( 'npr_pre_update_post_metas', $metas, $post_id, $story, $created ); - - foreach ( $metas as $k => $v ) { - update_post_meta( $post_id, $k, $v ); - } - - $args = array( - 'post_title' => $story->title, - 'post_content' => $story->body, - 'post_excerpt' => $story->teaser, - 'post_type' => $pull_post_type, - 'ID' => $post_id, - 'post_date' => $post_date, - ); - - //set author - if ( ! empty( $by_line ) ) { - $userQuery = new WP_User_Query( array( - 'search' => trim( $by_line ), - 'search_columns' => array( - 'nickname' - ) - ) - ); - - $user_results = $userQuery->get_results(); - if ( count( $user_results ) == 1 && isset( $user_results[0]->data->ID) ) { - $args['post_author'] = $user_results[0]->data->ID; - } - } - - //now set the status - if ( ! $existing ) { - if ( $publish ) { - $args['post_status'] = 'publish'; - } else { - $args['post_status'] = 'draft'; - } - } else { - //if the post existed, save its status - $args['post_status'] = $existing_status; - } - - /** - * Filters the $args passed to wp_insert_post() used to update - * - * Allow a site to modify the $args passed to wp_insert_post() prior to post being updated. - * - * @since 1.7 - * - * @param array $args Parameters passed to wp_insert_post() - * @param int $post_id Post ID or NULL if no post ID. - * @param NPRMLEntity $story Story object created during import - */ - $args = apply_filters( 'npr_pre_update_post', $args, $post_id, $story ); - - $post_id = wp_insert_post( $args ); - } - - //set categories for story - $category_ids = array(); - if ( isset( $story->parent ) ) { - if ( is_array( $story->parent ) ) { - foreach ( $story->parent as $parent ) { - if ( isset( $parent->type ) && 'category' === $parent->type ) { - - /** - * Filters term name prior to lookup of terms - * - * Allow a site to modify the terms looked-up before adding them to list of categories. - * - * @since 1.7 - * - * @param string $term_name Name of term - * @param int $post_id Post ID or NULL if no post ID. - * @param NPRMLEntity $story Story object created during import - */ - $term_name = apply_filters( 'npr_resolve_category_term', $parent->title->value, $post_id, $story ); - $category_id = get_cat_ID( $term_name ); - - if ( ! empty( $category_id ) ) { - $category_ids[] = $category_id; - } - } - } - } elseif ( isset( $story->parent->type ) && $story->parent->type === 'category') { - /* - * Filters term name prior to lookup of terms - * - * Allow a site to modify the terms looked-up before adding them to list of categories. - * - * @since 1.7 - * - * @param string $term_name Name of term - * @param int $post_id Post ID or NULL if no post ID. - * @param NPRMLEntity $story Story object created during import - */ - $term_name = apply_filters('npr_resolve_category_term', $story->parent->title->value, $post_id, $story ); - $category_id = get_cat_ID( $term_name ); - if ( ! empty( $category_id) ) { - $category_ids[] = $category_id; - } - } + $exists = new WP_Query([ + 'meta_key' => NPR_STORY_ID_META_KEY, + 'meta_value' => $story->id, + 'post_type' => $pull_post_type, + 'post_status' => 'any' + ]); + + // set the mod_date and pub_date to now so that for a new story we will fail the test below and do the update + $post_mod_date = strtotime( date( 'Y-m-d H:i:s' ) ); + $post_pub_date = $post_mod_date; + $cats = []; + if ( $exists->found_posts ) { + $existing = $exists->post; + $post_id = $existing->ID; + $existing_status = $exists->posts[0]->post_status; + $post_mod_date_meta = get_post_meta( $existing->ID, NPR_LAST_MODIFIED_DATE_KEY ); + // to store the category ids of the existing post + if ( !empty( $post_mod_date_meta[0] ) ) { + $post_mod_date = strtotime( $post_mod_date_meta[0] ); + } + $post_pub_date_meta = get_post_meta( $existing->ID, NPR_PUB_DATE_META_KEY ); + if ( !empty( $post_pub_date_meta[0] ) ) { + $post_pub_date = strtotime( $post_pub_date_meta[0] ); + } + // get ids of existing categories for post + $cats = wp_get_post_categories( $post_id ); + } else { + $existing = $existing_status = null; + } + + $npr_has_layout = FALSE; + $npr_has_video = FALSE; + if ( $use_npr_layout ) { + // get the "NPR layout" version if available and the "use rich layout" option checked in settings + $npr_layout = $this->get_body_with_layout( $story ); + if ( !empty( $npr_layout['body'] ) ) { + $story->body = $npr_layout['body']; + $npr_has_layout = TRUE; + $npr_has_video = $npr_layout['has_video']; + } + } + // add the transcript + $story->body .= $this->get_transcript_body( $story ); + + $story_date = new DateTime( $story->storyDate->value ); + $post_date = $story_date->format( 'Y-m-d H:i:s' ); + + // set the story as draft, so we don't try ingesting it + $args = [ + 'post_title' => $story->title, + 'post_excerpt' => $story->teaser, + 'post_content' => $story->body, + 'post_status' => 'draft', + 'post_type' => $pull_post_type, + 'post_date' => $post_date + ]; + $wp_category_ids = []; + $wp_category_id = ""; + if ( false !== $qnum ) { + $args['tags_input'] = get_option( 'ds_npr_query_tags_' . $qnum ); + if ( $pull_post_type == 'post' ) { + // Get Default category from options table and store in array for post_array + $wp_category_id = intval( get_option( 'ds_npr_query_category_' . $qnum ) ); + $wp_category_ids[] = $wp_category_id; + } + } else { + // Assign default category to new post + if ( $existing === null ) { + $wp_category_id = intval( get_option( 'default_category' ) ); + $wp_category_ids[] = $wp_category_id; + } + } + if ( 0 < sizeof( $cats ) ) { + // merge arrays and remove duplicate ids + $wp_category_ids = array_unique( array_merge( $wp_category_ids, $cats ) ); + } + // check the last modified date and pub date (sometimes the API just updates the pub date), if the story hasn't changed, just go on + if ( $post_mod_date != strtotime( $story->lastModifiedDate->value ) || $post_pub_date != strtotime( $story->pubDate->value ) ) { + $by_line = ''; + $byline_link = ''; + $multi_by_line = ''; + // continue to save single byline into npr_byline as is, but also set multi to false + if ( isset( $story->byline->name->value ) ) { // fails if there are multiple bylines or no bylines + $by_line = $story->byline->name->value; + $multi_by_line = 0; // only single author, set multi to false + if ( !empty( $story->byline->link ) ) { + $links = $story->byline->link; + if ( is_string( $links ) ) { + $byline_link = $links; + } elseif ( is_array( $links ) ) { + foreach ( $links as $link ) { + if ( empty( $link->type ) ) { + continue; + } + if ( 'html' === $link->type ) { + $byline_link = $link->value; + } + } + } elseif ( $links instanceof NPRMLElement && ! empty( $links->value ) ) { + $byline_link = $links->value; + } + } + } + + // construct delimited string if there are multiple bylines + if ( !empty( $story->byline ) ) { + $i = 0; + foreach ( (array)$story->byline as $single ) { + if ( !empty( $single->name->value ) ) { + if ( $i == 0 ) { + $multi_by_line .= $single->name->value; // builds multi byline string without delimiter on first pass + } else { + $multi_by_line .= '|' . $single->name->value; // builds multi byline string with delimiter + } + $by_line = $single->name->value; // overwrites so as to save just the last byline for previous single byline themes + } + if ( !empty( $single->link ) ) { + foreach( (array)$single->link as $link ) { + if ( empty( $link->type ) ) { + continue; + } + if ( 'html' === $link->type ) { + $byline_link = $link->value; // overwrites so as to save just the last byline link for previous single byline themes + $multi_by_line .= '~' . $link->value; // builds multi byline string links + } + } + } + $i++; + } + } + // set the meta RETRIEVED so when we publish the post, we don't try ingesting it + $metas = [ + NPR_STORY_ID_META_KEY => $story->id, + NPR_API_LINK_META_KEY => $story->link['api']->value, + NPR_HTML_LINK_META_KEY => $story->link['html']->value, + // NPR_SHORT_LINK_META_KEY => $story->link['short']->value, + NPR_STORY_CONTENT_META_KEY => $story->body, + NPR_BYLINE_META_KEY => $by_line, + NPR_BYLINE_LINK_META_KEY => $byline_link, + NPR_MULTI_BYLINE_META_KEY => $multi_by_line, + NPR_RETRIEVED_STORY_META_KEY => 1, + NPR_PUB_DATE_META_KEY => $story->pubDate->value, + NPR_STORY_DATE_MEATA_KEY => $story->storyDate->value, + NPR_LAST_MODIFIED_DATE_KEY => $story->lastModifiedDate->value, + NPR_STORY_HAS_LAYOUT_META_KEY => $npr_has_layout, + NPR_STORY_HAS_VIDEO_META_KEY => $npr_has_video + ]; + // get audio + if ( isset( $story->audio ) ) { + $mp3_array = $m3u_array = []; + foreach ( (array)$story->audio as $n => $audio ) { + if ( !empty( $audio->format->mp3['mp3'] ) && $audio->permissions->download->allow == 'true' ) { + if ( $audio->format->mp3['mp3']->type == 'mp3' ) { + $mp3_array[] = $audio->format->mp3['mp3']->value; + } + if ( $audio->format->mp3['m3u']->type == 'm3u' ) { + $m3u_array[] = $audio->format->mp3['m3u']->value; + } + } + } + $metas[NPR_AUDIO_META_KEY] = implode( ',', $mp3_array ); + $metas[NPR_AUDIO_M3U_META_KEY] = implode( ',', $m3u_array ); + } + if ( $existing ) { + $created = false; + $args['ID'] = $existing->ID; + } else { + $created = true; + } + + /** + * Filters the $args passed to wp_insert_post() + * + * Allow a site to modify the $args passed to wp_insert_post() prior to post being inserted. + * + * @since 1.7 + * + * @param array $args Parameters passed to wp_insert_post() + * @param int $post_id Post ID or NULL if no post ID. + * @param NPRMLEntity $story Story object created during import + * @param bool $created true if not pre-existing, false otherwise + */ + + if ( $npr_has_layout ) { + // keep WP from stripping content from NPR posts + kses_remove_filters(); + } + + $args = apply_filters( 'npr_pre_insert_post', $args, $post_id, $story, $created ); + $post_id = wp_insert_post( $args ); + wp_set_post_terms( $post_id, $wp_category_ids, 'category', true ); + + if ($npr_has_layout) { + // re-enable the built-in content stripping + kses_init_filters(); + } + + // now that we have an id, we can add images + // this is the way WP seems to do it, but we couldn't call media_sideload_image or media_ because that returned only the URL + // for the attachment, and we want to be able to set the primary image, so we had to use this method to get the attachment ID. + if ( !empty( $story->image ) && is_array( $story->image ) && count( $story->image ) ) { + + // are there any images saved for this post, probably on update, but no sense looking of the post didn't already exist + if ( $existing ) { + $image_args = [ + 'order'=> 'ASC', + 'post_mime_type' => 'image', + 'post_parent' => $post_id, + 'post_status' => null, + 'post_type' => 'attachment', + 'post_date' => $post_date + ]; + $attached_images = get_children( $image_args ); + } + foreach ( (array)$story->image as $image ) { + + // only sideload the primary image if using the npr layout + if ( ( $image->type != 'primary' ) && $npr_has_layout ) { + continue; + } + $image_url = ''; + // check the and then the crops, in this order "enlargement", "standard" if they don't exist, just get the image->src + if ( !empty( $image->enlargement ) ) { + $image_url = $image->enlargement->src; + } else { + if ( !empty( $image->crop ) && is_array( $image->crop ) ) { + foreach ( $image->crop as $crop ) { + if ( empty( $crop->type ) ) { + continue; + } + if ( 'enlargement' === $crop->type ) { + $image_url = $crop->src; + } + } + if ( empty( $image_url ) ) { + foreach ( $image->crop as $crop ) { + if ( empty( $crop->type ) ) { + continue; + } + if ( 'standard' === $crop->type ) { + $image_url = $crop->src; + } + } + } + } + } + + if ( empty( $image_url ) && !empty( $image->src ) ) { + $image_url = $image->src; + } + nprstory_error_log( 'Got image from: ' . $image_url ); + // Download file to temp location + $tmp = download_url( $image_url ); + + // Set variables for storage + // fix file filename for query strings + preg_match( '/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $image_url, $matches ); + $file_array['name'] = basename( $matches[0] ); + $file_array['tmp_name'] = $tmp; + + $file_OK = TRUE; + // If error storing temporarily, unlink + if ( is_wp_error( $tmp ) ) { + @unlink( $file_array['tmp_name'] ); + $file_array['tmp_name'] = ''; + $file_OK = FALSE; + } + + // do the validation and storage stuff + require_once( ABSPATH . 'wp-admin/includes/image.php' ); // needed for wp_read_image_metadata used by media_handle_sideload during cron + $id = media_handle_sideload( $file_array, $post_id, $image->title->value ); + // If error storing permanently, unlink + if ( is_wp_error( $id ) ) { + @unlink( $file_array['tmp_name'] ); + $file_OK = FALSE; + } else { + $image_post = get_post( $id ); + if ( !empty( $attached_images ) ) { + foreach( $attached_images as $att_image ) { + // see if the filename is very similar + // $att_guid = explode( '.', $att_image->guid ); + $attach_url = wp_get_attachment_url( $att_image->ID ); + $attach_url_parse = parse_url( $attach_url ); + $attach_url_parts = pathinfo( $attach_url_parse['path'] ); + + $imagep_attach_url = wp_get_attachment_url( $image_post->ID ); + $imagep_url_parse = parse_url( $imagep_attach_url ); + $imagep_url_parts = pathinfo( $imagep_url_parse['path'] ); + // so if the already attached image name is part of the name of the file + // coming in, ignore the new/temp file, it's probably the same + if ( strtolower( $attach_url_parts['filename'] ) == strtolower( $imagep_url_parts['filename'] ) ) { + @unlink( $file_array['tmp_name'] ); + wp_delete_attachment( $id ); + $file_OK = FALSE; + } + } + } + } + + //set the primary image + if ( $image->type == 'primary' && $file_OK ) { + add_post_meta( $post_id, '_thumbnail_id', $id, true ); + //get any image meta data and attatch it to the image post + $image_metas = [ + NPR_IMAGE_CREDIT_META_KEY => $image->producer->value, + NPR_IMAGE_AGENCY_META_KEY => $image->provider->value, + NPR_IMAGE_CAPTION_META_KEY => $image->caption->value + ]; + foreach ( $image_metas as $k => $v ) { + update_post_meta( $post_id, $k, $v ); + } + } + } + } + + /** + * Filters the post meta before series of update_post_meta() calls + * + * Allow a site to modify the post meta values prior to + * passing each element via update_post_meta(). + * + * @since 1.7 + * + * @param array $metas Array of key/value pairs to be updated + * @param int $post_id Post ID or NULL if no post ID. + * @param NPRMLEntity $story Story object created during import + * @param bool $created true if not pre-existing, false otherwise + */ + $metas = apply_filters( 'npr_pre_update_post_metas', $metas, $post_id, $story, $created ); + + foreach ( $metas as $k => $v ) { + update_post_meta( $post_id, $k, $v ); + } + + $args = [ + 'post_title' => $story->title, + 'post_content' => $story->body, + 'post_excerpt' => $story->teaser, + 'post_type' => $pull_post_type, + 'ID' => $post_id, + 'post_date' => $post_date + ]; + + //set author + if ( ! empty( $by_line ) ) { + $userQuery = new WP_User_Query([ + 'search' => trim( $by_line ), + 'search_columns' => [ 'nickname' ] + ]); + + $user_results = $userQuery->get_results(); + if ( count( $user_results ) == 1 && isset( $user_results[0]->data->ID ) ) { + $args['post_author'] = $user_results[0]->data->ID; + } + } + + //now set the status + if ( !$existing ) { + if ( $publish ) { + $args['post_status'] = 'publish'; + } else { + $args['post_status'] = 'draft'; + } + } else { + //if the post existed, save its status + $args['post_status'] = $existing_status; + } + + /** + * Filters the $args passed to wp_insert_post() used to update + * + * Allow a site to modify the $args passed to wp_insert_post() prior to post being updated. + * + * @since 1.7 + * + * @param array $args Parameters passed to wp_insert_post() + * @param int $post_id Post ID or NULL if no post ID. + * @param NPRMLEntity $story Story object created during import + */ + + if ( $npr_has_layout ) { + // keep WP from stripping content from NPR posts + kses_remove_filters(); + } + + $args = apply_filters( 'npr_pre_update_post', $args, $post_id, $story ); + $post_id = wp_insert_post( $args ); + + if ( $npr_has_layout ) { + // re-enable content stripping + kses_init_filters(); + } + } + // set categories for story + $category_ids = []; + $category_ids = array_merge( $category_ids, $wp_category_ids ); + if ( isset( $story->parent ) ) { + if ( is_array( $story->parent ) ) { + foreach ( $story->parent as $parent ) { + if ( isset( $parent->type ) && 'category' === $parent->type ) { + + /** + * Filters term name prior to lookup of terms + * + * Allow a site to modify the terms looked-up before adding them to list of categories. + * + * @since 1.7 + * + * @param string $term_name Name of term + * @param int $post_id Post ID or NULL if no post ID. + * @param NPRMLEntity $story Story object created during import + */ + $term_name = apply_filters( 'npr_resolve_category_term', $parent->title->value, $post_id, $story ); + $category_id = get_cat_ID( $term_name ); + + if ( !empty( $category_id ) ) { + $category_ids[] = $category_id; + } + } + } + } elseif ( isset( $story->parent->type ) && $story->parent->type === 'category' ) { + /* + * Filters term name prior to lookup of terms + * + * Allow a site to modify the terms looked-up before adding them to list of categories. + * + * @since 1.7 + * + * @param string $term_name Name of term + * @param int $post_id Post ID or NULL if no post ID. + * @param NPRMLEntity $story Story object created during import + */ + $term_name = apply_filters( 'npr_resolve_category_term', $story->parent->title->value, $post_id, $story ); + $category_id = get_cat_ID( $term_name ); + if ( !empty( $category_id ) ) { + $category_ids[] = $category_id; + } + } } /* - * Filters category_ids prior to setting assigning to the post. - * - * Allow a site to modify category IDs before assigning to the post. - * - * @since 1.7 - * - * @param int[] $category_ids Array of Category IDs to assign to post identified by $post_id - * @param int $post_id Post ID or NULL if no post ID. - * @param NPRMLEntity $story Story object created during import - */ + * Filters category_ids prior to setting assigning to the post. + * + * Allow a site to modify category IDs before assigning to the post. + * + * @since 1.7 + * + * @param int[] $category_ids Array of Category IDs to assign to post identified by $post_id + * @param int $post_id Post ID or NULL if no post ID. + * @param NPRMLEntity $story Story object created during import + */ $category_ids = apply_filters( 'npr_pre_set_post_categories', $category_ids, $post_id, $story ); if ( 0 < count( $category_ids ) && is_integer( $post_id ) ) { wp_set_post_categories( $post_id, $category_ids ); } - - } - if ( $single_story ) { - return isset( $post_id ) ? $post_id : 0; - } - } - return null; - } - - - - /** - * Create NPRML from wordpress post. - * - * @param object $post - * A wordpress post. - * - * @return string - * An NPRML string. - */ - function create_NPRML( $post ) { - //using some old helper code - return nprstory_to_nprml( $post ); - } - - /** - * This function will send the push request to the NPR API to add/update a story. - * - * @see NPRAPI::send_request() - * - * @param string $nprml - * @param int $post_ID - */ - function send_request ( $nprml, $post_ID ) { - $error_text = ''; - $org_id = get_option( 'ds_npr_api_org_id' ); - if ( ! empty( $org_id ) ) { - $url = add_query_arg( array( - 'orgId' => $org_id, - 'apiKey' => get_option( 'ds_npr_api_key' ) - ), get_option( 'ds_npr_api_push_url' ) . '/story' ); - - nprstory_error_log( 'Sending nprml = ' . $nprml ); - - $result = wp_remote_post( $url, array( 'body' => $nprml ) ); - if ( ! is_wp_error( $result ) ) { - if ( $result['response']['code'] == 200 ) { - $body = wp_remote_retrieve_body( $result ); - if ( $body ) { - $response_xml = simplexml_load_string( $body ); - $npr_story_id = (string) $response_xml->list->story['id']; - update_post_meta( $post_ID, NPR_STORY_ID_META_KEY, $npr_story_id ); - } else { - error_log( 'Error returned from NPR Story API with status code 200 OK but failed wp_remote_retrieve_body: ' . print_r( $result, true ) ); // debug use - } - } else { - $error_text = ''; - if ( ! empty( $result['response']['message'] ) ) { - $error_text = 'Error pushing story with post_id = '. $post_ID .' for url='.$url . ' HTTP Error response = '. $result['response']['message']; - } - $body = wp_remote_retrieve_body( $result ); - - if ( $body ) { - $response_xml = simplexml_load_string( $body ); - $error_text .= ' API Error Message = ' . $response_xml->message->text; - } - error_log('Error returned from NPR Story API with status code other than 200 OK: ' . $error_text); // debug use - } - } else { - $error_text = 'WP_Error returned when sending story with post_ID ' . $post_ID . ' for url ' . $url . ' to NPR Story API:'. $result->get_error_message(); - error_log( $error_text ); // debug use - } - } else { - $error_text = 'OrgID was not set when tried to push post_ID ' . $post_ID . ' to the NPR Story API.'; - error_log ( $error_text ); // debug use - } + if ( $single_story ) { + return isset( $post_id ) ? $post_id : 0; + } + } + return null; + } + + /** + * Create NPRML from wordpress post. + * + * @param object $post + * A wordpress post. + * + * @return string + * An NPRML string. + */ + function create_NPRML( $post ) { + // using some old helper code + return nprstory_to_nprml( $post ); + } + + /** + * This function will send the push request to the NPR API to add/update a story. + * + * @see NPRAPI::send_request() + * + * @param string $nprml + * @param int $post_ID + */ + function send_request ( $nprml, $post_ID ) { + $error_text = ''; + $org_id = get_option( 'ds_npr_api_org_id' ); + if ( !empty( $org_id ) ) { + $url = add_query_arg( [ + 'orgId' => $org_id, + 'apiKey' => get_option( 'ds_npr_api_key' ) + ], get_option( 'ds_npr_api_push_url' ) . '/story' ); + + nprstory_error_log( 'Sending nprml = ' . $nprml ); + + $result = wp_remote_post( $url, ['body' => $nprml ] ); + if ( !is_wp_error( $result ) ) { + if ( $result['response']['code'] == 200 ) { + $body = wp_remote_retrieve_body( $result ); + if ( $body ) { + $response_xml = simplexml_load_string( $body ); + $npr_story_id = (string)$response_xml->list->story['id']; + update_post_meta( $post_ID, NPR_STORY_ID_META_KEY, $npr_story_id ); + } else { + error_log( 'Error returned from NPR Story API with status code 200 OK but failed wp_remote_retrieve_body: ' . print_r( $result, true ) ); // debug use + } + } else { + $error_text = ''; + if ( !empty( $result['response']['message'] ) ) { + $error_text = 'Error pushing story with post_id = ' . $post_ID . ' for url=' . $url . ' HTTP Error response = ' . $result['response']['message']; + } + $body = wp_remote_retrieve_body( $result ); + + if ( $body ) { + $response_xml = simplexml_load_string( $body ); + $error_text .= ' API Error Message = ' . $response_xml->message->text; + } + error_log( 'Error returned from NPR Story API with status code other than 200 OK: ' . $error_text ); // debug use + } + } else { + $error_text = 'WP_Error returned when sending story with post_ID ' . $post_ID . ' for url ' . $url . ' to NPR Story API:' . $result->get_error_message(); + error_log( $error_text ); // debug use + } + } else { + $error_text = 'OrgID was not set when tried to push post_ID ' . $post_ID . ' to the NPR Story API.'; + error_log( $error_text ); // debug use + } // Add errors to the post that you just tried to push - if ( ! empty( $error_text ) ) { - update_post_meta( $post_ID, NPR_PUSH_STORY_ERROR, $error_text ); - } - else { + if ( !empty( $error_text ) ) { + update_post_meta( $post_ID, NPR_PUSH_STORY_ERROR, $error_text ); + } else { delete_post_meta( $post_ID, NPR_PUSH_STORY_ERROR ); } - } - - /** - * - * Because wordpress doesn't offer a method=DELETE for wp_remote_post, we needed to write a curl version to send delete - * requests to the NPR API - * - * @param $api_id - */ - function send_delete( $api_id ) { - $url = add_query_arg( array( - 'orgId' => get_option( 'ds_npr_api_org_id' ), - 'apiKey' => get_option( 'ds_npr_api_key' ), + } + + /** + * + * Because wordpress doesn't offer a method=DELETE for wp_remote_post, we needed to write a curl version to send delete + * requests to the NPR API + * + * @param $api_id + */ + function send_delete( $api_id ) { + $url = add_query_arg( [ + 'orgId' => get_option( 'ds_npr_api_org_id' ), + 'apiKey' => get_option( 'ds_npr_api_key' ), 'id' => $api_id - ), get_option( 'ds_npr_api_push_url' ) . '/story' ); - - //wp doesn't let me do a wp_remote_post with method=DELETE so we have to make our own curl request. fun - //a lot of this code came from WP's class-http object - //$result = wp_remote_post( $url, array( 'method' => 'DELETE' ) ); - $handle = curl_init(); - curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'DELETE' ); - curl_setopt( $handle, CURLOPT_URL, $url ); - curl_setopt( $handle, CURLOPT_RETURNTRANSFER, TRUE ); + ], get_option( 'ds_npr_api_push_url' ) . '/story' ); + + // wp doesn't let me do a wp_remote_post with method=DELETE so we have to make our own curl request. fun + // a lot of this code came from WP's class-http object + // $result = wp_remote_post( $url, array( 'method' => 'DELETE' ) ); + $handle = curl_init(); + curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'DELETE' ); + curl_setopt( $handle, CURLOPT_URL, $url ); + curl_setopt( $handle, CURLOPT_RETURNTRANSFER, TRUE ); curl_exec( $handle ); curl_close( $handle ); - } - - /** - * - * This function will check a story to see if there are transcripts that should go with it, if there are - * we'll return the transcript as one big strang with Transcript at the top and each paragraph separated by

- * - * @param string $story - * @return string - */ - function get_transcript_body( $story ) { - $transcript_body = ""; - if ( ! empty( $story->transcript ) && is_array( $story->transcript ) ) { - foreach ( $story->transcript as $transcript ) { - if ( empty( $transcript->link ) ) { - continue; - } - foreach ( (array) $transcript->link as $link ) { - if ( ! isset( $link->type ) || 'api' !== $link->type ) { - continue; - } - $response = wp_remote_get( $link->value ); - if ( is_wp_error( $response ) ) { - /** - * @var WP_Error $response - */ - $code = $response->get_error_code(); - $message = $response->get_error_message(); - $message = sprintf( 'Error requesting story transcript via API URL: %s (%s [%d])', $link->value, $message, $code ); - error_log( $message ); - continue; - } - $body_xml = simplexml_load_string( $response[ 'body' ] ); - if ( empty( $body_xml->paragraph ) || ! is_array( $body_xml->paragraph ) ) { - continue; - } - $transcript_body .= "

Transcript :

"; - foreach ( $body_xml->paragraph as $paragraph ) { - $transcript_body .= '

' . ( strip_tags( $paragraph ) ) . '

'; - } - } - } - - } - - return $transcript_body; - } + } + + /** + * + * This function will check a story to see if there are transcripts that should go with it, if there are + * we'll return the transcript as one big strang with Transcript at the top and each paragraph separated by

+ * + * @param string $story + * @return string + */ + function get_transcript_body( $story ) { + $transcript_body = ""; + if ( !empty( $story->transcript ) && is_array( $story->transcript ) ) { + foreach ( $story->transcript as $transcript ) { + if ( empty( $transcript->link ) ) { + continue; + } + foreach ( (array)$transcript->link as $link ) { + if ( !isset( $link->type ) || 'api' !== $link->type ) { + continue; + } + $response = wp_remote_get( $link->value ); + if ( is_wp_error( $response ) ) { + /** + * @var WP_Error $response + */ + $code = $response->get_error_code(); + $message = $response->get_error_message(); + $message = sprintf( 'Error requesting story transcript via API URL: %s (%s [%d])', $link->value, $message, $code ); + error_log( $message ); + continue; + } + $body_xml = simplexml_load_string( $response[ 'body' ] ); + if ( empty( $body_xml->paragraph ) || !is_array( $body_xml->paragraph ) ) { + continue; + } + $transcript_body .= "

Transcript :

"; + foreach ( $body_xml->paragraph as $paragraph ) { + $transcript_body .= '

' . ( strip_tags( $paragraph ) ) . '

'; + } + } + } + + } + return $transcript_body; + } + + /** + * + * This function will check a story to see if it has a layout object, if there is + * we'll format the body with any images, externalAssets, or htmlAssets inserted in the order they are in the layout + * and return an array of the transformed body and flags for what sort of elements are returned + * + * @param NPRMLEntity $story Story object created during import + * @return array with reconstructed body and flags describing returned elements + */ + function get_body_with_layout( $story ) { + $returnary = [ 'body' => FALSE, 'has_layout' => FALSE, 'has_image' => FALSE, 'has_video' => FALSE, 'has_external' => FALSE ]; + $body_with_layout = ""; + if ( !empty( $story->layout ) ) { + // simplify the arrangement of the storytext object + $layoutarry = []; + foreach( $story->layout->storytext as $type => $elements ) { + if ( !is_array( $elements ) ) { + $elements = [ $elements ]; + } + foreach ( $elements as $element ) { + $num = $element->num; + $reference = $element->refId; + if ( $type == 'text' ) { + // only paragraphs don't have a refId, they use num instead + $reference = $element->paragraphNum; + } + $layoutarry[ (int)$num ] = [ 'type' => $type, 'reference' => $reference ]; + } + } + ksort($layoutarry); + $returnary['has_layout'] = TRUE; + + $paragraphs = []; + $num = 1; + foreach ( $story->textWithHtml->paragraphs as $paragraph ) { + $partext = (string)$paragraph->value; + $paragraphs[ $num ] = $partext; + $num++; + } + + $storyimages = []; + if ( isset($story->image ) ) { + $storyimages_array = []; + if ( isset( $story->image->id ) ) { + $storyimages_array[] = $story->image; + } else { + // sometimes there are multiple objects + foreach ( (array)$story->image as $stryimage ) { + if ( isset( $stryimage->id ) ) { + $storyimages_array[] = $stryimage; + } + } + } + foreach ( $storyimages_array as $image ) { + $image_url = FALSE; + $is_portrait = FALSE; + if ( !empty( $image->enlargement ) ) { + $image_url = $image->enlargement->src; + } + if ( !empty( $image->crop ) ) { + if ( !is_array( $image->crop ) ) { + $cropobj = $image->crop; + unset( $image->crop ); + $image->crop = [ $cropobj ]; + } + foreach ( $image->crop as $crop ) { + if ( empty( $crop->primary ) ) { + continue; + } + $image_url = $crop->src; + if ( $crop->type == 'custom' && ( (int)$crop->height > (int)$crop->width ) ) { + $is_portrait = TRUE; + } + break; + } + } + if ( empty( $image_url ) && !empty( $image->src ) ) { + $image_url = $image->src; + } + // add resizing to any npr-hosted image + if ( strpos( $image_url, 'media.npr.org' ) ) { + // remove any existing querystring + if ( strpos( $image_url, '?' ) ) { + $image_url = substr( $image_url, 0, strpos( $image_url, '?' ) ); + } + $image_url .= ( !$is_portrait ? '?s=6' : '?s=12' ); + } + $storyimages[ $image->id ] = (array)$image; + $storyimages[ $image->id ]['image_url'] = $image_url; + $storyimages[ $image->id ]['is_portrait'] = $is_portrait; + } + } + + $externalAssets = []; + if ( isset( $story->externalAsset ) ) { + $externals_array = []; + if ( isset( $story->externalAsset->type ) ) { + $externals_array[] = $story->externalAsset; + } else { + // sometimes there are multiple objects + foreach ( (array)$story->externalAsset as $extasset ) { + if ( isset( $extasset->type ) ) { + $externals_array[] = $extasset; + } + } + } + foreach ( $externals_array as $embed ) { + $externalAssets[ $embed->id ] = (array)$embed; + } + } + + $htmlAssets = []; + if ( isset( $story->htmlAsset ) ) { + if ( isset( $story->htmlAsset->id ) ) { + $htmlAssets[ $story->htmlAsset->id ] = $story->htmlAsset->value; + } else { + // sometimes there are multiple objects + foreach ( (array)$story->htmlAsset as $hasset ) { + if ( isset( $hasset->id ) ) { + $htmlAssets[ $hasset->id ] = $hasset->value; + } + } + } + } + + $multimedia = []; + if ( isset( $story->multimedia ) ) { + $multims_array = []; + if ( isset( $story->multimedia->id ) ) { + $multims_array[] = $story->multimedia; + } else { + // sometimes there are multiple objects + foreach ( (array)$story->multimedia as $multim ) { + if ( isset( $multim->id ) ) { + $multims_array[] = $multim; + } + } + } + foreach( $multims_array as $multim ) { + $multimedia[ $multim->id ] = (array)$multim; + } + } + + foreach ( $layoutarry as $ordernum => $element ) { + $reference = $element['reference']; + switch ( $element['type'] ) { + case 'text': + if ( !empty( $paragraphs[ $reference ] ) ) { + $body_with_layout .= "

" . $paragraphs[ $reference ] . "

\n"; + } + break; + case 'staticHtml': + if ( !empty( $htmlAssets[ $reference ] ) ) { + $body_with_layout .= $htmlAssets[ $reference ] . "\n\n"; + $returnary['has_external'] = TRUE; + if ( strpos( $htmlAssets[ $reference ], 'jwplayer.com' ) ) { + $returnary['has_video'] = TRUE; + } + } + break; + case 'externalAsset': + if ( !empty( $externalAssets[ $reference ] ) ) { + $figclass = "wp-block-embed"; + if ( !empty( (string)$externalAssets[ $reference ]['type'] ) && strtolower( (string)$externalAssets[ $reference ]['type'] ) == 'youtube') { + $returnary['has_video'] = TRUE; + $figclass .= " is-type-video"; + } + $fightml = "
"; + $fightml .= "\n" . $externalAssets[$reference]['url'] . "\n"; + $figcaption = ''; + if ( !empty( (string)$externalAssets[ $reference ]['credit'] ) || !empty( (string)$externalAssets[ $reference ]['caption'] ) ) { + if ( !empty( trim( (string)$externalAssets[ $reference ]['credit'] ) ) ) { + $figcaption .= "" . trim( (string)$externalAssets[ $reference ]['credit'] ) . ""; + } + if ( !empty( (string)$externalAssets[ $reference ]['caption'] ) ) { + $figcaption .= trim( (string)$externalAssets[ $reference ]['caption'] ); + } + $figcaption = !empty( $figcaption ) ? "
$figcaption
" : ""; + } + $fightml .= "
$figcaption
\n"; + $body_with_layout .= $fightml; + } + break; + case 'multimedia': + if ( !empty( $multimedia[ $reference ] ) ) { + // check permissions + $perms = $multimedia[ $reference ]['permissions']; + if ( $perms->embed->allow != false ) { + $fightml = "
"; + $returnary['has_video'] = TRUE; + $fightml .= "
"; + $figcaption = ''; + if ( !empty( (string)$multimedia[ $reference ]['credit'] ) || !empty( (string)$multimedia[ $reference ]['caption'] ) ) { + if (!empty( trim( (string)$multimedia[ $reference ]['credit'] ) ) ) { + $figcaption .= "" . trim( (string)$multimedia[ $reference ]['credit'] ) . ""; + } + if ( !empty( (string)$multimedia[ $reference ]['caption'] ) ) { + $figcaption .= trim( (string)$multimedia[ $reference ]['caption'] ); + } + $figcaption = ( !empty( $figcaption ) ? "
$figcaption
" : "" ); + } + $fightml .= "
$figcaption
\n"; + $body_with_layout .= $fightml; + } + } + break; + default: + // handles both 'list' and 'image' since it will reset the type and then assign the reference + if ( $element['type'] == 'list' ) { + foreach ( $storyimages as $image ) { + if ( $image['type'] != 'primary' ) { + continue; + } + $reference = $image['id']; + $element['type'] = 'image'; + break; + } + } + if ( $element['type'] != 'image' ) { + break; + } + if ( !empty( $storyimages[ $reference ] ) ) { + $figclass = "wp-block-image size-large"; + $thisimg = $storyimages[ $reference ]; + $fightml = ( !empty( (string)$thisimg['image_url'] ) ? '' . strip_tags( $thiscaption ) . '' : '' ); + $figcaption = ( !empty( $fightml ) && !empty( $thiscaption ) ? $thiscaption : '' ); + $cites = ''; + foreach ( [ 'producer', 'provider', 'copyright' ] as $item ) { + $thisitem = trim( (string)$thisimg[ $item ] ); + if ( !empty( $thisitem ) ) { + $cites .= ( !empty( $cites ) ? ' | ' . $thisitem : $thisitem ); + } + } + $cites = ( !empty( $cites ) ? "$cites" : '' ); + $thiscaption .= $cites; + $figcaption = ( !empty( $fightml ) && !empty( $thiscaption ) ? "
$thiscaption
" : '' ); + $fightml .= ( !empty( $fightml ) && !empty( $figcaption ) ? $figcaption : '' ); + $body_with_layout .= ( !empty( $fightml ) ? "
$fightml
\n\n" : '' ); + // make sure it doesn't get reused; + unset( $storyimages[ $reference ] ); + } + break; + } + } + } + $returnary['body'] = $body_with_layout; + return $returnary; + } } diff --git a/classes/nprml.php b/classes/nprml.php index 0f46071..725fac0 100644 --- a/classes/nprml.php +++ b/classes/nprml.php @@ -4,37 +4,37 @@ * nprstory_to_nprml(): Translates a post to NPRML. Returns an XML string. */ function nprstory_to_nprml( $post ) { - $story = nprstory_post_to_nprml_story( $post ); - $doc = array(); - $doc[] = array( - 'tag' => 'list', - 'children' => array( array( 'tag' => 'story', 'children' => $story ), ), - ); - $ret_xml = nprstory_nprml_array_to_xml( 'nprml', array( 'version' => '0.93' ), $doc ); - return $ret_xml; + $story = nprstory_post_to_nprml_story( $post ); + $doc = []; + $doc[] = [ + 'tag' => 'list', + 'children' => [ [ 'tag' => 'story', 'children' => $story ] ] + ]; + $ret_xml = nprstory_nprml_array_to_xml( 'nprml', [ 'version' => '0.93' ], $doc ); + return $ret_xml; } /** - * - * Do the mapping from WP post to the array that we're going to build the NPRML from. + * + * Do the mapping from WP post to the array that we're going to build the NPRML from. * This is also where we will do custom mapping if need be. * If a mapped custom field does not exist in a certain post, just send the default field. * @param $post */ function nprstory_post_to_nprml_story( $post ) { - $story = array(); - $story[] = array( + $story = []; + $story[] = [ 'tag' => 'link', - 'attr' => array( 'type' => 'html' ), - 'text' => get_permalink( $post ), - ); + 'attr' => [ 'type' => 'html' ], + 'text' => get_permalink( $post ) + ]; $use_custom = get_option( 'dp_npr_push_use_custom_map' ); //get the list of metas available for this post $post_metas = get_post_custom_keys( $post->ID ); $teaser_text = ''; - if ( ! empty( $post->post_excerpt ) ){ + if ( !empty( $post->post_excerpt ) ) { $teaser_text = $post->post_excerpt; } @@ -44,14 +44,14 @@ function nprstory_post_to_nprml_story( $post ) { $custom_content_meta = get_option( 'ds_npr_api_mapping_body' ); if ( $use_custom - && ! empty( $custom_content_meta ) + && !empty( $custom_content_meta ) && $custom_content_meta != '#NONE#' && in_array( $custom_content_meta, $post_metas ) - ){ - $content = get_post_meta( $post->ID, $custom_content_meta, true); + ) { + $content = get_post_meta( $post->ID, $custom_content_meta, true ); $post_for_teaser = $post; $post_for_teaser->post_content = $content; - if ( empty( $teaser_text ) ){ + if ( empty( $teaser_text ) ) { $teaser_text = nprstory_nai_get_excerpt( $post_for_teaser ); } } else { @@ -72,14 +72,14 @@ function nprstory_post_to_nprml_story( $post ) { // Let any plugin that has short codes try and replace those with HTML $content = do_shortcode( $content ); - //for any remaining short codes, nuke 'em + // for any remaining short codes, nuke 'em $content = strip_shortcodes( $content ); $content = apply_filters( 'the_content', $content ); - $story[] = array( + $story[] = [ 'tag' => 'teaser', - 'text' => $teaser_text, - ); + 'text' => $teaser_text + ]; /* * Custom title @@ -90,17 +90,17 @@ function nprstory_post_to_nprml_story( $post ) { && !empty( $custom_title_meta ) && $custom_title_meta != '#NONE#' && in_array( $custom_content_meta, $post_metas ) - ){ + ) { $custom_title = get_post_meta( $post->ID, $custom_title_meta, true ); - $story[] = array( + $story[] = [ 'tag' => 'title', - 'text' => $custom_title, - ); + 'text' => $custom_title + ]; } else { - $story[] = array( + $story[] = [ 'tag' => 'title', - 'text' => $post->post_title, - ); + 'text' => $post->post_title + ]; } /* @@ -114,53 +114,53 @@ function nprstory_post_to_nprml_story( $post ) { // Custom field mapping byline if ( $use_custom - && ! empty( $custom_byline_meta ) + && !empty( $custom_byline_meta ) && $custom_byline_meta != '#NONE#' && in_array( $custom_content_meta, $post_metas ) ) { $byline = TRUE; - $story[] = array( + $story[] = [ 'tag' => 'byline', - 'children' => array( - array( + 'children' => [ + [ 'tag' => 'name', 'text' => get_post_meta( $post->ID, $custom_byline_meta, true ), - ) - ), - ); + ] + ] + ]; } // Co-Authors Plus support overrides the NPR custom byline if ( function_exists( 'get_coauthors' ) ) { $coauthors = get_coauthors( $post->ID ); - if ( ! empty( $coauthors ) ) { + if ( !empty( $coauthors ) ) { $byline = TRUE; - foreach( $coauthors as $i=>$co ) { - $story[] = array( + foreach( $coauthors as $i => $co ) { + $story[] = [ 'tag' => 'byline', - 'children' => array( - array( + 'children' => [ + [ 'tag' => 'name', - 'text' => $co->display_name, - ) - ) - ); + 'text' => $co->display_name + ] + ] + ]; } } else { nprstory_error_log( 'we do not have co authors' ); } } else { - nprstory_error_log('can not find get_coauthors'); + nprstory_error_log( 'can not find get_coauthors' ); } - if ( ! $byline ) { - $story[] = array( + if ( !$byline ) { + $story[] = [ 'tag' => 'byline', - 'children' => array ( - array( + 'children' => [ + [ 'tag' => 'name', - 'text' => get_the_author_meta( 'display_name', $post->post_author ), - ) - ), - ); + 'text' => get_the_author_meta( 'display_name', $post->post_author ) + ] + ] + ]; } /* @@ -171,10 +171,10 @@ function nprstory_post_to_nprml_story( $post ) { */ $nprapi = get_post_meta( $post->ID, '_send_to_one', true ); // 0 or 1 if ( ! empty( $nprapi ) && ( '1' === $nprapi || 1 === $nprapi ) ) { - $story[] = array( + $story[] = [ 'tag' => 'parent', - 'attr' => array( 'id' => '319418027', 'type' => 'collection' ), - ); + 'attr' => [ 'id' => '319418027', 'type' => 'collection' ] + ]; } /* @@ -184,46 +184,46 @@ function nprstory_post_to_nprml_story( $post ) { */ $nprapi = get_post_meta( $post->ID, '_nprone_featured', true ); // 0 or 1 if ( ! empty( $nprapi ) && ( '1' === $nprapi || 1 === $nprapi ) ) { - $story[] = array( + $story[] = [ 'tag' => 'parent', - 'attr' => array( 'id' => '500549367', 'type' => 'collection' ), - ); + 'attr' => [ 'id' => '500549367', 'type' => 'collection' ] + ]; } /* * Mini Teaser (not yet implemented) * Slug (not yet implemented) */ - #'miniTeaser' => array( 'text' => '' ), - #'slug' => array( 'text' => '' ), + // 'miniTeaser' => [ 'text' => '' ], + // 'slug' => [ 'text' => '' ], /* * Dates and times */ - $story[] = array( + $story[] = [ 'tag' => 'storyDate', - 'text' => mysql2date( 'D, d M Y H:i:s +0000', $post->post_date_gmt ), - ); - $story[] = array( + 'text' => mysql2date( 'D, d M Y H:i:s +0000', $post->post_date_gmt ) + ]; + $story[] = [ 'tag' => 'pubDate', - 'text' => mysql2date( 'D, d M Y H:i:s +0000', $post->post_modified_gmt ), - ); - $story[] = array( + 'text' => mysql2date( 'D, d M Y H:i:s +0000', $post->post_modified_gmt ) + ]; + $story[] = [ 'tag' => 'lastModifiedDate', - 'text' => mysql2date( 'D, d M Y H:i:s +0000', $post->post_modified_gmt ), - ); - $story[] = array( + 'text' => mysql2date( 'D, d M Y H:i:s +0000', $post->post_modified_gmt ) + ]; + $story[] = [ 'tag' => 'partnerId', - 'text' => $post->guid, - ); + 'text' => $post->guid + ]; // NPR One audio run-by date $datetime = nprstory_get_post_expiry_datetime( $post ); // if expiry date is not set, returns publication date plus 7 days if ( $datetime instanceof DateTime ) { - $story[] = array( + $story[] = [ 'tag' => 'audioRunByDate', 'text' => date_format( $datetime, 'j M Y H:i:00 O' ) // 1 Oct 2017 01:00:00 -0400, 29 Feb 2020 23:59:00 -0500 - ); + ]; } @@ -235,42 +235,43 @@ function nprstory_post_to_nprml_story( $post ) { * It would be nice to send text after we strip all html and shortcodes, but we need the html * and sending both will duplicate the data in the API */ - $story[] = array( + $story[] = [ 'tag' => 'textWithHtml', - 'children' => nprstory_nprml_split_paragraphs( $content ), - ); + 'children' => nprstory_nprml_split_paragraphs( $content ) + ]; $perms_group = get_option( 'ds_npr_story_default_permission' ); - if (!empty( $perms_group ) ) { - $story[] = array( + if ( !empty( $perms_group ) ) { + $story[] = [ 'tag' => 'permissions', - 'children' => array ( - array( + 'children' => [ + [ 'tag' => 'permGroup', - 'attr' => array( 'id' => $perms_group ), - ) - ), - ); + 'attr' => [ 'id' => $perms_group ] + ] + ] + ]; } $custom_media_credit = get_option( 'ds_npr_api_mapping_media_credit' ); $custom_media_agency = get_option( 'ds_npr_api_mapping_media_agency' ); - /* remove this for now until we decide if we're going to actually do this...km - $dist_media_option = get_option('ds_npr_api_mapping_distribute_media'); - $dist_media_polarity = get_option('ds_npr_api_mapping_distribute_media_polarity'); + /* + remove this for now until we decide if we're going to actually do this...km + $dist_media_option = get_option('ds_npr_api_mapping_distribute_media'); + $dist_media_polarity = get_option('ds_npr_api_mapping_distribute_media_polarity'); */ /* * Attach images to the post */ - $args = array( + $args = [ 'order'=> 'DESC', 'post_mime_type' => 'image', 'post_parent' => $post->ID, 'post_status' => null, 'post_type' => 'attachment' - ); + ]; $images = get_children( $args ); $primary_image = get_post_thumbnail_id( $post->ID ); @@ -282,7 +283,7 @@ function nprstory_post_to_nprml_story( $post ) { if ( $use_custom && !empty( $custom_media_credit ) && $custom_media_credit != '#NONE#' && in_array( $custom_media_credit,$image_metas ) ) { $custom_credit = get_post_meta( $image->ID, $custom_media_credit, true ); } - if ( $use_custom && ! empty( $custom_media_agency ) && $custom_media_agency != '#NONE#' && in_array( $custom_media_agency,$image_metas ) ) { + if ( $use_custom && !empty( $custom_media_agency ) && $custom_media_agency != '#NONE#' && in_array( $custom_media_agency,$image_metas ) ) { $custom_agency = get_post_meta( $image->ID, $custom_media_agency, true); } @@ -300,38 +301,41 @@ function nprstory_post_to_nprml_story( $post ) { // Is the image in the content? If so, tell the API with a flag that CorePublisher knows. // WordPress may add something like "-150X150" to the end of the filename, before the extension. // Isn't that nice? Let's remove that. - $image_name_parts = explode( ".", $image_guid ); - $image_regex = "/" . $image_name_parts[0] . "\-[a-zA-Z0-9]*" . $image_name_parts[1] . "/"; + $image_attach_url = wp_get_attachment_url( $image->ID ); + $image_url = parse_url( $image_attach_url ); + $image_name_parts = pathinfo( $image_url['path'] ); + + $image_regex = "/" . $image_name_parts['filename'] . "\-[a-zA-Z0-9]*" . $image_name_parts['extension'] . "/"; $in_body = ""; if ( preg_match( $image_regex, $content ) ) { - if ( strstr( $image->guid, '?') ) { + if ( strstr( $image_attach_url, '?') ) { $in_body = "&origin=body"; } else { $in_body = "?origin=body"; } } - $story[] = array( + $story[] = [ 'tag' => 'image', - 'attr' => array( 'src' => $image->guid . $in_body, 'type' => $image_type ), - 'children' => array( - array( + 'attr' => [ 'src' => $image_attach_url . $in_body, 'type' => $image_type ], + 'children' => [ + [ 'tag' => 'title', - 'text' => $image->post_title, - ), - array( + 'text' => $image->post_title + ], + [ 'tag' => 'caption', - 'text' => $image->post_excerpt, - ), - array( + 'text' => $image->post_excerpt + ], + [ 'tag' => 'producer', 'text' => $custom_credit - ), - array( + ], + [ 'tag' => 'provider', 'text' => $custom_agency - ) - ), - ); + ] + ] + ]; } /* @@ -339,14 +343,15 @@ function nprstory_post_to_nprml_story( $post ) { * * Should be able to do the same as image for audio, with post_mime_type = 'audio' or something. */ - $args = array( + $args = [ 'order'=> 'DESC', 'post_mime_type' => 'audio', 'post_parent' => $post->ID, 'post_status' => null, 'post_type' => 'attachment' - ); + ]; $audios = get_children( $args ); + $audio_files = []; foreach ( $audios as $audio ) { $audio_meta = wp_get_attachment_metadata( $audio->ID ); @@ -355,29 +360,31 @@ function nprstory_post_to_nprml_story( $post ) { if ( empty( $caption ) ) { $caption = $audio->post_content; } + $audio_guid = wp_get_attachment_url( $audio->ID ); + $audio_files[] = $audio->ID; - $story[] = array( + $story[] = [ 'tag' => 'audio', - 'children' => array( - array( + 'children' => [ + [ 'tag' => 'format', - 'children' => array ( - array( + 'children' => [ + [ 'tag' => 'mp3', - 'text' => $audio->guid, - ) - ), - ), - array( + 'text' => $audio_guid, + ] + ] + ], + [ 'tag' => 'description', - 'text' => $caption, - ), - array( + 'text' => $caption + ], + [ 'tag' => 'duration', - 'text' => $audio_meta['length'], - ), - ), - ); + 'text' => $audio_meta['length'] + ] + ] + ]; } /* @@ -390,28 +397,42 @@ function nprstory_post_to_nprml_story( $post ) { if ( $enclosures = get_metadata( 'post', $post->ID, 'enclosure' ) ) { foreach( $enclosures as $enclosure ) { $pieces = explode( "\n", $enclosure ); - if ( !empty( $pieces[3] ) ) { - $metadata = unserialize( $pieces[3] ); - $duration = ( ! empty($metadata['duration'] ) ) ? nprstory_convert_duration_to_seconds( $metadata['duration'] ) : NULL; + + $audio_guid = trim( $pieces[0] ); + $attach_id = attachment_url_to_postid( $audio_guid ); + if ( !in_array( $attach_id, $audio_files ) ) { + $audio_files[] = $attach_id; + + $audio_meta = wp_get_attachment_metadata( $attach_id ); + $duration = 0; + if ( !empty( $audio_meta['length'] ) ) : + $duration = $audio_meta['length']; + elseif ( !empty( $audio_meta['length_formatted'] ) ) : + $duration = nprstory_convert_duration_to_seconds( $audio_meta['length_formatted'] ); + elseif ( !empty( $pieces[3] ) ) : + $metadata = unserialize( trim( $pieces[3] ) ); + $duration = ( !empty($metadata['duration'] ) ) ? nprstory_convert_duration_to_seconds( $metadata['duration'] ) : 0; + endif; + + $story[] = [ + 'tag' => 'audio', + 'children' => [ + [ + 'tag' => 'duration', + 'text' => $duration + ], + [ + 'tag' => 'format', + 'children' => [ + [ + 'tag' => 'mp3', + 'text' => wp_get_attachment_url( $attach_id ) + ] + ] + ] + ] + ]; } - $story[] = array( - 'tag' => 'audio', - 'children' => array( - array( - 'tag' => 'duration', - 'text' => ( !empty($duration) ) ? $duration : 0, - ), - array( - 'tag' => 'format', - 'children' => array( - array( - 'tag' => 'mp3', - 'text' => $pieces[0], - ), - ), - ), - ), - ); } } @@ -423,26 +444,26 @@ function nprstory_post_to_nprml_story( $post ) { // Convert "HH:MM:SS" duration (not time) into seconds function nprstory_convert_duration_to_seconds( $duration ) { - $pieces = explode( ':', $duration ); - $duration_in_seconds = ( $pieces[0] * 60 * 60 + $pieces[1] * 60 + $pieces[2] ); - return $duration_in_seconds; + $pieces = explode( ':', $duration ); + $duration_in_seconds = ( $pieces[0] * 60 * 60 + $pieces[1] * 60 + $pieces[2] ); + return $duration_in_seconds; } function nprstory_nprml_split_paragraphs( $html ) { - $parts = array_filter( - array_map( 'trim', preg_split( "/<\/?p>/", $html ) ) - ); - $graphs = array(); - $num = 1; - foreach ( $parts as $part ) { - $graphs[] = array( - 'tag' => 'paragraph', - 'attr' => array( 'num' => $num ), - 'cdata' => $part, - ); - $num++; - } - return $graphs; + $parts = array_filter( + array_map( 'trim', preg_split( "/<\/?p>/", $html ) ) + ); + $graphs = []; + $num = 1; + foreach ( $parts as $part ) { + $graphs[] = [ + 'tag' => 'paragraph', + 'attr' => [ 'num' => $num ], + 'cdata' => $part + ]; + $num++; + } + return $graphs; } @@ -450,18 +471,18 @@ function nprstory_nprml_split_paragraphs( $html ) { * convert a PHP array to XML */ function nprstory_nprml_array_to_xml( $tag, $attrs, $data ) { - $xml = new DOMDocument(); - $xml->formatOutput = true; - $root = $xml->createElement( $tag ); - foreach ( $attrs as $k => $v ) { - $root->setAttribute( $k, $v ); - } - foreach ( $data as $item ) { - $elemxml = nprstory_nprml_item_to_xml( $item, $xml ); - $root->appendChild( $elemxml ); - } - $xml->appendChild( $root ); - return $xml->saveXML(); + $xml = new DOMDocument(); + $xml->formatOutput = true; + $root = $xml->createElement( $tag ); + foreach ( $attrs as $k => $v ) { + $root->setAttribute( $k, $v ); + } + foreach ( $data as $item ) { + $elemxml = nprstory_nprml_item_to_xml( $item, $xml ); + $root->appendChild( $elemxml ); + } + $xml->appendChild( $root ); + return $xml->saveXML(); } /** @@ -473,33 +494,33 @@ function nprstory_nprml_array_to_xml( $tag, $attrs, $data ) { * @param DOMDocument $xml */ function nprstory_nprml_item_to_xml( $item, $xml ) { - if ( ! array_key_exists( 'tag', $item ) ) { - error_log( "Unable to convert NPRML item to XML: no tag for: " . print_r( $item, true ) ); // debug use + if ( !array_key_exists( 'tag', $item ) ) { + error_log( "Unable to convert NPRML item to XML: no tag for: " . print_r( $item, true ) ); // debug use // this should actually be a serious error - } - $elem = $xml->createElement( $item[ 'tag' ] ); - if ( array_key_exists( 'children', $item ) ) { - foreach ( $item[ 'children' ] as $child ) { - $childxml = nprstory_nprml_item_to_xml( $child, $xml ); - $elem->appendChild( $childxml ); - } - } - if ( array_key_exists( 'text', $item ) ) { - $elem->appendChild( - $xml->createTextNode( $item[ 'text' ] ) - ); - } - if ( array_key_exists( 'cdata', $item ) ) { - $elem->appendChild( - $xml->createCDATASection( $item[ 'cdata' ] ) - ); - } - if ( array_key_exists( 'attr', $item ) ) { - foreach ( $item[ 'attr' ] as $attr => $val ) { - $elem->setAttribute( $attr, $val ); - } - } - return $elem; + } + $elem = $xml->createElement( $item['tag'] ); + if ( array_key_exists( 'children', $item ) ) { + foreach ( $item['children'] as $child ) { + $childxml = nprstory_nprml_item_to_xml( $child, $xml ); + $elem->appendChild( $childxml ); + } + } + if ( array_key_exists( 'text', $item ) ) { + $elem->appendChild( + $xml->createTextNode( $item['text'] ) + ); + } + if ( array_key_exists( 'cdata', $item ) ) { + $elem->appendChild( + $xml->createCDATASection( $item['cdata'] ) + ); + } + if ( array_key_exists( 'attr', $item ) ) { + foreach ( $item['attr'] as $attr => $val ) { + $elem->setAttribute( $attr, $val ); + } + } + return $elem; } /** @@ -512,29 +533,27 @@ function nprstory_nprml_item_to_xml( $item, $xml ) { * * @todo replace this with wp_trim_words, see https://github.com/nprds/nprapi-wordpress/issues/20 * - * @param object $post Post object - * @param int $word_count Number of words (default 30) + * @param object $post Post object + * @param int $word_count Number of words (default 30) * @return String */ function nprstory_nai_get_excerpt( $post, $word_count = 30 ) { - $text = $post->post_content; - - $text = strip_shortcodes( $text ); - - $text = apply_filters( 'the_content', $text ); - $text = str_replace( ']]>', ']]>', $text ); - $text = strip_tags( $text ); - $excerpt_length = apply_filters( 'excerpt_length', $word_count ); - //$excerpt_more = apply_filters( 'excerpt_more', ' ' . '[...]' ); - $words = preg_split( "/[\n\r\t ]+/", $text, $excerpt_length + 1, - PREG_SPLIT_NO_EMPTY ); - if ( count( $words ) > $excerpt_length ) { - array_pop( $words ); - $text = implode( ' ', $words ); - //$text = $text . $excerpt_more; - } else { - $text = implode( ' ', $words ); - } - return $text; -} - + $text = $post->post_content; + + $text = strip_shortcodes( $text ); + + $text = apply_filters( 'the_content', $text ); + $text = str_replace( ']]>', ']]>', $text ); + $text = strip_tags( $text ); + $excerpt_length = apply_filters( 'excerpt_length', $word_count ); + //$excerpt_more = apply_filters( 'excerpt_more', ' ' . '[...]' ); + $words = preg_split( "/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY ); + if ( count( $words ) > $excerpt_length ) { + array_pop( $words ); + $text = implode( ' ', $words ); + //$text = $text . $excerpt_more; + } else { + $text = implode( ' ', $words ); + } + return $text; +} \ No newline at end of file diff --git a/ds-npr-api.php b/ds-npr-api.php index a2a4282..2fb5bf1 100644 --- a/ds-npr-api.php +++ b/ds-npr-api.php @@ -7,20 +7,20 @@ * License: GPLv2 */ /* - Copyright 2012 NPR Digital Services + Copyright 2012 NPR Digital Services - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ define( 'NPR_STORY_ID_META_KEY', 'npr_story_id' ); @@ -31,19 +31,23 @@ define( 'NPR_BYLINE_META_KEY', 'npr_byline' ); define( 'NPR_BYLINE_LINK_META_KEY', 'npr_byline_link' ); define( 'NPR_MULTI_BYLINE_META_KEY', 'npr_multi_byline' ); -define( 'NPR_IMAGE_GALLERY_META_KEY', 'npr_image_gallery'); -define( 'NPR_AUDIO_META_KEY', 'npr_audio'); -define( 'NPR_AUDIO_M3U_META_KEY', 'npr_audio_m3u'); -define( 'NPR_PUB_DATE_META_KEY', 'npr_pub_date'); -define( 'NPR_STORY_DATE_MEATA_KEY', 'npr_story_date'); -define( 'NPR_LAST_MODIFIED_DATE_KEY', 'npr_last_modified_date'); -define( 'NPR_RETRIEVED_STORY_META_KEY', 'npr_retrieved_story'); +define( 'NPR_IMAGE_GALLERY_META_KEY', 'npr_image_gallery' ); +define( 'NPR_HTML_ASSETS_META_KEY', 'npr_html_assets' ); +define( 'NPR_AUDIO_META_KEY', 'npr_audio' ); +define( 'NPR_AUDIO_M3U_META_KEY', 'npr_audio_m3u' ); +define( 'NPR_PUB_DATE_META_KEY', 'npr_pub_date' ); +define( 'NPR_STORY_DATE_MEATA_KEY', 'npr_story_date' ); +define( 'NPR_LAST_MODIFIED_DATE_KEY', 'npr_last_modified_date' ); +define( 'NPR_RETRIEVED_STORY_META_KEY', 'npr_retrieved_story' ); -define( 'NPR_IMAGE_CREDIT_META_KEY', 'npr_image_credit'); -define( 'NPR_IMAGE_AGENCY_META_KEY', 'npr_image_agency'); -define( 'NPR_IMAGE_CAPTION_META_KEY', 'npr_image_caption'); +define( 'NPR_IMAGE_CREDIT_META_KEY', 'npr_image_credit' ); +define( 'NPR_IMAGE_AGENCY_META_KEY', 'npr_image_agency' ); +define( 'NPR_IMAGE_CAPTION_META_KEY', 'npr_image_caption' ); -define( 'NPR_PUSH_STORY_ERROR', 'npr_push_story_error'); +define( 'NPR_STORY_HAS_LAYOUT_META_KEY', 'npr_has_layout' ); +define( 'NPR_STORY_HAS_VIDEO_META_KEY', 'npr_has_video' ); + +define( 'NPR_PUSH_STORY_ERROR', 'npr_push_story_error' ); define( 'NPR_MAX_QUERIES', 10 ); @@ -54,14 +58,14 @@ // Load files define( 'NPRSTORY_PLUGIN_DIR', plugin_dir_path(__FILE__) ); require_once( NPRSTORY_PLUGIN_DIR . 'settings.php' ); -require_once( NPRSTORY_PLUGIN_DIR . 'classes/NPRAPIWordpress.php'); -require_once( NPRSTORY_PLUGIN_DIR . 'get_stories.php'); -require_once( NPRSTORY_PLUGIN_DIR . 'meta-boxes.php'); -require_once( NPRSTORY_PLUGIN_DIR . 'push_story.php'); +require_once( NPRSTORY_PLUGIN_DIR . 'classes/NPRAPIWordpress.php' ); +require_once( NPRSTORY_PLUGIN_DIR . 'get_stories.php' ); +require_once( NPRSTORY_PLUGIN_DIR . 'meta-boxes.php' ); +require_once( NPRSTORY_PLUGIN_DIR . 'push_story.php' ); //add the cron to get stories register_activation_hook( NPRSTORY_PLUGIN_DIR . 'ds-npr-api.php', 'nprstory_activation' ); -add_action( 'npr_ds_hourly_cron', array ( 'DS_NPR_API','nprstory_cron_pull' ) ); +add_action( 'npr_ds_hourly_cron', [ 'DS_NPR_API', 'nprstory_cron_pull' ] ); register_deactivation_hook( NPRSTORY_PLUGIN_DIR . 'ds-npr-api.php', 'nprstory_deactivation' ); @@ -71,7 +75,7 @@ function nprstory_activation() { // check if it is a network activation - if so, run the activation function for each blog id $old_blog = $wpdb->blogid; // Get all blog ids - $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs" ) ); + $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM %s", $wpdb->blogs ) ); foreach ( $blogids as $blog_id ) { switch_to_blog( $blog_id ); nprstory_activate(); @@ -84,16 +88,16 @@ function nprstory_activation() { function nprstory_activate() { update_option( 'dp_npr_query_multi_cron_interval', 60 ); - if ( ! wp_next_scheduled( 'npr_ds_hourly_cron' ) ) { + if ( !wp_next_scheduled( 'npr_ds_hourly_cron' ) ) { nprstory_error_log( 'turning on cron event for NPR Story API plugin' ); wp_schedule_event( time(), 'hourly', 'npr_ds_hourly_cron' ); } - $num = get_option( 'ds_npr_num' ); - if ( empty($num) ) { + $num = get_option( 'ds_npr_num' ); + if ( empty( $num ) ) { update_option( 'ds_npr_num', 5 ); } - + $def_url = 'https://api.npr.org'; $pull_url = get_option( 'ds_npr_api_pull_url' ); if ( empty( $pull_url ) ) { @@ -107,7 +111,7 @@ function nprstory_deactivation() { // check if it is a network activation - if so, run the activation function for each blog id $old_blog = $wpdb->blogid; // Get all blog ids - $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs" ) ); + $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM %s", $wpdb->blogs ) ); foreach ( $blogids as $blog_id ) { switch_to_blog( $blog_id ); nprstory_deactivate(); @@ -124,7 +128,7 @@ function nprstory_deactivate() { if ( ! empty($num) ) { delete_option( 'ds_npr_num' ); } - + $push_url = get_option( 'ds_npr_api_push_url' ); if ( ! empty( $push_url ) ) { delete_option( 'ds_npr_api_push_url' ); @@ -144,18 +148,16 @@ function nprstory_show_message( $message, $errormsg = false ) { add_action( 'init', 'nprstory_create_post_type' ); function nprstory_create_post_type() { - register_post_type( NPR_POST_TYPE, - array( - 'labels' => array( - 'name' => __( 'NPR Stories' ), - 'singular_name' => __( 'NPR Story' ), - ), - 'public' => true, - 'has_archive' => true, - 'menu_position' => 5, - 'supports' => array( 'title', 'editor', 'thumbnail', 'custom-fields' ), - ) - ); + register_post_type( NPR_POST_TYPE, [ + 'labels' => [ + 'name' => __( 'NPR Stories' ), + 'singular_name' => __( 'NPR Story' ) + ], + 'public' => true, + 'has_archive' => true, + 'menu_position' => 5, + 'supports' => [ 'title', 'editor', 'thumbnail', 'custom-fields' ] + ]); } /** @@ -170,7 +172,7 @@ function nprstory_add_meta_boxes() { $push_post_type = get_option( 'ds_npr_push_post_type' ) ?: 'post'; $push_url = get_option( 'ds_npr_api_push_url' ); if ( $screen->id == $push_post_type ) { - if ( ! empty( $push_url ) ) { + if ( !empty( $push_url ) ) { global $post; add_meta_box( 'ds_npr_document_meta', diff --git a/get_stories.php b/get_stories.php index 2e7deae..865c9ce 100644 --- a/get_stories.php +++ b/get_stories.php @@ -4,7 +4,7 @@ */ require_once( NPRSTORY_PLUGIN_DIR . 'get_stories_ui.php' ); -require_once( NPRSTORY_PLUGIN_DIR . 'classes/NPRAPIWordpress.php'); +require_once( NPRSTORY_PLUGIN_DIR . 'classes/NPRAPIWordpress.php' ); class DS_NPR_API { var $created_message = ''; @@ -28,22 +28,22 @@ public static function nprstory_get_pull_post_type() { public static function nprstory_cron_pull() { // here we should get the list of IDs/full urls that need to be checked hourly //because this is run on cron, and may be fired off by an non-admin, we need to load a bunch of stuff - require_once( ABSPATH . 'wp-admin/includes/file.php'); - require_once( ABSPATH . 'wp-admin/includes/media.php'); + require_once( ABSPATH . 'wp-admin/includes/file.php' ); + require_once( ABSPATH . 'wp-admin/includes/media.php' ); // This is debug code. It may be save future devs some time; please keep it around. /* - $now = gmDate("D, d M Y G:i:s O "); - error_log("right now the time is -- ".$now); // debug use + $now = gmDate("D, d M Y G:i:s O "); + error_log("right now the time is -- ".$now); // debug use */ // here we go. $num = get_option( 'ds_npr_num' ); - for ($i=0; $i<$num; $i++ ) { + for ( $i=0; $i < $num; $i++ ) { $api = new NPRAPIWordpress(); $q = 'ds_npr_query_' . $i; $query_string = get_option( $q ); - if ( ! empty( $query_string ) ) { + if ( !empty( $query_string ) ) { nprstory_error_log( 'Cron '. $i . ' querying NPR API for ' . $query_string ); //if the query string contains the pull url and 'query', just make request from the API if ( stristr( $query_string, get_option( 'ds_npr_api_pull_url' ) ) && stristr( $query_string,'query' ) ) { @@ -60,29 +60,28 @@ public static function nprstory_cron_pull() { var_export( get_option( 'ds_npr_api_pull_url' ), true ) ) ); // debug use } else { - $params = array ('id' => $query_string, 'apiKey' => get_option( 'ds_npr_api_key' )); + $params = [ 'id' => $query_string, 'apiKey' => get_option( 'ds_npr_api_key' ) ]; $api->request( $params, 'query', get_option( 'ds_npr_api_pull_url' ) ); } } $api->parse(); - try { - if ( empty( $api->message ) || $api->message->level != 'warning' ) { - //check the publish flag and send that along. - $pub_flag = FALSE; - $pub_option = get_option('ds_npr_query_publish_'.$i); - if ( $pub_option == 'Publish' ) { - $pub_flag = TRUE; - } - $story = $api->update_posts_from_stories($pub_flag, $i); - } else { - if ( empty($story) ) { - error_log('NPR Story API: not going to save story. Query '. $query_string .' returned an error '.$api->message->id. ' error'); // debug use - } - } - } - catch (Exception $e) { - error_log('NPR Story API: error in ' . __FUNCTION__ . ' like this :'. $e); // debug use - } + try { + if ( empty( $api->message ) || $api->message->level != 'warning' ) { + //check the publish flag and send that along. + $pub_flag = FALSE; + $pub_option = get_option( 'ds_npr_query_publish_' . $i ); + if ( $pub_option == 'Publish' ) { + $pub_flag = TRUE; + } + $story = $api->update_posts_from_stories( $pub_flag, $i ); + } else { + if ( empty( $story ) ) { + error_log( 'NPR Story API: not going to save story. Query ' . $query_string . ' returned an error ' . $api->message->id . ' error' ); // debug use + } + } + } catch( Exception $e ) { + error_log( 'NPR Story API: error in ' . __FUNCTION__ . ' like this :'. $e ); // debug use + } } } } @@ -90,101 +89,100 @@ public static function nprstory_cron_pull() { /** * Function to convert an alleged NPR story URL or ID into a story ID, then request it */ - public function load_page_hook() { + public function load_page_hook() { // find the input that is allegedly a story id // We validate these later - if ( isset( $_POST ) && isset( $_POST[ 'story_id' ] ) ) { - $story_id = $_POST[ 'story_id' ] ; - if ( isset( $_POST['publishNow'] ) ){ - $publish = true; - } - if ( isset($_POST['createDaft'] ) ){ - $publish = false; - } - if ( ! check_admin_referer('nprstory_nonce_story_id', 'nprstory_nonce_story_id_field') ) { + if ( isset( $_POST ) && isset( $_POST[ 'story_id' ] ) ) { + $story_id = $_POST[ 'story_id' ] ; + if ( isset( $_POST['publishNow'] ) ) { + $publish = true; + } + if ( isset( $_POST['createDaft'] ) ) { + $publish = false; + } + if ( !check_admin_referer( 'nprstory_nonce_story_id', 'nprstory_nonce_story_id_field' ) ) { wp_die( - __('Nonce did not verify in DS_NPR_API::load_page_hook. Are you sure you should be doing this?'), - __('NPR Story API Error'), + __( 'Nonce did not verify in DS_NPR_API::load_page_hook. Are you sure you should be doing this?' ), + __( 'NPR Story API Error' ), 403 ); } - } else if ( isset( $_GET['story_id']) && isset( $_GET['create_draft'] ) ) { - $story_id = $_GET['story_id']; - } + } elseif ( isset( $_GET['story_id'] ) && isset( $_GET['create_draft'] ) ) { + $story_id = $_GET['story_id']; + } // if the current user shouldn't be doing this, fail - if ( ! current_user_can('edit_posts') ) { + if ( !current_user_can( 'edit_posts' ) ) { wp_die( - __('You do not have permission to edit posts, and therefore you do not have permission to pull posts from the NPR API'), - __('NPR Story API Error'), + __( 'You do not have permission to edit posts, and therefore you do not have permission to pull posts from the NPR API' ), + __( 'NPR Story API Error' ), 403 ); } // try to get the ID of the story from the URL - if ( isset( $story_id ) ) { - //check to see if we got an ID or a URL - if ( is_numeric( $story_id ) ) { - if (strlen($story_id) >= 8) { - $story_id = $story_id; + if ( isset( $story_id ) ) { + //check to see if we got an ID or a URL + if ( is_numeric( $story_id ) ) { + if ( strlen( $story_id ) >= 8 ) { + $story_id = $story_id; } - } else { - // url format: /yyyy/mm/dd/id + } else { + // url format: /yyyy/mm/dd/id // url format: /blogs/name/yyyy/mm/dd/id $story_id = preg_replace( '/https?\:\/\/[^\s\/]*npr\.org\/((([^\/]*\/){3,5})([0-9]{8,12}))\/.*/', '$4', $story_id ); - if ( ! is_numeric( $story_id ) ) { - // url format: /templates/story/story.php?storyId=id + if ( !is_numeric( $story_id ) ) { + // url format: /templates/story/story.php?storyId=id $story_id = preg_replace( '/https?\:\/\/[^\s\/]*npr\.org\/([^&\s\<]*storyId\=([0-9]+)).*/', '$2', $story_id ); } - } + } } // Don't do anything if $story_id isn't an ID if ( isset( $story_id ) && is_numeric( $story_id ) ) { // start the API class - // todo: check that the API key is actually set - $api = new NPRAPIWordpress(); + // todo: check that the API key is actually set + $api = new NPRAPIWordpress(); - $params = array( 'id' => $story_id, 'apiKey' => get_option( 'ds_npr_api_key' ) ); - $api->request( $params, 'query', get_option( 'ds_npr_api_pull_url' ) ); - $api->parse(); + $params = [ 'id' => $story_id, 'apiKey' => get_option( 'ds_npr_api_key' ) ]; + $api->request( $params, 'query', get_option( 'ds_npr_api_pull_url' ) ); + $api->parse(); - if ( empty( $api->message ) || $api->message->level != 'warning') { - $post_id = $api->update_posts_from_stories($publish); - if ( ! empty( $post_id ) ) { - //redirect to the edit page if we just updated one story - $post_link = admin_url( 'post.php?action=edit&post=' . $post_id ); - wp_redirect( $post_link ); - } - } else { - if ( empty($story) ) { - $xml = simplexml_load_string( $api->xml ); - nprstory_show_message('Error retrieving story for id = ' . $story_id . '
API error ='.$api->message->id . '
API Message ='. $xml->message->text , TRUE); - error_log('Not going to save the return from query for story_id='. $story_id .', we got an error='.$api->message->id. ' from the NPR Story API'); // debug use - return; - } - } - } - } + if ( empty( $api->message ) || $api->message->level != 'warning' ) { + $post_id = $api->update_posts_from_stories( $publish ); + if ( !empty( $post_id ) ) { + //redirect to the edit page if we just updated one story + $post_link = admin_url( 'post.php?action=edit&post=' . $post_id ); + wp_redirect( $post_link ); + } + } else { + if ( empty( $story ) ) { + $xml = simplexml_load_string( $api->xml ); + nprstory_show_message( 'Error retrieving story for id = ' . $story_id . '
API error =' . $api->message->id . '
API Message =' . $xml->message->text, TRUE ); + error_log( 'Not going to save the return from query for story_id=' . $story_id .', we got an error=' . $api->message->id . ' from the NPR Story API' ); // debug use + return; + } + } + } + } /** * Class constructor that hooks up the menu and the "Get NPR Stories" page action. */ - public function __construct() { - if ( ! is_admin() ) { - return; - } - add_action( 'admin_menu', array( &$this, 'admin_menu' ) ); - add_action( 'load-posts_page_get-npr-stories', array( $this, 'load_page_hook' ) ); - } + public function __construct() { + if ( !is_admin() ) { + return; + } + add_action( 'admin_menu', [ $this, 'admin_menu' ] ); + add_action( 'load-posts_page_get-npr-stories', [ $this, 'load_page_hook' ] ); + } /** * Register the admin menu for "Get NPR Stories" */ - public function admin_menu() { - add_posts_page( 'Get NPR Stories', 'Get NPR Stories', 'edit_posts', 'get-npr-stories', 'nprstory_get_stories' ); - } - + public function admin_menu() { + add_posts_page( 'Get NPR Stories', 'Get NPR Stories', 'edit_posts', 'get-npr-stories', 'nprstory_get_stories' ); + } } -new DS_NPR_API; +new DS_NPR_API; \ No newline at end of file diff --git a/get_stories_ui.php b/get_stories_ui.php index f8f2c74..e863d7e 100644 --- a/get_stories_ui.php +++ b/get_stories_ui.php @@ -3,140 +3,143 @@ * Functions related to the user interface for fetching stories from the API */ -/** +/* * This will turn on the update story column for all posts * yes, this is intentionally commented out * -add_filter('manage_posts_columns', 'nprstory_update_column'); +add_filter( 'manage_posts_columns', 'nprstory_update_column' ); -function nprstory_update_column($defaults){ +function nprstory_update_column( $defaults ) { $pull_post_type = DS_NPR_API::nprstory_get_pull_post_type(); - global $post_type; - if($post_type == $pull_post_type) { + global $post_type; + if ( $post_type == $pull_post_type ) { $defaults['update_story'] = 'Update Story'; - } + } return $defaults; } -/**/ +*/ // Add the update story column to the page listing the posts for the pull-type -add_filter( 'manage_edit-' . DS_NPR_API::nprstory_get_pull_post_type() . '_columns', 'nprstory_add_new_story_columns'); +add_filter( 'manage_edit-' . DS_NPR_API::nprstory_get_pull_post_type() . '_columns', 'nprstory_add_new_story_columns' ); + function nprstory_add_new_story_columns( $cols ) { $cols['update_story'] = 'Update Story'; return $cols; } add_action( 'manage_posts_custom_column', 'nprstory_update_column_content', 10, 2 ); -function nprstory_update_column_content ( $column_name, $post_ID ) { + +function nprstory_update_column_content( $column_name, $post_ID ) { if ( $column_name == 'update_story' ) { $retrieved = get_post_meta( $post_ID, NPR_RETRIEVED_STORY_META_KEY, true ); - if ($retrieved) { + if ( $retrieved ) { $api_id = get_post_meta( $post_ID, NPR_STORY_ID_META_KEY, TRUE ); - echo ( ' Update ' ); + echo ' Update '; } } } //add the bulk action to the dropdown on the post admin page add_action( 'admin_footer-edit.php', 'nprstory_bulk_action_update_dropdown' ); + function nprstory_bulk_action_update_dropdown() { $pull_post_type = DS_NPR_API::nprstory_get_pull_post_type(); - global $post_type; - if( $post_type == $pull_post_type ) { - ?> - - + + current_action(); - - switch( $action ) { - // 3. Perform the action - case 'updateNprStory': - - // make sure ids are submitted. depending on the resource type, this may be 'media' or 'ids' - if ( isset( $_REQUEST['post'] ) ) { - $post_ids = array_map( 'intval', $_REQUEST['post'] ); - } - - $exported = 0; - foreach( $post_ids as $post_id ) { - $api_id = get_post_meta( $post_id, NPR_STORY_ID_META_KEY, TRUE ); - - // don't run API queries for posts that have no ID - // @todo: why do some posts have no ID - // @todo: oh, it's only imported drafts that don't have an ID - if ( !empty( $api_id ) ) { - $api = new NPRAPIWordpress(); - $params = array( 'id' => $api_id, 'apiKey' => get_option( 'ds_npr_api_key' ) ); - $api->request( $params, 'query', get_option( 'ds_npr_api_pull_url' ) ); - $api->parse(); - if ( empty( $api->message ) || $api->message->level != 'warning' ){ - nprstory_error_log( 'updating story for API ID='.$api_id ); - $story = $api->update_posts_from_stories(); + // 1. get the action + $wp_list_table = _get_list_table( 'WP_Posts_List_Table' ); + $action = $wp_list_table->current_action(); + + switch ( $action ) { + // 3. Perform the action + case 'updateNprStory': + + // make sure ids are submitted. depending on the resource type, this may be 'media' or 'ids' + if ( isset( $_REQUEST['post'] ) ) { + $post_ids = array_map( 'intval', $_REQUEST['post'] ); + } + + $exported = 0; + foreach( $post_ids as $post_id ) { + $api_id = get_post_meta( $post_id, NPR_STORY_ID_META_KEY, TRUE ); + + // don't run API queries for posts that have no ID + // @todo: why do some posts have no ID + // @todo: oh, it's only imported drafts that don't have an ID + if ( !empty( $api_id ) ) { + $api = new NPRAPIWordpress(); + $params = [ 'id' => $api_id, 'apiKey' => get_option( 'ds_npr_api_key' ) ]; + $api->request( $params, 'query', get_option( 'ds_npr_api_pull_url' ) ); + $api->parse(); + if ( empty( $api->message ) || $api->message->level != 'warning' ) { + nprstory_error_log( 'updating story for API ID='.$api_id ); + $story = $api->update_posts_from_stories(); + } } - } else { } - } - // build the redirect url - //$sendback = add_query_arg( array('exported' => $exported, 'ids' => join(',', $post_ids) ), $sendback ); - break; - default: - return; - } + // build the redirect url + //$sendback = add_query_arg( array('exported' => $exported, 'ids' => join(',', $post_ids) ), $sendback ); + break; + default: return; + } - // ... + // ... - // 4. Redirect client - //wp_redirect($sendback); - //exit(); + // 4. Redirect client + //wp_redirect($sendback); + //exit(); } function nprstory_get_stories() { - global $is_IE; - $api_key = get_option( 'ds_npr_api_key' ); - $pull_url = get_option( 'ds_npr_api_pull_url' ); + global $is_IE; + $api_key = get_option( 'ds_npr_api_key' ); + $pull_url = get_option( 'ds_npr_api_pull_url' ); ?> -
-

Get NPR Stories

- Set your API Key here.', TRUE);?> - Set your API Pull URL here.', TRUE);?> - +

Get NPR Stories

+ Set your API Key here.', TRUE ); + } + if ( !$pull_url ) { + nprstory_show_message ('You do not currently have an API Pull URL set. Set your API Pull URL here.', TRUE ); + } + + // Get the story ID from the URL, then paste it into the input's value field with esc_attr + $story_id = ''; + if ( ( isset( $_POST ) && isset( $_POST[ 'story_id' ] ) ) || ( isset( $_GET ) && isset( $_GET['story_id'] ) ) ) { + if ( !empty( $_POST['story_id'] ) ) { + $story_id = $_POST['story_id']; + } + if ( !empty($_GET['story_id'] ) ) { + $story_id = $_GET['story_id']; + } + } ?> -
-
- Enter an NPR Story ID or URL: - - - -
-
- -
- +
+ Enter an NPR Story ID or URL: + + + +
+ + post_status ); - $attrs = array( 'id' => 'ds-npr-update-push' ); + $attrs = [ 'id' => 'ds-npr-update-push' ]; - if ( $is_disabled ) { + if ( $is_disabled ) { $attrs['disabled'] = 'disabled'; } @@ -61,7 +61,6 @@ function nprstory_publish_meta_box( $post ) { ) ); echo ''; // end the "Send to NPR API" list item - ?> @@ -70,12 +69,12 @@ function nprstory_publish_meta_box( $post ) { * this section is only enabled if "include for listening in NPR One" is checked! * This section does not use https://developer.wordpress.org/reference/functions/touch_time/ because there does not seem to be a way to pass it a custom element */ - + $datetime = nprstory_get_post_expiry_datetime( $post ); ?>
- Expires on: + Expires on: %1$s', @@ -123,7 +122,7 @@ function nprstory_publish_meta_box_assets() { wp_register_script( 'nprstory_publish_meta_box_script', NPRSTORY_PLUGIN_URL . 'assets/js/meta-box.js', - array( 'jquery', 'jquery-ui-datepicker' ), + [ 'jquery', 'jquery-ui-datepicker' ], null, true ); @@ -158,4 +157,4 @@ function nprstory_publish_meta_box_prompt( $post ) { wp_kses_post( __( 'Your site administrator must set the NPR Story API Push URL in the NPR Story API plugin\'s settings in order to push to the NPR API.', 'nprapi' ) ) ); } -} +} \ No newline at end of file diff --git a/push_story.php b/push_story.php index a964698..86322d1 100644 --- a/push_story.php +++ b/push_story.php @@ -13,8 +13,8 @@ * @param Int $post_ID * @param WP_Post $post */ -function nprstory_api_push ( $post_ID, $post ) { - if ( ! current_user_can( 'publish_posts' ) ) { +function nprstory_api_push( $post_ID, $post ) { + if ( !current_user_can( 'publish_posts' ) ) { wp_die( __( 'You do not have permission to publish posts, and therefore you do not have permission to push posts to the NPR API.', 'nprapi' ), __( 'NPR Story API Error', 'nprapi' ), @@ -30,7 +30,7 @@ function nprstory_api_push ( $post_ID, $post ) { //if the push url isn't set, don't even try to push. $push_url = get_option( 'ds_npr_api_push_url' ); - if ( ! empty ( $push_url ) ) { + if ( !empty ( $push_url ) ) { // For now, only submit the sort of post that is the push post type, and then only if published if ( $post->post_type != $push_post_type || $post->post_status != 'publish' ) { return; @@ -49,7 +49,7 @@ function nprstory_api_push ( $post_ID, $post ) { $custom_content_meta = get_option( 'ds_npr_api_mapping_body' ); $body_field = $custom_content_meta; - if ( ! empty( $custom_content_meta ) && $custom_content_meta !== '#NONE#' && in_array( $custom_content_meta, $post_metas, true ) ) { + if ( !empty( $custom_content_meta ) && $custom_content_meta !== '#NONE#' && in_array( $custom_content_meta, $post_metas, true ) ) { $content = get_post_meta( $post->ID, $custom_content_meta, true ); } } @@ -67,9 +67,9 @@ function nprstory_api_push ( $post_ID, $post ) { // Don't push stories to the NPR story API if they were originally pulled from the NPR Story API $retrieved = get_post_meta( $post_ID, NPR_RETRIEVED_STORY_META_KEY, true ); if ( empty( $retrieved ) || $retrieved == 0 ) { - $api->send_request( $api->create_NPRML( $post ), $post_ID); + $api->send_request( $api->create_NPRML( $post ), $post_ID ); } else { - nprstory_error_log('Not pushing the story with post_ID ' . $post_ID . ' to the NPR Story API because it came from the API'); + nprstory_error_log( 'Not pushing the story with post_ID ' . $post_ID . ' to the NPR Story API because it came from the API' ); } } } @@ -81,8 +81,8 @@ function nprstory_api_push ( $post_ID, $post ) { * * @param unknown_type $post_ID */ -function nprstory_api_delete ( $post_ID ) { - if ( ! current_user_can( 'delete_others_posts' ) ) { +function nprstory_api_delete( $post_ID ) { + if ( !current_user_can( 'delete_others_posts' ) ) { wp_die( __('You do not have permission to delete posts in the NPR API. Users that can delete other users\' posts have that ability: administrators and editors.'), __('NPR Story API Error'), @@ -105,7 +105,7 @@ function nprstory_api_delete ( $post_ID ) { $post = get_post( $post_ID ); //if the push url isn't set, don't even try to delete. $push_url = get_option( 'ds_npr_api_push_url' ); - if ( $post->post_type == $push_post_type && ! empty( $push_url ) && ! empty( $api_id ) ) { + if ( $post->post_type == $push_post_type && !empty( $push_url ) && !empty( $api_id ) ) { // For now, only submit regular posts, and only on publish. if ( $post->post_type != 'post' || $post->post_status != 'publish' ) { return; @@ -113,10 +113,10 @@ function nprstory_api_delete ( $post_ID ) { $api = new NPRAPIWordpress(); $retrieved = get_post_meta( $post_ID, NPR_RETRIEVED_STORY_META_KEY, true ); - if ( empty( $retrieved ) || $retrieved == 0) { - $api->send_request( $api->create_NPRML( $post ), $post_ID); + if ( empty( $retrieved ) || $retrieved == 0 ) { + $api->send_request( $api->create_NPRML( $post ), $post_ID ); } else { - nprstory_error_log('Pushing delete action to the NPR Story API for the story with post_ID ' . $post_ID ); + nprstory_error_log( 'Pushing delete action to the NPR Story API for the story with post_ID ' . $post_ID ); $api->send_delete( $api_id ); } } @@ -140,13 +140,13 @@ function nprstory_api_delete ( $post_ID ) { * define the option page for mapping fields */ function nprstory_push_add_field_mapping_page() { - add_options_page( - 'NPR API Push Field Mapping', - 'NPR API Field Mapping', - 'manage_options', - 'ds_npr_api_push_mapping', - 'nprstory_add_field_mapping_page' - ); + add_options_page( + 'NPR API Push Field Mapping', + 'NPR API Field Mapping', + 'manage_options', + 'ds_npr_api_push_mapping', + 'nprstory_add_field_mapping_page' + ); } add_action( 'admin_menu', 'nprstory_push_add_field_mapping_page' ); @@ -165,24 +165,24 @@ function nprstory_api_push_mapping_callback() { } * @param $post_type */ function nprstory_push_meta_keys( $post_type = 'post' ) { - global $wpdb; - $limit = (int) apply_filters( 'postmeta_form_limit', 30 ); - $query = " - SELECT DISTINCT( $wpdb->postmeta.meta_key ) - FROM $wpdb->posts - LEFT JOIN $wpdb->postmeta - ON $wpdb->posts.ID = $wpdb->postmeta.post_id - WHERE $wpdb->posts.post_type = '%s' - AND $wpdb->postmeta.meta_key != '' - AND $wpdb->postmeta.meta_key NOT RegExp '(^[_0-9]wp_.+$)' - AND $wpdb->postmeta.meta_key NOT RegExp '(^[0-9]+$)' - "; - //AND $wpdb->postmeta.meta_key NOT RegExp '(^[_0-9].+$)' - $keys = $wpdb->get_col( $wpdb->prepare( $query, $post_type ) ); - if ( $keys ) natcasesort( $keys ); - - //set_transient('ds_npr_' . $post_type .'_meta_keys', $keys, 60*60*24); # 1 Day Expiration - return $keys; + global $wpdb; + $limit = (int) apply_filters( 'postmeta_form_limit', 30 ); + $query = " + SELECT DISTINCT( $wpdb->postmeta.meta_key ) + FROM $wpdb->posts + LEFT JOIN $wpdb->postmeta + ON $wpdb->posts.ID = $wpdb->postmeta.post_id + WHERE $wpdb->posts.post_type = '%s' + AND $wpdb->postmeta.meta_key != '' + AND $wpdb->postmeta.meta_key NOT RegExp '(^[_0-9]wp_.+$)' + AND $wpdb->postmeta.meta_key NOT RegExp '(^[0-9]+$)' + "; + //AND $wpdb->postmeta.meta_key NOT RegExp '(^[_0-9].+$)' + $keys = $wpdb->get_col( $wpdb->prepare( $query, $post_type ) ); + if ( $keys ) natcasesort( $keys ); + + //set_transient('ds_npr_' . $post_type .'_meta_keys', $keys, 60*60*24); # 1 Day Expiration + return $keys; } /** @@ -192,13 +192,13 @@ function nprstory_push_meta_keys( $post_type = 'post' ) { * @param $post_type default is 'post' */ function nprstory_get_post_meta_keys( $post_type = 'post' ) { - //$cache = get_transient('ds_npr_' . $post_type .'_meta_keys'); - if ( ! empty( $cache ) ) { - $meta_keys = $cache; - } else { - $meta_keys = nprstory_push_meta_keys( $post_type ); - } - return $meta_keys; + //$cache = get_transient('ds_npr_' . $post_type .'_meta_keys'); + if ( !empty( $cache ) ) { + $meta_keys = $cache; + } else { + $meta_keys = nprstory_push_meta_keys( $post_type ); + } + return $meta_keys; } /** @@ -223,7 +223,7 @@ function nprstory_validation_callback_select( $value ) { * @see nprstory_settings_init */ function nprstory_validation_callback_url( $value ) { - // because of the generic nature of this callback , it's not going to log anything, just do some sanitization + // because of the generic nature of this callback, it's not going to log anything, just do some sanitization // this value must be suitable for use as a form value return esc_attr( $value ); } @@ -294,37 +294,37 @@ function nprstory_validation_callback_debug( $value ) { } /** - Set up the fields for mapping custom meta fields to NRPML fields that we push to the API -*/ + * Set up the fields for mapping custom meta fields to NRPML fields that we push to the API + */ function nprstory_push_settings_init() { - add_settings_section( 'ds_npr_push_settings', 'NPR API PUSH settings', 'nprstory_api_push_settings_callback', 'ds_npr_api_push_mapping' ); + add_settings_section( 'ds_npr_push_settings', 'NPR API PUSH settings', 'nprstory_api_push_settings_callback', 'ds_npr_api_push_mapping' ); - add_settings_field( 'dp_npr_push_use_custom_map', 'Use Custom Settings', 'nprstory_api_use_custom_mapping_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'dp_npr_push_use_custom_map', 'nprstory_validation_callback_checkbox' ); + add_settings_field( 'dp_npr_push_use_custom_map', 'Use Custom Settings', 'nprstory_api_use_custom_mapping_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'dp_npr_push_use_custom_map', 'nprstory_validation_callback_checkbox' ); - add_settings_field( 'ds_npr_api_mapping_title', 'Story Title', 'nprstory_api_mapping_title_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_title', 'nprstory_validation_callback_select'); + add_settings_field( 'ds_npr_api_mapping_title', 'Story Title', 'nprstory_api_mapping_title_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_title', 'nprstory_validation_callback_select'); - add_settings_field( 'ds_npr_api_mapping_body', 'Story Body', 'nprstory_api_mapping_body_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_body' , 'nprstory_validation_callback_select'); + add_settings_field( 'ds_npr_api_mapping_body', 'Story Body', 'nprstory_api_mapping_body_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_body' , 'nprstory_validation_callback_select'); - add_settings_field( 'ds_npr_api_mapping_byline', 'Story Byline', 'nprstory_api_mapping_byline_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_byline' , 'nprstory_validation_callback_select'); + add_settings_field( 'ds_npr_api_mapping_byline', 'Story Byline', 'nprstory_api_mapping_byline_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_byline' , 'nprstory_validation_callback_select'); - add_settings_field( 'ds_npr_api_mapping_media_credit', 'Media Credit Field', 'nprstory_api_mapping_media_credit_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_media_credit' , 'nprstory_validation_callback_select'); + add_settings_field( 'ds_npr_api_mapping_media_credit', 'Media Credit Field', 'nprstory_api_mapping_media_credit_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_media_credit' , 'nprstory_validation_callback_select'); - add_settings_field( 'ds_npr_api_mapping_media_agency', 'Media Agency Field', 'nprstory_api_mapping_media_agency_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_media_agency' , 'nprstory_validation_callback_select'); - /** This will add the mapping for media distribution. But for now, hold off. - add_settings_field( 'ds_npr_api_mapping_distribute_media', 'Distribute Media Field', 'nprstory_api_mapping_distribute_media_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_distribute_media' , 'nprstory_validation_callback_select'); + add_settings_field( 'ds_npr_api_mapping_media_agency', 'Media Agency Field', 'nprstory_api_mapping_media_agency_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_media_agency' , 'nprstory_validation_callback_select'); + /* This will add the mapping for media distribution. But for now, hold off. + add_settings_field( 'ds_npr_api_mapping_distribute_media', 'Distribute Media Field', 'nprstory_api_mapping_distribute_media_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_distribute_media' , 'nprstory_validation_callback_select'); - add_settings_field( 'ds_npr_api_mapping_distribute_media_polarity', 'Distribute Media Field Polarity', 'nprstory_api_mapping_distribute_media_polarity_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); - register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_distribute_media_polarity' , 'nprstory_validation_callback_select'); - //nprstory_api_mapping_distribute_media_polarity_callback - * - */ + add_settings_field( 'ds_npr_api_mapping_distribute_media_polarity', 'Distribute Media Field Polarity', 'nprstory_api_mapping_distribute_media_polarity_callback', 'ds_npr_api_push_mapping', 'ds_npr_push_settings' ); + register_setting( 'ds_npr_api_push_mapping', 'ds_npr_api_mapping_distribute_media_polarity' , 'nprstory_validation_callback_select'); + //nprstory_api_mapping_distribute_media_polarity_callback + * + */ } add_action( 'admin_init', 'nprstory_push_settings_init' ); @@ -332,20 +332,19 @@ function nprstory_push_settings_init() { /** * call back for push settings */ -function nprstory_api_push_settings_callback() { -} +function nprstory_api_push_settings_callback() { } /** * callback for use custom mapping checkbox */ -function nprstory_api_use_custom_mapping_callback(){ +function nprstory_api_use_custom_mapping_callback() { $use_custom = get_option( 'dp_npr_push_use_custom_map' ); $check_box_string = "Do Distribute or Do Not Distribute? '; $selected = get_option( 'ds_npr_api_mapping_distribute_media_polarity' ); - $keys = array( 1 => "DO Distribute", 0 => "DO NOT Dsitribute"); - foreach ( $keys as $i=>$key ) { + $keys = [ 1 => "DO Distribute", 0 => "DO NOT Dsitribute" ]; + foreach ( $keys as $i => $key ) { $option_string = "\n
"; +} + +function nprstory_api_select_category_callback( $i ) { + $selected = get_option( 'ds_npr_query_category_' . $i ); + settype( $selected, "integer" ); + $args = [ + 'show_option_none' => __( 'Select category', '' ), + 'name' => 'ds_npr_query_category_' . $i, + 'hierarchical' => true, + 'show_count' => 0, + 'orderby' => 'name', + 'echo' => 0, + 'selected' => $selected, + 'hide_empty' => 0, + 'multiple' => true + ]; + $select = wp_dropdown_categories( $args ); + + echo $select; +} + +function nprstory_api_select_category_callback($i) { + $selected =get_option( 'ds_npr_query_category_' . $i ); + settype($selected, "integer"); + $args = array( + 'show_option_none' => __( 'Select category', '' ), + 'name' => 'ds_npr_query_category_'.$i, + 'hierarchical' => true, + 'show_count' => 0, + 'orderby' => 'name', + 'echo' => 0, + 'selected' => $selected, + 'hide_empty' => 0, + 'multiple' => true + ); + $select = wp_dropdown_categories( $args ); + + echo $select; } function nprstory_api_query_callback( $i ) { @@ -183,13 +254,12 @@ function nprstory_api_query_callback( $i ) { wp_nonce_field( 'nprstory_nonce_ds_npr_query_' . $i, 'nprstory_nonce_ds_npr_query_' . $i . '_name', true, true ); } - function ds_npr_api_query_tags_callback( $i ) { $name = 'ds_npr_query_tags_' . $i; $option = get_option( $name ); - + echo "

Add tag(s) to each story pulled from NPR (comma separated).

"; - wp_nonce_field( 'nprstory_nonce_ds_npr_tags_' . $i, 'nprstory_nonce_ds_npr_tags_' . $i . '_name', true, true ); + wp_nonce_field( 'nprstory_nonce_ds_npr_tags_' . $i, 'nprstory_nonce_ds_npr_tags_' . $i . '_name', true, true ); echo "


"; } @@ -200,26 +270,26 @@ function nprstory_api_num_multi_callback() { } function nprstory_api_key_callback() { - $option = get_option( 'ds_npr_api_key' ); - echo ""; + $option = get_option( 'ds_npr_api_key' ); + echo ""; wp_nonce_field( 'nprstory_nonce_ds_npr_api_key', 'nprstory_nonce_ds_npr_api_key_name', true, true ); } function nprstory_api_pull_url_callback() { - $option = get_option( 'ds_npr_api_pull_url' ); - echo ""; + $option = get_option( 'ds_npr_api_pull_url' ); + echo ""; wp_nonce_field( 'nprstory_nonce_ds_npr_api_pull_url', 'nprstory_nonce_ds_npr_api_pull_url_name', true, true ); } function nprstory_api_push_url_callback() { - $option = get_option( 'ds_npr_api_push_url' ); - echo ""; + $option = get_option( 'ds_npr_api_push_url' ); + echo ""; wp_nonce_field( 'nprstory_nonce_ds_npr_api_push_url', 'nprstory_nonce_ds_npr_api_push_url_name', true, true ); } function nprstory_api_org_id_callback() { - $option = get_option( 'ds_npr_api_org_id' ); - echo ""; + $option = get_option( 'ds_npr_api_org_id' ); + echo ""; wp_nonce_field( 'nprstory_nonce_ds_npr_api_org_id', 'nprstory_nonce_ds_npr_api_org_id_name', true, true ); } @@ -231,17 +301,17 @@ function nprstory_pull_post_type_callback() { function nprstory_push_post_type_callback() { $post_types = get_post_types(); nprstory_show_post_types_select( 'ds_npr_push_post_type', $post_types ); - echo ('
If you change the Push Post Type setting remember to update the mappings for API Fields at NPR API Field Mapping page.
'); + echo ('
If you change the Push Post Type setting remember to update the mappings for API Fields at NPR API Field Mapping page.
'); } function nprstory_push_story_permissions_callback() { - $permissions_groups = nprstory_get_permission_groups(); + $permissions_groups = nprstory_get_permission_groups(); - if (!empty($permissions_groups)){ + if ( !empty( $permissions_groups ) ) { nprstory_show_perms_select( 'ds_npr_story_default_permission', $permissions_groups ); - echo ('
This is where you select the default permissions group to use when pushing stories to the NPR API.
'); + echo '
This is where you select the default permissions group to use when pushing stories to the NPR API.
'; } else { - echo ('
You have no Permission Groups defined with the NPR API.
'); + echo '
You have no Permission Groups defined with the NPR API.
'; } } @@ -250,15 +320,15 @@ function nprstory_push_story_permissions_callback() { * @param $field_name * @param $keys - an array like (1=>'Value1', 2=>'Value2', 3=>'Value3'); */ -function nprstory_show_post_types_select( $field_name, $keys ){ +function nprstory_show_post_types_select( $field_name, $keys ) { $selected = get_option( $field_name ); echo "
"; echo ''; foreach ( $keys as $id => $key ) { $option_string = "\n"; + $option_string .= "value='" . esc_attr( $id ) . "'>" . esc_html( $key['name'] ) . " "; echo $option_string; } echo "
"; diff --git a/settings_ui.php b/settings_ui.php index fdffb8b..4de5afc 100644 --- a/settings_ui.php +++ b/settings_ui.php @@ -8,13 +8,13 @@ */ function nprstory_api_options_page() { ?> -
-
- - - -
-
+
+
+ + + +
+
-

Create an NPR API query (see the NPR API query generator). Enter your queries into one of the rows below to have stories on that query automatically publish to your site. Please note, you do not need to include your API key to the query.

-
- - - -
-
+

Create an NPR API query (see the NPR API query generator). Enter your queries into one of the rows below to have stories on that query automatically publish to your site. Please note, you do not need to include your API key to the query.

+
+ + + +
+
-
Use this page to map your custom WordPress Meta fields to fields sent the NPR API.

Clicking the Use Custom Settings checkbox will enable these mappings. If you wish to use the default mapping for a field, select — default — and we will use the obvious WordPress field.

-

-

Select for the Meta fields for the post type
- - -
- Use this page to map your custom WordPress Meta fields to fields sent the NPR API. Clicking the Use Custom Settings checkbox will enable these mappings. If you wish to use the default mapping for a field, select — default — and we will use the obvious WordPress field. +
Select for the Meta fields for the post type
+ + + +