3 // Declare theme features
4 add_theme_support( 'post-thumbnails' );
6 function register_menus() {
8 add_action( 'init', function () {
9 register_nav_menu('site-nav', __( 'Site Navigation' ));
10 register_nav_menu('footer-nav', __( 'Footer Navigation' ));
11 register_nav_menu('sitemap', __( 'Site Map Page' ));
14 function modify_contact_methods($profile_fields) {
17 $profile_fields['twitter'] = 'Twitter Handle';
18 unset($profile_fields['aim']);
19 unset($profile_fields['yim']);
20 unset($profile_fields['jabber']);
22 return $profile_fields;
25 add_filter('user_contactmethods', function ($fields) {
26 // Add Twitter field to user profiles
27 $fields['twitter'] = 'Twitter Handle';
29 // Remove unused social networks
30 unset($fields['aim']);
31 unset($fields['yim']);
32 unset($fields['jabber']);
37 add_action('init', function () {
38 register_sidebar(array(
39 'name'=> 'Home Tiles',
41 'before_widget' => '',
48 add_filter('the_title', function( $title ) {
49 if ( is_admin() ) return $title;
50 $title = str_replace(": ", ":<br>", $title);
54 // For RSS feeds, convert relative URIs to absolute
55 add_filter('the_content', function($content) {
56 if (!is_feed()) return $content;
57 $base = trailingslashit(get_site_url());
58 $content = preg_replace('/<a([^>]*) href="\/([^"]*)"/', '<a$1 href="' . $base . '$2"', $content);
59 $content = preg_replace('/<img([^>]*) src="\/([^"]*)"/', '<img$1 src="' . $base . '$2"', $content);
63 add_action('wp_head', function () {
64 if (!is_single()) return;
66 $style = get_post_meta(get_the_ID(), 'style', true);
68 echo '<style type="text/css">' . $style . '</style>';
70 $script = get_post_meta(get_the_ID(), 'script', true);
72 echo '<script type="text/javascript">' . $script . '</script>';
75 add_action('the_post', function($post) {
77 if (!is_single()) return;
79 $content = $post->post_content;
80 if (strpos($content, 'abovetitle') === false) return;
81 if (strpos($content, '<img') !== 0) return;
83 $post->post_title_img = substr($content, 0, strpos($content, ">\n") + 3);
84 $post->post_content = str_replace($post->post_title_img, '', $content);
85 $pages = array($post->post_content);
88 function before_the_title() {
91 if ( isset($post->post_title_img) )
92 echo wp_make_content_images_responsive($post->post_title_img);
95 // Hide category 41: Legacy from archives
96 add_filter('pre_get_posts', function ($query) {
97 if ( $query->is_home() )
98 $query->set('cat', '-41');
102 include('widgets/post.php');
103 include('widgets/icon.php');
104 include('widgets/twitter.php');
105 include('widgets/page.php');
107 add_filter( 'get_the_excerpt', function( $excerpt ) {
108 $sentences = preg_split( '/(\.|!|\?)\s/', $excerpt, 2, PREG_SPLIT_DELIM_CAPTURE );
110 // if ( empty($sentences[1]) )
111 // $sentences[1] = '…';
113 return $sentences[0] . $sentences[1];
117 function table_of_contents() {
118 if ( class_exists('WebKitTableOfContents') )
119 WebKitTableOfContents::markup();
122 function has_table_of_contents() {
123 if ( class_exists('WebKitTableOfContents') )
124 return WebKitTableOfContents::hasIndex();
127 function table_of_contents_index( $content, $post_id ) {
128 if ( ! class_exists('WebKitTableOfContents') )
130 $content = WebKitTableOfContents::parse($content);
131 WebKitTableOfContents::wp_insert_post($post_id);
135 function is_super_cache_enabled() {
136 global $super_cache_enabled;
137 return (isset($super_cache_enabled) && true === $super_cache_enabled);
140 function tag_post_image_luminance( $post_id ) {
144 // Get the image data
145 $image_src = wp_get_attachment_image_src( get_post_thumbnail_id($post_id), 'small' );
146 $image_url = $image_src[0];
148 if ( empty($image_url) ) return $post_id;
150 // detect luminence value
151 $luminance = calculate_image_luminance($image_url);
152 $tags = wp_get_post_tags($post_id, array('fields' => 'names'));
154 if ( $luminance < $threshold )
156 elseif ( false !== ( $key = array_search('dark', $messages) ) )
157 unset($tags[ $key ]);
160 if ( ! empty($tags) )
161 wp_set_post_tags( $post_id, $tags, true );
166 function calculate_image_luminance($image_url) {
167 // Get original image dimensions
168 $size = getimagesize($image_url);
170 // Create image resource from source image
171 $image = ImageCreateFromString(file_get_contents($image_url));
173 // Allocate image resource
174 $sample = ImageCreateTrueColor(1, 1);
176 // Flood fill with a white background (to properly calculate luminance of PNGs with alpha)
177 ImageFill($sample , 0, 0, ImageColorAllocate($sample, 255, 255, 255));
179 // Downsample to 1x1 image
180 ImageCopyResampled($sample, $image, 0, 0, 0, 0, 1, 1, $size[0], $size[1]);
182 // Get the RGB value of the pixel
183 $rgb = ImageColorAt($sample, 0, 0);
184 $red = ($rgb >> 16) & 0xFF;
185 $green = ($rgb >> 8) & 0xFF;
188 // Calculate relative luminance value (https://en.wikipedia.org/wiki/Relative_luminance)
189 return ( 0.2126 * $red + 0.7152 * $green + 0.0722 * $blue);
192 function html_select_options(array $list, $selected = null, $values = false, $append = false) {
193 if ( ! is_array($list) ) return '';
197 // Append the options if the selected value doesn't exist
198 if ( ( ! in_array($selected, $list) && ! isset($list[ $selected ])) && $append )
199 $_ .= '<option value="' . esc_attr($selected) . '">' .esc_html($selected) . '</option>';
201 foreach ( $list as $value => $text ) {
203 $value_attr = $selected_attr = '';
205 if ( $values ) $value_attr = ' value="' . esc_attr($value) . '"';
206 if ( ( $values && (string)$value === (string)$selected)
207 || ( ! $values && (string)$text === (string)$selected ) )
208 $selected_attr = ' selected="selected"';
210 if ( is_array($text) ) {
212 $_ .= '<optgroup label="' . esc_attr($label) . '">';
213 $_ .= self::menuoptions($text, $selected, $values);
216 } else $_ .= "<option$value_attr$selected_attr>$text</option>";
222 add_filter('save_post', 'tag_post_image_luminance');
224 add_filter('next_post_link', function ( $format ) {
225 return str_replace('href=', 'class="page-numbers next-post" href=', $format);
227 add_filter('previous_post_link', function ( $format ) {
228 return str_replace('href=', 'class="page-numbers prev-post" href=', $format);
233 // Queue global scripts
234 add_action( 'wp_enqueue_scripts', function () {
237 get_stylesheet_directory_uri() . '/scripts/global.js',
243 wp_enqueue_script( 'theme-global' );
247 class Responsive_Toggle_Walker_Nav_Menu extends Walker_Nav_Menu {
249 private $toggleid = null;
251 public function start_lvl( &$output, $depth = 0, $args = array() ) {
252 $output .= "\n" . str_repeat("\t", $depth);
253 $classes = array("sub-menu");
255 $classes[] = "sub-menu-layer";
257 $id = ( 0 == $depth ) ? " id=\"sub-menu-for-{$this->toggleid}\"" : '';
258 $class_names = esc_attr(join( ' ', $classes ));
259 $output .= "<ul class=\"$class_names\" role=\"menu\"$id>\n";
262 public function end_lvl( &$output, $depth = 0, $args = array() ) {
263 $indent = str_repeat("\t", $depth);
264 $output .= "$indent</ul>\n";
267 public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
269 $before = $args->link_before;
270 $after = $args->link_after;
272 if ( in_array('menu-item-has-children', $item->classes) && 0 == $depth ) {
273 $this->toggleid = $item->ID;
274 $args->before .= "<input type=\"checkbox\" id=\"toggle-{$item->ID}\" class=\"menu-toggle\" />";
275 $args->link_before = "<label for=\"toggle-{$item->ID}\" class=\"label-toggle\">" . $args->link_before;
276 $args->link_after .= "</label>";
277 $item->url = '#nav-sub-menu';
278 } elseif ( in_array('menu-item-has-children', $item->classes) && 1 == $depth ) {
279 // $item->role = "presentation";
280 } else $toggleid = null;
282 $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
284 $classes = empty( $item->classes ) ? array() : (array) $item->classes;
285 $classes[] = 'menu-item-' . $item->ID;
287 $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
288 $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
290 $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth );
291 $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
293 $output .= $indent . '<li' . $id . $class_names . '>';
296 $atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
297 $atts['target'] = ! empty( $item->target ) ? $item->target : '';
298 $atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
299 $atts['href'] = ! empty( $item->url ) ? $item->url : '';
300 $atts['role'] = ! empty( $item->role ) ? $item->role : '';
302 if ( in_array('menu-item-has-children', $item->classes) && 0 == $depth ) {
303 $atts['aria-haspopup'] = "true";
304 $atts['aria-owns'] = 'sub-menu-for-' . $item->ID;
305 $atts['aria-controls'] = 'sub-menu-for-' . $item->ID;
306 $atts['aria-expanded'] = 'true';
309 $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
312 foreach ( $atts as $attr => $value ) {
313 if ( ! empty( $value ) ) {
314 $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
315 $attributes .= ' ' . $attr . '="' . $value . '"';
319 $item_output = $args->before;
320 $item_output .= '<a'. $attributes .'>';
321 $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
322 $item_output .= '</a>';
323 $item_output .= $args->after;
325 $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
327 $args->link_before = $before;
328 $args->link_after = $after;
333 class Front_Page_Posts {
335 private static $object; // Singleton instance
337 private static $wp_query; // WP_Query instance
339 public static function &object () {
340 if ( ! self::$object instanceof self )
341 self::$object = new self;
343 if ( empty(self::$wp_query) )
344 self::$wp_query = new WP_Query(array('post_type' => 'post'));
346 return self::$object;
349 public static function WP_Query() {
350 return self::$wp_query;