true,
'cx' => true,
'cy' => true,
'r' => true,
'x' => true,
'y' => true,
'rx' => true,
'width' => true,
'height' => true,
'fill' => true,
'opacity' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'stroke-linejoin' => true,
);
return array(
'svg' => array(
'class' => true,
'viewbox' => true,
'width' => true,
'height' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'stroke-linejoin' => true,
'aria-hidden' => true,
'xmlns' => true,
),
'path' => $shape,
'circle' => $shape,
'rect' => $shape,
'span' => array(
'class' => true,
'aria-hidden' => true,
'style' => true,
),
'b' => array( 'class' => true ),
'i' => array( 'class' => true ),
'a' => array(
'class' => true,
'href' => true,
),
);
}
/**
* Tags and attributes of a rendered gallery, for wp_kses().
*
* @return array
*/
function tpika_kses_gallery() {
$data = array(
'id' => true,
'class' => true,
'style' => true,
'title' => true,
'role' => true,
'aria-label' => true,
'aria-hidden' => true,
'aria-live' => true,
'aria-pressed' => true,
'data-settings' => true,
'data-filter' => true,
'data-filters' => true,
'data-index' => true,
'data-w' => true,
'data-h' => true,
'data-type' => true,
'data-full' => true,
'data-link' => true,
'data-caption' => true,
'data-color' => true,
'data-text' => true,
);
return array_merge(
tpika_kses_icons(),
array(
'div' => $data,
'figure' => $data,
'figcaption' => $data,
'p' => $data,
'span' => $data,
'a' => $data + array(
'href' => true,
'target' => true,
'rel' => true,
),
'button' => $data + array( 'type' => true ),
'select' => $data,
'option' => $data + array(
'value' => true,
'selected' => true,
),
'img' => $data + array(
'src' => true,
'srcset' => true,
'sizes' => true,
'width' => true,
'height' => true,
'alt' => true,
'loading' => true,
'decoding' => true,
),
)
);
}
/**
* Language fallback: a site in de_CH, de_AT, es_MX … uses the closest bundled translation (de_DE, es_ES …).
* Hooked on load_textdomain_mofile and load_script_translation_file.
*
* @param string|false $file Translation file WordPress is about to load.
* @return string|false
*/
function tpika_locale_fallback_file( $file ) {
if ( ! $file || ! is_string( $file ) || file_exists( $file ) ) {
return $file;
}
if ( ! preg_match( '/^3pika-gallery-(([a-z]{2,3})(?:_[A-Za-z0-9_]+)?)((?:-[a-z0-9\-]+)?\.(?:mo|json))$/', basename( $file ), $m ) ) {
return $file;
}
// Variants and closely related languages that have no translation of their own.
$related = array(
'pt_AO' => 'pt_PT',
'pt_PT_ao90' => 'pt_PT',
'zh_HK' => 'zh_TW',
'zh_SG' => 'zh_CN',
'ary' => 'ar',
'haz' => 'fa_IR',
'szl' => 'pl_PL',
'dsb' => 'de_DE',
'hsb' => 'de_DE',
'fur' => 'it_IT',
'arg' => 'es_ES',
'sah' => 'ru_RU',
'tah' => 'fr_FR',
'kab' => 'fr_FR',
'snd' => 'ur',
'skr' => 'ur',
);
$base = TPIKA_PATH . 'languages/3pika-gallery-';
if ( isset( $related[ $m[1] ] ) && file_exists( $base . $related[ $m[1] ] . $m[3] ) ) {
return $base . $related[ $m[1] ] . $m[3];
}
if ( file_exists( $base . $m[2] . $m[3] ) ) {
return $base . $m[2] . $m[3];
}
$found = glob( $base . $m[2] . '_*' . $m[3] );
return $found ? $found[0] : $file;
}
/**
* Get all galleries (WP_Post objects).
*
* @param array $args Extra WP_Query args.
* @return WP_Post[]
*/
function tpika_get_galleries( $args = array() ) {
$query = new WP_Query(
wp_parse_args(
$args,
array(
'post_type' => TPIKA_Post_Type::TYPE,
'post_status' => array( 'publish', 'draft' ),
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'no_found_rows' => true,
)
)
);
return $query->posts;
}
/**
* id => title list for pickers.
*
* @return array
*/
function tpika_gallery_options() {
$out = array();
foreach ( tpika_get_galleries() as $post ) {
/* translators: %d: gallery ID */
$out[ $post->ID ] = $post->post_title ? $post->post_title : sprintf( __( 'Gallery #%d', '3pika-gallery' ), $post->ID );
}
return $out;
}
/**
* Shortcode string for a gallery.
*
* @param int $id Gallery ID.
* @return string
*/
function tpika_shortcode( $id ) {
return '[3pika_gallery id="' . absint( $id ) . '"]';
}
/**
* Render a gallery (template tag). The markup is escaped and ready to print.
*
* @param int $id Gallery ID.
* @param array $args Overrides.
* @return string
*/
function tpika_render( $id, $args = array() ) {
$html = wp_kses( TPIKA_Renderer::render( $id, $args ), tpika_kses_gallery() );
return $html;
}
/**
* Admin URL helper.
*
* @param string $page Page slug.
* @param array $args Query args.
* @return string
*/
function tpika_admin_url( $page, $args = array() ) {
return add_query_arg( array_merge( array( 'page' => $page ), $args ), admin_url( 'admin.php' ) );
}
/**
* Preview URL for a gallery (editors only).
*
* @param int $id Gallery ID.
* @return string
*/
function tpika_preview_url( $id ) {
$id = absint( $id );
return add_query_arg(
array(
'tpika_preview' => $id,
'_wpnonce' => wp_create_nonce( 'tpika_preview_' . $id ),
),
home_url( '/' )
);
}
/**
* Small inline SVG icon set.
*
* @param string $name Icon name.
* @return string
*/
function tpika_icon( $name ) {
$icons = array(
'close' => '',
'prev' => '',
'next' => '',
'zoom' => '',
'play' => '',
'pause' => '',
'fullscreen' => '',
'share' => '',
'download' => '',
'video' => '',
/* ---- admin UI (18px, stroke) ---- */
'images' => '',
'plus' => '',
'film' => '',
'copy' => '',
'edit' => '',
'trash' => '',
'eye' => '',
'duplicate' => '',
'export' => '',
'import' => '',
'settings' => '',
'key' => '',
'check' => '',
'minus' => '',
'grid' => '',
'back' => '',
'drag' => '',
'tag' => '',
'layout' => '',
'lightbox' => '',
'pages' => '',
'shield' => '',
'code' => '',
'sliders' => '',
'star' => '',
'external' => '',
'spark' => '',
'lock' => '',
'unlock' => '',
/* ---- hover icons (front-end, 22px stroke) ---- */
'hi-zoom' => '',
'hi-plus' => '',
'hi-expand' => '',
'hi-eye' => '',
'hi-link' => '',
);
return isset( $icons[ $name ] ) ? $icons[ $name ] : '';
}
/**
* Readable text colour (black or white) for a background colour.
*
* @param string $hex Background colour (#rrggbb).
* @return string
*/
function tpika_contrast_color( $hex ) {
$hex = ltrim( (string) $hex, '#' );
if ( 3 === strlen( $hex ) ) {
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
}
if ( 6 !== strlen( $hex ) || ! ctype_xdigit( $hex ) ) {
return '#ffffff';
}
$r = hexdec( substr( $hex, 0, 2 ) );
$g = hexdec( substr( $hex, 2, 2 ) );
$b = hexdec( substr( $hex, 4, 2 ) );
$l = ( 0.299 * $r + 0.587 * $g + 0.114 * $b ) / 255;
return $l > 0.6 ? '#111111' : '#ffffff';
}
/**
* Thumbnail URLs of the first items of a gallery (admin cards).
*
* @param int $id Gallery ID.
* @param int $limit Max thumbs.
* @return string[]
*/
function tpika_gallery_thumbs( $id, $limit = 4 ) {
$images = get_post_meta( $id, '_tpika_images', true );
$out = array();
if ( ! is_array( $images ) ) {
return $out;
}
foreach ( $images as $img ) {
if ( count( $out ) >= $limit ) {
break;
}
$src = '';
if ( ! empty( $img['id'] ) ) {
$s = wp_get_attachment_image_src( (int) $img['id'], 'medium' );
$src = $s ? $s[0] : '';
}
if ( $src ) {
$out[] = $src;
}
}
return $out;
}
/**
* Icons for the settings sections (nav).
*
* @param string $slug Section slug.
* @return string
*/
function tpika_section_icon( $slug ) {
$map = array(
'layout' => 'layout',
'filters' => 'tag',
'lightbox' => 'lightbox',
'pagination' => 'pages',
'protection' => 'shield',
'advanced' => 'code',
'general' => 'sliders',
);
return tpika_icon( isset( $map[ $slug ] ) ? $map[ $slug ] : 'settings' );
}