/** * Class containing utility static methods that other SEO tools are relying on. */ class Jetpack_SEO_Utils { /** * Site option name used to store front page meta description. */ const FRONT_PAGE_META_OPTION = 'advanced_seo_front_page_description'; /** * Old version of option name that was previously used under Free plan. */ const GRANDFATHERED_META_OPTION = 'seo_meta_description'; /** * Used to check whether SEO tools are enabled for given site. * * @param int $site_id Optional. Defaults to current blog id if not given. * * @return bool True if SEO tools are enabled, false otherwise. */ public static function is_enabled_jetpack_seo( $site_id = 0 ) { /** * Can be used by SEO plugin authors to disable the conflicting output of SEO Tools. * * @module seo-tools * * @since 5.0.0 * * @param bool True if SEO Tools should be disabled, false otherwise. */ if ( apply_filters( 'jetpack_disable_seo_tools', false ) ) { return false; } if ( function_exists( 'has_blog_sticker' ) ) { // For WPCOM sites if ( empty( $site_id ) ) { $site_id = get_current_blog_id(); } return has_blog_sticker( 'business-plan', $site_id ); } // For all Jetpack sites return true; } /** * Checks if this option was set while it was still available under free plan. * * @return bool True if we should enable grandfathering, false otherwise. */ public static function has_grandfathered_front_page_meta() { return ! self::is_enabled_jetpack_seo() && get_option( self::GRANDFATHERED_META_OPTION ); } /** * Returns front page meta description for current site. * * Since we allowed non-business users to set Front page meta description for some time, * before bundling it with other SEO tools features that require a business plan, * we are supporting grandfathering here. * * @return string Front page meta description string or empty string. */ public static function get_front_page_meta_description() { if ( self::is_enabled_jetpack_seo() ) { $front_page_meta = get_option( self::FRONT_PAGE_META_OPTION ); return $front_page_meta ? $front_page_meta : get_option( self::GRANDFATHERED_META_OPTION, '' ); } // Support grandfathering for non-business users. return get_option( self::GRANDFATHERED_META_OPTION, '' ); } /** * Updates the site option value for front page meta description. * * We are taking care to update the correct option, in case the value is grandfathered for current site. * * @param $value string New value for front page meta description. * * @return string Saved value, or empty string if no update was performed. */ public static function update_front_page_meta_description( $value ) { $front_page_description = sanitize_text_field( $value ); /** * Can be used to limit the lenght of front page meta description. * * @module seo-tools * * @since 4.4.0 * * @param int Maximum length of front page meta description. Defaults to 300. */ $description_max_length = apply_filters( 'jetpack_seo_front_page_description_max_length', 300 ); if ( function_exists( 'mb_substr' ) ) { $front_page_description = mb_substr( $front_page_description, 0, $description_max_length ); } else { $front_page_description = substr( $front_page_description, 0, $description_max_length ); } $can_set_meta = self::is_enabled_jetpack_seo(); $grandfathered_meta_option = get_option( self::GRANDFATHERED_META_OPTION ); $has_old_meta = ! empty( $grandfathered_meta_option ); $option_name = self::has_grandfathered_front_page_meta() ? self::GRANDFATHERED_META_OPTION : self::FRONT_PAGE_META_OPTION; $did_update = update_option( $option_name, $front_page_description ); if ( $did_update && $has_old_meta && $can_set_meta ) { // Delete grandfathered option if user has switched to Business plan and updated meta description. delete_option( 'seo_meta_description' ); } if ( $did_update ) { return $front_page_description; } return ''; } } /* * Each title format is an array of arrays containing two values: * - type * - value * * Possible values for type are: 'token' and 'string'. * Possible values for 'value' are: any string in case that 'type' is set * to 'string', or allowed token values for page type in case that 'type' * is set to 'token'. * * Examples of valid formats: * * [ * 'front_page' => [ * [ 'type' => 'string', 'value' => 'Front page title and site name:'], * [ 'type' => 'token', 'value' => 'site_name'] * ], * 'posts' => [ * [ 'type' => 'token', 'value' => 'site_name' ], * [ 'type' => 'string', 'value' => ' | ' ], * [ 'type' => 'token', 'value' => 'post_title' ] * ], * 'pages' => [], * 'groups' => [], * 'archives' => [] * ] * Custom title for given page type is created by concatenating all of the array 'value' parts. * Tokens are replaced with their corresponding values for current site. * Empty array signals that we are not overriding the default title for particular page type. */ /** * Class containing utility static methods for managing SEO custom title formats. */ class Jetpack_SEO_Titles { /** * Site option name used to store custom title formats. */ const TITLE_FORMATS_OPTION = 'advanced_seo_title_formats'; /** * Retrieves custom title formats from site option. * * @return array Array of custom title formats, or empty array. */ public static function get_custom_title_formats() { if( Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) { return get_option( self::TITLE_FORMATS_OPTION, array() ); } return array(); } /** * Returns tokens that are currently supported for each page type. * * @return array Array of allowed token strings. */ public static function get_allowed_tokens() { return array( 'front_page' => array( 'site_name', 'tagline' ), 'posts' => array( 'site_name', 'tagline', 'post_title' ), 'pages' => array( 'site_name', 'tagline', 'page_title' ), 'groups' => array( 'site_name', 'tagline', 'group_title' ), 'archives' => array( 'site_name', 'tagline', 'date' ), ); } /** * Used to modify the default title with custom SEO title. * * @param string $default_title Default title for current page. * * @return string Custom title with replaced tokens or default title. */ public static function get_custom_title( $default_title = '' ) { // Don't filter title for unsupported themes. if ( self::is_conflicted_theme() ) { return $default_title; } $page_type = self::get_page_type(); // Keep default title if invalid page type is supplied. if ( empty( $page_type ) ) { return $default_title; } $title_formats = self::get_custom_title_formats(); // Keep default title if user has not defined custom title for this page type. if ( empty( $title_formats[ $page_type ] ) ) { return $default_title; } if ( ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) { return $default_title; } $custom_title = ''; $format_array = $title_formats[ $page_type ]; foreach ( $format_array as $item ) { if ( 'token' == $item['type'] ) { $custom_title .= self::get_token_value( $item['value'] ); } else { $custom_title .= $item['value']; } } return esc_html( $custom_title ); } /** * Returns string value for given token. * * @param string $token_name The token name value that should be replaced. * * @return string Token replacement for current site, or empty string for unknown token name. */ public static function get_token_value( $token_name ) { switch ( $token_name ) { case 'site_name': return get_bloginfo( 'name' ); case 'tagline': return get_bloginfo( 'description' ); case 'post_title': case 'page_title': return get_the_title(); case 'group_title': return single_tag_title( '', false ); case 'date': return self::get_date_for_title(); default: return ''; } } /** * Returns page type for current page. We need this helper in order to determine what * user defined title format should be used for custom title. * * @return string|bool Type of current page or false if unsupported. */ public static function get_page_type() { if ( is_front_page() ) { return 'front_page'; } if ( is_category() || is_tag() ) { return 'groups'; } if ( is_archive() && ! is_author() ) { return 'archives'; } if ( is_page() ) { return 'pages'; } if ( is_singular() ) { return 'posts'; } return false; } /** * Returns the value that should be used as a replacement for the date token, * depending on the archive path specified. * * @return string Token replacement for a given date, or empty string if no date is specified. */ public static function get_date_for_title() { // If archive year, month, and day are specified. if ( is_day() ) { return get_the_date(); } // If archive year, and month are specified. if ( is_month() ) { return trim( single_month_title( ' ', false ) ); } // Only archive year is specified. if ( is_year() ) { return get_query_var( 'year' ); } return ''; } /** * Checks if current theme is defining custom title that won't work nicely * with our custom SEO title override. * * @return bool True if current theme sets custom title, false otherwise. */ public static function is_conflicted_theme() { /** * Can be used to specify a list of themes that use their own custom title format. * * If current site is using one of the themes listed as conflicting, * Jetpack SEO custom title formats will be disabled. * * @module seo-tools * * @since 4.4.0 * * @param array List of conflicted theme names. Defaults to empty array. */ $conflicted_themes = apply_filters( 'jetpack_seo_custom_title_conflicted_themes', array() ); return isset( $conflicted_themes[ get_option( 'template' ) ] ); } /** * Checks if a given format conforms to predefined SEO title templates. * * Every format type and token must be whitelisted. * @see get_allowed_tokens() * * @param array $title_formats Template of SEO title to check. * * @return bool True if the formats are valid, false otherwise. */ public static function are_valid_title_formats( $title_formats ) { $allowed_tokens = self::get_allowed_tokens(); if ( ! is_array( $title_formats ) ) { return false; } foreach ( $title_formats as $format_type => $format_array ) { if ( ! in_array( $format_type, array_keys( $allowed_tokens ) ) ) { return false; } if ( '' === $format_array ) { continue; } if ( ! is_array( $format_array ) ) { return false; } foreach ( $format_array as $item ) { if ( empty( $item['type'] ) || empty( $item['value'] ) ) { return false; } if ( 'token' == $item['type'] ) { if ( ! in_array( $item['value'], $allowed_tokens[ $format_type ] ) ) { return false; } } } } return true; } /** * Combines the previous values of title formats, stored as array in site options, * with the new values that are provided. * * @param array $new_formats Array containing new title formats. * * @return array $result Array of updated title formats, or empty array if no update was performed. */ public static function update_title_formats( $new_formats ) { // Empty array signals that custom title shouldn't be used. $empty_formats = array( 'front_page' => array(), 'posts' => array(), 'pages' => array(), 'groups' => array(), 'archives' => array(), ); $previous_formats = self::get_custom_title_formats(); $result = array_merge( $empty_formats, $previous_formats, $new_formats ); if ( update_option( self::TITLE_FORMATS_OPTION, $result ) ) { return $result; } return array(); } } /** * Class containing utility static methods for managing SEO custom descriptions for Posts and Pages. */ class Jetpack_SEO_Posts { /** * Key of the post meta value that will be used to store post custom description. */ const DESCRIPTION_META_KEY = 'advanced_seo_description'; /** * Build meta description for post SEO. * * @param WP_Post $post Source of data for custom description. * * @return string Post description or empty string. */ public static function get_post_description( $post ) { if ( empty( $post ) ) { return ''; } if ( post_password_required() || ! is_singular() ) { return ''; } // Business users can overwrite the description $custom_description = self::get_post_custom_description( $post ); if ( ! empty( $custom_description ) ) { return $custom_description; } if ( ! empty( $post->post_excerpt ) ) { return $post->post_excerpt; } return $post->post_content; } /** * Returns post's custom meta description if it is set, and if * SEO tools are enabled for current blog. * * @param WP_Post $post Source of data for custom description * * @return string Custom description or empty string */ public static function get_post_custom_description( $post ) { if ( empty( $post ) ) { return ''; } $custom_description = get_post_meta( $post->ID, self::DESCRIPTION_META_KEY, true ); if ( empty( $custom_description ) || ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) { return ''; } return $custom_description; } } Dancing Around the Border | The Cunning Rustic

Dancing Around the Border

Dancing Around the Border

The origins and rise of Morris and Traditional Folk Dancing. How Morris Dancing relates to Paganism and Tradition in the British Isles.

While chugging a cider at our local medieval fair, some ten years ago, I found my heart warmed by the sounds of jingle bells and of staves being cracked together in time to a merry tune wrought from a fiddle accompanied by penny whistle and drums.  A local team of Morris dancers was keeping the tradition alive right here in Florida!


For those unfamiliar with ‘The Morris’ it is a form of English folk dancing, that has taken up a revival of sorts in recent years. Traditionally the morris men (and it was a male dance), hop and skip in time with bells on their shins and arms, wearing breeches and brightly coloured sashes over white shirts, sometimes waving handkerchiefs and sometimes knocking together sticks.

Much debate is to be had over the origins of the peculiar style of dancing. The name alone is a mystery, some say it is the dance of the people of the moors, while others say that it is the dance of the Moorish people! Some claim it is a renaissance invention, whilst many, like myself, believe the origins to be much, much older. The Abbots Bromley Horn Dance, while not strictly a morris dance, seems to be of great vintage, still performed annually with reindeer antlers that have been carbon dated to the 11th century, long after the beasts became extinct in the British isles.  These antlers came from  Scandinavia, and the dance seems to be accepted as part of a Pagan tradition.

Those of us who follow a  native European faith are likely familiar with the God Frey.  Among many other more complex ideas, Frey is a God of fertility who fights with stag antlers at the Ragnarok, the final battle between the Gods and the forces of Chaos.  Writing in the early thirteenth century, the Danish monk Saxo Grammaticus, talked of the warrior named Starkad, in the Gesta Danorum, and described priests of Frey:

“…he went into the land of the Swedes, where he lived at leisure for seven years’ space with the sons of Frey. At last he left them and betook himself to Hakon, the tyrant of Denmark, because when stationed at Upsala, at the time of the sacrifices, he was disgusted by the effeminate gestures and the clapping of the mimes on the stage, and by the unmanly clatter of the bells.”

Whilst Saxo Grammaticus may have had his own religious axe to grind, for those who have witnessed the hankie-waving Cotswold Morris, it’s hard to think of a better description than ‘effeminate gestures’ and ‘the unmanly clatter of the bells’.  It  wouldn’t be out of place for hunting rituals to be dedicated to Frey and brought to Mercia by Danish invaders, and the Abbots Bromley horn dance could certainly fall into that category.  Elements of these ritual dances would be kept and misunderstood by the uninitiated for generations, as the meanings are lost in time.  Perhaps Starkadder’s objection to the effeminacy of the priests explains the ‘Maid Marian’ figure in the horn dance, which is always a male dressed in female attire.  Perhaps the hobby horse that is present, is also sacred in some way, just as the sacrificial horse dedicated to Frey in the Icelandic saga ‘Hrafnkel, Frey’s Gothi (priest)’.  Regardless of origin, both morris and the horn dance are part of the folk tradition of the British isles, which encapsulates the spirit of a folk, and to my eyes, that supersedes any claim to religiosity, as the true folk religion belongs to the spirit of the Folk that created and embraced it.

A Border Morris musician

A Border Morris musician

A certain part of me balks at modern interventions as the dances change and evolve, but even as staunch as I can be, I try to see the reason in the natural evolution of our folkways.  Certainly, morris dancing seems to be on the up, but it is also changing form. We have seen the rise of ‘Border Morris’, a more vigorous form of the dance from the Welsh border.  Border Morris has been the source of much controversy, attacked by  traditional dancers for it’s often mixed sets (where women dance alongside men, although this dates back in certain areas, to at least the 18th century, it has never been the norm), modern instrumentation and heavy Pagan leanings.

When one observes the spectacle of Border morris, it’s hard not to be taken in by its polar opposition to the more common morris troupe.  Traditional morris seems scrubbed clean, perhaps by the Victorians, but Border is far less refined.  Where the traditional morris teams are often named for their villages,  the Border dancers give their teams names like ‘Bloodstone’, ‘Witchmen’, and ‘Beltane’.  The typical Border dancer is clad in a black rag coat, a top hat crested with feathers, Dr. Martin’s boots and bedecked with silver skulls, or other gothic imagery.  Their cries aren’t jeers but hollers, and the dance seems like a stomp, rather than a prance. 

The sudden enthusiasm for Border morris is easy to see, for one, the black face paint they wear gives anonymity, important in ancient times, but perhaps all the more now when morris dancing is less enticing to the youth.  From the esoteric perspective, if the Traditional dance is indeed descended from Frey’s priests, it would seem that Border derives from the spirit of Woden. Watching the feathered hats and rag coats bouncing accompanied by whoops and caws, it is impossible, not to feel as if this is some kind of dance for the Raven God of the Slain.

He didn't like the Morris.

He didn’t like the Morris.

An American Morris dancer who I talked to was quick to decry the Border Morris as ‘racist’ because it is often performed by dancers with blackened faces.  This poor woman was ignorant to the idea that the coal black face most likely came from the miners that first performed it, although there are the typical university types who push the absurd idea that it traveled across the ocean from American Minstrel shows and through the medium of vaudeville into these small English country villages!  It should also be pointed out that the only time in which morris dances were stopped was during the Interregnum, the reign of the despicable Oliver Cromwell.  No doubt the newest New Model Army, comprised of Social Justice Warriors and other Neo-Puritans would love to see a stop to all our traditions.

Ironically, there are those within the Border Morris crowd who believe that what they are doing is specifically anti-traditional and that can only be a good thing. This is also very silly and I can only hope that point of view is limited to a few fringe loonies. It’s interesting to see this new evolution rise as there is a far greater interest in English folk tradition now, than at any time in my life. I see a place for both styles, and hope that they continue to thrive with greater enthusiasm, and I am delighted to see my friends continue the morris here in the US.

Regardless of whether you believe that Border morris is Anti-Traditional or merely an evolution of tradition, or you think that morris should be performed only by men at the appropriate seasonal festival, one thing that we should agree on, is that the morris is best performed and observed after a proper English pint.



  1. Karon A. Hartshorn

    June 20, 2016 at 10:46 pm

    Our Border Morris team, Ladies of the Rolling Pin, does both very traditional and our own takes on traditional dances. We have learned from such disparate sources like traditional teams in Cornwall, and other spots in England and from youtube. As shown by our name, we are on the lighter side of Border (sometimes to my consternation as I would really, really like to do Katy Cruel!) But our audience is usually families and our squire feels that some of the darker dances won’t be well received. For my own take, all Morris needs to both evolve to fit the times (or number of dancers) and to hold on to the traditional dances so they will not be lost or forgotten. Accompanied by a pint, of course!

  2. B Taylor-Hicks

    June 22, 2016 at 8:46 pm

    Fascinating! Thank you for the link.

Leave a Reply

Your email address will not be published.

© 2018 The Cunning Rustic

Theme by Anders NorenUp ↑