get_the_ID(), 'sort_order' => 'ASC', 'sort_column' => 'menu_order', ) ); foreach ( $children as &$child ) { $child->url = get_page_link( $child->ID ); } return $children; } // Modify which pages should render the sidebar. add_filter( 'hasSidebar', function ( $has_sidebar ) { // Add post types that should never have a sidebar. if ( is_page() && ! get_field( 'has_sidebar' ) ) { return false; } return $has_sidebar; } ); /** Helper to check whether or not the sidebar should be rendered * (to add/remove a sidebar from a page, edit the filter instead * of modifying this function). */ function hasSidebar() { return apply_filters( 'hasSidebar', true ); } // Add extra body classes here. add_filter( 'body_class', function ( $classes ) { if ( hasSidebar() ) { $classes = array_merge( $classes, array( 'has-sidebar' ) ); } return $classes; } ); /** * Checks if the page should render a page header. * * Returns true only when the page heading ACF field is explicitly set to * 'default'. When 'none' is selected, no page header should render (the * page instead relies on its own hero block / template hero). * * @return bool true if page header should be rendered, false otherwise */ function hasPageHeader() { global $post; if ( get_field( 'hero_style' ) === 'default' ) { return true; } return false; } /** Create the Owner role. * * This function creates a new role named "Owner" with all the capabilities of the * Administrator role, except for the following: * * - activate_plugins * - delete_plugins * - edit_plugins * - install_plugins * - update_plugins * - switch_themes * - edit_themes * - delete_themes * - install_themes * - update_themes * - update_core * - manage_options * * This role is meant to be used by a person who should have almost all the same * capabilities as an Administrator, but should not have the ability to update * the WordPress core software, manage plugins or themes, or edit other site * options. * * @return void */ function createOwnerRole() { // First, remove the role if it exists. remove_role( 'owner' ); // Get the administrator role. $admin_role = get_role( 'administrator' ); $admin_capabilities = $admin_role->capabilities; // Remove specific capabilities. $capabilities_to_remove = array( 'activate_plugins', 'delete_plugins', 'edit_plugins', 'install_plugins', 'update_plugins', 'switch_themes', 'edit_themes', 'delete_themes', 'install_themes', 'update_themes', 'update_core', 'manage_options', ); foreach ( $capabilities_to_remove as $capability ) { unset( $admin_capabilities[ $capability ] ); } // Add the Owner role with the modified capabilities. add_role( 'owner', 'Owner', $admin_capabilities ); } add_action( 'init', __NAMESPACE__ . '\\createOwnerRole' ); /** Retrieves the appropriate title for the current page context. * * The function determines the type of page being viewed and returns * the corresponding title. It handles different page types, including * the home page, single posts, archives, search results, and 404 pages. * If none of these conditions apply, it defaults to fetching the page's title. * * @return string The title relevant to the current page context. */ function getTheTitle() { $title = ''; if ( is_home() || is_single() ) { $title = get_the_title( get_option( 'page_for_posts', true ) ); } elseif ( is_archive() ) { // get_the_archive_title() is filtered below to drop the // "Project Type:" / "Category:" prefix — see stripArchiveTitlePrefix(). $title = get_the_archive_title(); } elseif ( is_search() ) { $title = sprintf( /* translators: %s is replaced with the search query */ __( 'Search Results for "%s"', 'sf-evo' ), get_search_query() ); } elseif ( is_404() ) { $title = 'Page Not Found (error 404)'; } else { $title = get_the_title(); } return $title; } /** Strip the "Project Type:" / "Category:" / "Tag:" prefix from archive titles. * * WordPress's get_the_archive_title() returns plain text with the taxonomy * or post-type label concatenated before a colon (e.g. "Project Type: Plugins", * "Category: WordPress", "Tag: php"). The site's hero partial uses the raw * archive title as its

, and templates render their own context-appropriate * headers, so the prefix is redundant and visually noisy. * * @param string $title The full archive title, including prefix. * @return string The title with the prefix removed. */ function stripArchiveTitlePrefix( $title ) { // Drop the "