406 lines
13 KiB
PHP
406 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This class renders the html for the event avatar.
|
|
*
|
|
* @author Time.ly Network Inc.
|
|
* @since 2.0
|
|
*
|
|
* @package AI1EC
|
|
* @subpackage AI1EC.View.Event
|
|
*/
|
|
class Ai1ec_View_Event_Avatar extends Ai1ec_Base {
|
|
|
|
/**
|
|
* Get HTML markup for the post's "avatar" image according conditional
|
|
* fallback model.
|
|
*
|
|
* Accepts an ordered array of named avatar $fallbacks. Also accepts a string
|
|
* of space-separated classes to add to the default classes.
|
|
* @param Ai1ec_Event $event The event to get the avatar for
|
|
* @param array|null $fallback_order Order of fallback in searching for
|
|
* images, or null to use default
|
|
* @param string $classes A space-separated list of CSS classes
|
|
* to apply to the outer <div> element.
|
|
* @param boolean $wrap_permalink Whether to wrap the element in a link
|
|
* to the event details page.
|
|
*
|
|
* @return string String of HTML if image is found
|
|
*/
|
|
public function get_event_avatar(
|
|
Ai1ec_Event $event,
|
|
$fallback_order = null,
|
|
$classes = '',
|
|
$wrap_permalink = true
|
|
) {
|
|
$source = $size = null;
|
|
$url = $this->get_event_avatar_url(
|
|
$event,
|
|
$fallback_order,
|
|
$source,
|
|
$size
|
|
);
|
|
|
|
if ( empty( $url ) ) {
|
|
return '';
|
|
}
|
|
|
|
$url = esc_attr( $url );
|
|
$classes = esc_attr( $classes );
|
|
|
|
// Set the alt tag (helpful for SEO).
|
|
$alt = $event->get( 'post' )->post_title;
|
|
$location = $this->_registry->get( 'view.event.location' )->get_short_location( $event );
|
|
if ( ! empty( $location ) ) {
|
|
$alt .= ' @ ' . $location;
|
|
}
|
|
|
|
$alt = esc_attr( $alt );
|
|
$size_attr = $size[0] ? "width=\"$size[0]\" height=\"$size[1]\"" : "";
|
|
$html = '<img src="' . $url . '" alt="' . $alt . '" ' .
|
|
$size_attr . ' />';
|
|
|
|
if ( $wrap_permalink ) {
|
|
$permalink = add_query_arg(
|
|
'instance_id',
|
|
$event->get( 'instance_id' ),
|
|
get_permalink( $event->get( 'post_id' ) )
|
|
);
|
|
$html = '<a href="' . $permalink . '">' . $html . '</a>';
|
|
}
|
|
|
|
$classes .= ' ai1ec-' . $source;
|
|
$classes .= ( $size[0] > $size[1] )
|
|
? ' ai1ec-landscape'
|
|
: ' ai1ec-portrait';
|
|
$html = '<div class="ai1ec-event-avatar timely ' . $classes . '">' .
|
|
$html . '</div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Get the post's "avatar" image url according conditional fallback model.
|
|
*
|
|
* Accepts an ordered array of named methods for $fallback order. Returns
|
|
* image URL or null if no image found. Also returns matching fallback in the
|
|
* $source reference.
|
|
*
|
|
* @param array|null $fallback_order Order of fallbacks in search for images
|
|
* @param null $source Fallback that returned matching image,
|
|
* returned format is string
|
|
* @param null $size (width, height) array of returned image
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_event_avatar_url(
|
|
Ai1ec_Event $event,
|
|
$fallback_order = null,
|
|
&$source = null,
|
|
&$size = null
|
|
) {
|
|
if ( empty( $fallback_order ) ) {
|
|
$fallback_order = array(
|
|
'post_thumbnail',
|
|
'content_img',
|
|
'category_avatar',
|
|
'default_avatar',
|
|
);
|
|
}
|
|
|
|
$valid_fallbacks = $this->_get_valid_fallbacks();
|
|
|
|
foreach ( $fallback_order as $fallback ) {
|
|
if ( ! isset( $valid_fallbacks[$fallback] ) ) {
|
|
continue;
|
|
}
|
|
|
|
$function = $valid_fallbacks[$fallback];
|
|
$url = null;
|
|
if (
|
|
! is_array( $function ) &&
|
|
method_exists( $this, $function )
|
|
) {
|
|
$url = $this->$function( $event, $size );
|
|
} else if ( is_callable( $function ) ) {
|
|
$url = call_user_func_array( $function, array( $event, &$size ) );
|
|
}
|
|
if ( null !== $url ) {
|
|
$source = $fallback;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( empty( $url ) ) {
|
|
return null;
|
|
}
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Read post meta for post-thumbnail and return its URL as a string.
|
|
*
|
|
* @param Ai1ec_Event $event Event object.
|
|
* @param null $size (width, height) array of returned image.
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_post_thumbnail_url( Ai1ec_Event $event, &$size = null ) {
|
|
return $this->_get_post_attachment_url(
|
|
$event,
|
|
array(
|
|
'medium',
|
|
'large',
|
|
'full',
|
|
),
|
|
$size
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Read post meta for post-image and return its URL as a string.
|
|
*
|
|
* @param Ai1ec_Event $event Event object.
|
|
* @param null $size (width, height) array of returned image.
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_post_image_url( Ai1ec_Event $event, &$size = null ) {
|
|
return $this->_get_post_attachment_url(
|
|
$event,
|
|
array(
|
|
'full',
|
|
'large',
|
|
'medium'
|
|
),
|
|
$size
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Read post meta for featured image and return its URL as a string.
|
|
*
|
|
* @param Ai1ec_Event $event Event object.
|
|
* @param null $size (width, height) array of returned image.
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_featured_image_url( Ai1ec_Event $event, &$size = null ) {
|
|
$featured_image = get_post_meta( $event->get( 'post_id' ) , '_featured_image', true );
|
|
if ( empty( $featured_image ) ) {
|
|
return $this->_get_post_attachment_url(
|
|
$event,
|
|
array(
|
|
'full',
|
|
'large',
|
|
'medium'
|
|
),
|
|
$size
|
|
);
|
|
} else {
|
|
$priority_order = array( 'large', 'full', 'medium', 'thumbnail' );
|
|
$url = null;
|
|
foreach ( $priority_order as $priority ) {
|
|
foreach ( $featured_image as $values_arr ) {
|
|
if ( $values_arr[0] === $priority ) {
|
|
$url = $values_arr[1];
|
|
$size = array( $values_arr[2], $values_arr[3] );
|
|
break;
|
|
}
|
|
}
|
|
if ( null !== $url ) {
|
|
break;
|
|
}
|
|
}
|
|
return $url;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove the avatar url from the event content
|
|
*/
|
|
public function remove_avatar_url( $content ) {
|
|
return preg_replace( '/<div[^<>]+class=[\'"]?ai1ec-event-avatar[^<>]*[\'"]?[^<>]+>.+<\/div>[.\s]*/'
|
|
, ''
|
|
, $content );
|
|
}
|
|
|
|
/**
|
|
* Simple regex-parse of post_content for matches of <img src="foo" />; if
|
|
* one is found, return its URL.
|
|
*
|
|
* @param Ai1ec_Event $event
|
|
* @param null $size (width, height) array of returned image
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_content_img_url( Ai1ec_Event $event, &$size = null ) {
|
|
$matches = $this->get_image_from_content(
|
|
$event->get( 'post' )->post_content
|
|
);
|
|
// Check if we have a result, otherwise a notice is issued.
|
|
if ( empty( $matches ) ) {
|
|
return null;
|
|
}
|
|
|
|
$url = $matches[2];
|
|
$size = array( 0, 0 );
|
|
|
|
// Try to detect width and height.
|
|
$attrs = $matches[1] . $matches[3];
|
|
$matches = null;
|
|
preg_match_all(
|
|
'/(width|height)=["\']?(\d+)/i',
|
|
$attrs,
|
|
$matches,
|
|
PREG_SET_ORDER
|
|
);
|
|
// Check if we have a result, otherwise a notice is issued.
|
|
if ( ! empty( $matches ) ) {
|
|
foreach ( $matches as $match ) {
|
|
$size[ $match[1] === 'width' ? 0 : 1 ] = $match[2];
|
|
}
|
|
}
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Get an image tag from an html string
|
|
*
|
|
* @param string $content
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_image_from_content( $content ) {
|
|
preg_match(
|
|
'/<img([^>]+)src=["\']?([^"\'\ >]+)([^>]*)>/i',
|
|
$content,
|
|
$matches
|
|
);
|
|
return $matches;
|
|
}
|
|
/**
|
|
* Returns default avatar image (normally when no other ones are available).
|
|
*
|
|
* @param null $size (width, height) array of returned image
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_default_avatar_url( &$size = null ) {
|
|
$loader = $this->_registry->get( 'theme.loader' );
|
|
$file = $loader->get_file( 'default-event-avatar.png', array(), false );
|
|
$size = array( 256, 256 );
|
|
return $file->get_url();
|
|
}
|
|
|
|
/**
|
|
* Returns avatar image for event's deepest category, if any.
|
|
*
|
|
* @param Ai1ec_Event $event Avatar requester.
|
|
* @param void $size Unused argument.
|
|
*
|
|
* @return string|null Avatar's HTML or null if none.
|
|
*/
|
|
public function get_category_avatar_url( Ai1ec_Event $event, &$size = null ) {
|
|
$db = $this->_registry->get( 'dbi.dbi' );
|
|
|
|
$terms = $this->_registry->get( 'model.taxonomy' )->get_post_categories(
|
|
$event->get( 'post_id' )
|
|
);
|
|
if ( empty( $terms ) ) {
|
|
return null;
|
|
}
|
|
|
|
$terms_by_id = array();
|
|
// Key $terms by term_id rather than arbitrary int.
|
|
foreach ( $terms as $term ) {
|
|
$terms_by_id[$term->term_id] = $term;
|
|
}
|
|
|
|
// Array to store term depths, sorted later.
|
|
$term_depths = array();
|
|
foreach ( $terms_by_id as $term ) {
|
|
$depth = 0;
|
|
$ancestor = $term;
|
|
while ( ! empty( $ancestor->parent ) ) {
|
|
$depth++;
|
|
if ( ! isset( $terms_by_id[$ancestor->parent] ) ) {
|
|
break;
|
|
}
|
|
$ancestor = $terms_by_id[$ancestor->parent];
|
|
}
|
|
// Store negative depths for asort() to order from deepest to shallowest.
|
|
$term_depths[$term->term_id] = -$depth;
|
|
}
|
|
// Order term IDs by depth.
|
|
asort( $term_depths );
|
|
|
|
$url = '';
|
|
$model = $this->_registry->get( 'model.taxonomy' );
|
|
// Starting at deepest depth, find the first category that has an avatar.
|
|
foreach ( $term_depths as $term_id => $depth ) {
|
|
$term_image = $model->get_category_image( $term_id );
|
|
if ( $term_image ) {
|
|
$url = $term_image;
|
|
break;
|
|
}
|
|
}
|
|
return empty( $url ) ? null : $url;
|
|
}
|
|
|
|
/**
|
|
* Read post meta for post-attachment and return its URL as a string.
|
|
*
|
|
* @param Ai1ec_Event $event Event object.
|
|
* @param array $ordered_img_sizes Image sizes order.
|
|
* @param null $size (width, height) array of returned
|
|
* image.
|
|
*
|
|
* @return string|null
|
|
*/
|
|
protected function _get_post_attachment_url(
|
|
Ai1ec_Event $event,
|
|
array $ordered_img_sizes,
|
|
&$size = null
|
|
) {
|
|
// Since WP does will return null if the wrong size is targeted,
|
|
// we iterate over an array of sizes, breaking if a URL is found.
|
|
foreach ( $ordered_img_sizes as $size ) {
|
|
$attributes = wp_get_attachment_image_src(
|
|
get_post_thumbnail_id( $event->get( 'post_id' ) ), $size
|
|
);
|
|
if ( $attributes ) {
|
|
$url = array_shift( $attributes );
|
|
$size = $attributes;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return empty( $url ) ? null : $url;
|
|
}
|
|
|
|
/**
|
|
* Returns list of valid fallbacks.
|
|
*
|
|
* @return array List of valid fallbacks.
|
|
*/
|
|
protected function _get_valid_fallbacks() {
|
|
static $fallbacks;
|
|
if ( null === $fallbacks ) {
|
|
$fallbacks = apply_filters(
|
|
'ai1ec_avatar_valid_callbacks',
|
|
array(
|
|
'post_image' => 'get_post_image_url',
|
|
'post_thumbnail' => 'get_post_thumbnail_url',
|
|
'content_img' => 'get_content_img_url',
|
|
'category_avatar' => 'get_category_avatar_url',
|
|
'default_avatar' => 'get_default_avatar_url',
|
|
'featured_image' => 'get_featured_image_url'
|
|
)
|
|
);
|
|
}
|
|
return $fallbacks;
|
|
}
|
|
|
|
}
|