$title ) { // Check if the link matches the current URI base, if true, add 'current' class. $class = gp_startswith( $current_uri, $link ) ? 'current' : ''; $html .= '' . $title . ''; } return $html; } function gp_nav_menu_items( $location = 'main' ) { $items = array(); if ( 'main' === $location ) { $items[ gp_url( '/projects' ) ] = __( 'Projects', 'glotpress' ); $items[ gp_url( '/languages' ) ] = __( 'Locales', 'glotpress' ); } elseif ( 'side' === $location ) { if ( is_user_logged_in() ) { $user = wp_get_current_user(); $items[ gp_url_profile( $user->user_nicename ) ] = __( 'Profile', 'glotpress' ); $items[ gp_url( '/settings' ) ] = __( 'Settings', 'glotpress' ); $items[ esc_url( wp_logout_url( gp_url_current() ) ) ] = __( 'Log out', 'glotpress' ); } else { $items[ esc_url( wp_login_url( gp_url_current() ) ) ] = __( 'Log in', 'glotpress' ); } } /** * Filter the list of navigation menu items. * * @since 1.0.0 * * @param array $items Menu items. URL as the key, menu label as the value. * @param string $location Location of the menu. */ return apply_filters( 'gp_nav_menu_items', $items, $location ); } function gp_tmpl_filter_args( $args ) { $clean_args = array(); foreach ( $args as $k => $v ) { if ( '_' != $k[0] && 'GLOBALS' != $k && ! gp_startswith( $k, 'HTTP' ) && ! gp_startswith( $k, 'PHP' ) ) { $clean_args[ $k ] = $v; } } return $clean_args; } function gp_tmpl_404( $args = array() ) { gp_tmpl_load( '404', $args + array( 'title' => __( 'Not Found', 'glotpress' ), 'http_status' => 404, ) ); exit(); } function gp_title( $title = null ) { if ( ! is_null( $title ) ) { add_filter( 'gp_title', function() use ( $title ) { return $title; }, 5 ); } else { /** * Filter the title of a page. * * @since 1.0.0 * * @param string $title The title of a page. */ return apply_filters( 'gp_title', '' ); } } function gp_breadcrumb( $breadcrumb = null, $args = array() ) { if ( $breadcrumb ) { $breadcrumb = gp_array_flatten( $breadcrumb ); add_filter( 'gp_breadcrumb_items', function( $breadcrumbs ) use ( $breadcrumb ) { return array_merge( $breadcrumbs, $breadcrumb ); }, 1 ); } else { /** * Filter the list of breadcrumb navigation items. * * @since 1.0.0 * * @param array $breadcrumb_items Breadcrumb items as HTML string. */ $breadcrumbs = apply_filters( 'gp_breadcrumb_items', array() ); if ( $breadcrumbs ) { $defaults = array( /* translators: separates links in the navigation breadcrumb */ 'before' => '
  • ', 'after' => '
  • ', 'breadcrumb-template' => '', ); $args = array_merge( $defaults, $args ); $whole_breadcrumb = ''; foreach ( $breadcrumbs as $breadcrumb ) { $whole_breadcrumb .= $args['before'] . $breadcrumb . $args['after']; } $whole_breadcrumb = str_replace( '{breadcrumb}', $whole_breadcrumb, $args['breadcrumb-template'] ); /** * Filter the breadcrumb HTML output. * * @since 1.0.0 * * @param string $whole_breadcrumb Breadcrumb HTML. */ return apply_filters( 'gp_breadcrumb', $whole_breadcrumb ); } } } function gp_project_names_from_root( $leaf_project ) { $names = array(); $path_from_root = array_reverse( $leaf_project->path_to_root() ); foreach ( $path_from_root as $project ) { $names[] = esc_html( $project->name ); } $project_path = implode( ' | ', $names ); return $project_path; } function gp_project_links_from_root( $leaf_project ) { if ( 0 === $leaf_project->id ) { return array(); } $links = array(); $path_from_root = array_reverse( $leaf_project->path_to_root() ); $links[] = empty( $path_from_root ) ? __( 'Projects', 'glotpress' ) : gp_link_get( gp_url( '/projects' ), __( 'Projects', 'glotpress' ) ); foreach ( $path_from_root as $project ) { $links[] = gp_link_project_get( $project, esc_html( $project->name ) ); } return $links; } function gp_breadcrumb_project( $project ) { return gp_breadcrumb( gp_project_links_from_root( $project ) ); } function gp_js_focus_on( $html_id ) { return ''; } function gp_select( $name_and_id, $options, $selected_key, $attrs = array() ) { $attributes = gp_html_attributes( $attrs ); $attributes = $attributes ? " $attributes" : ''; $res = "\n"; return $res; } function gp_radio_buttons( $name, $radio_buttons, $checked_key ) { $res = ''; foreach ( $radio_buttons as $value => $label ) { $checked = checked( $value, $checked_key, false ); // TODO: something more flexible than
    $res .= "\t "; $res .= "
    \n"; } return $res; } function gp_pagination( $page, $per_page, $objects ) { $surrounding = 2; $first = $prev_dots = $prev_pages = $next_pages = $next_dots = $last = ''; $page = intval( $page ) ? intval( $page ) : 1; $pages = ceil( $objects / $per_page ); if ( $page > $pages ) { return ''; } if ( $page > 1 ) { $prev = gp_link_get( add_query_arg( array( 'page' => $page - 1 ) ), '←', array( 'class' => 'previous' ) ); } else { $prev = ''; } if ( $page < $pages ) { $next = gp_link_get( add_query_arg( array( 'page' => $page + 1 ) ), '→', array( 'class' => 'next' ) ); } else { $next = ''; } $current = '' . $page . ''; if ( $page > 1 ) { $prev_pages = array(); foreach ( range( max( 1, $page - $surrounding ), $page - 1 ) as $prev_page ) { $prev_pages[] = gp_link_get( add_query_arg( array( 'page' => $prev_page ) ), $prev_page ); } $prev_pages = implode( ' ', $prev_pages ); if ( $page - $surrounding > 1 ) { $prev_dots = ''; } } if ( $page < $pages ) { $next_pages = array(); foreach ( range( $page + 1, min( $pages, $page + $surrounding ) ) as $next_page ) { $next_pages[] = gp_link_get( add_query_arg( array( 'page' => $next_page ) ), $next_page ); } $next_pages = implode( ' ', $next_pages ); if ( $page + $surrounding < $pages ) { $next_dots = ''; } } if ( $prev_dots ) { $first = gp_link_get( add_query_arg( array( 'page' => 1 ) ), 1 ); } if ( $next_dots ) { $last = gp_link_get( add_query_arg( array( 'page' => $pages ) ), $pages ); } $html = << $prev $first $prev_dots $prev_pages $current $next_pages $next_dots $last $next HTML; /** * Filter the pagination HTML output. * * @since 1.0.0 * * @param string $html The pagination HTML. * @param int $page Current page number. * @param int $per_page Objects per page. * @param int $objects Total number of objects to page. */ return apply_filters( 'gp_pagination', $html, $page, $per_page, $objects ); } function gp_html_attributes( $attrs ) { $attrs = wp_parse_args( $attrs ); $strings = array(); foreach ( $attrs as $key => $value ) { $strings[] = $key . '="' . esc_attr( $value ) . '"'; } return implode( ' ', $strings ); } function gp_attrs_add_class( $attrs, $class_name ) { $attrs['class'] = isset( $attrs['class'] ) ? $attrs['class'] . ' ' . $class_name : $class_name; return $attrs; } /** * Returns HTML markup for a select element for all locales of a project. * * @since 1.0.0 * * @param int $project_id ID of a project. * @param string $name_and_id Name and ID of the select element. * @param string $selected_slug Slug of the current selected locale. * @param array $attrs Extra attributes. * * @return string HTML markup for a select element. */ function gp_locales_by_project_dropdown( $project_id, $name_and_id, $selected_slug = null, $attrs = array() ) { $locales = GP_Locales::locales(); if ( null != $project_id ) { $sets = GP::$translation_set->by_project_id( $project_id ); $temp_locales = array(); foreach ( $sets as $set ) { $temp_locales[ $set->locale ] = $locales[ $set->locale ]; } if ( count( $temp_locales ) > 0 ) { $locales = $temp_locales; } } ksort( $locales ); $options = array( '' => __( '— Locale —', 'glotpress' ) ); foreach ( $locales as $key => $locale ) { $options[ $key ] = sprintf( '%s — %s', $locale->slug, $locale->english_name ); } return gp_select( $name_and_id, $options, $selected_slug, $attrs ); } /** * Returns HTML markup for a select element for all locales. * * @since 1.0.0 * * @param string $name_and_id Name and ID of the select element. * @param string $selected_slug Slug of the current selected locale. * @param array $attrs Extra attributes. * * @return string HTML markup for a select element. */ function gp_locales_dropdown( $name_and_id, $selected_slug = null, $attrs = array() ) { return gp_locales_by_project_dropdown( null, $name_and_id, $selected_slug, $attrs ); } /** * Returns HTML markup for a select element for projects. * * @since 1.0.0 * * @param string $name_and_id Name and ID of the select element. * @param string $selected_project_id The project id to mark as the currently selected. * @param array $attrs Extra attributes. * @param array $exclude An array of project IDs to exclude from the list. * @param array $exclude_no_parent Exclude the "No Parent" option from the list of projects. * * @return string HTML markup for a select element. */ function gp_projects_dropdown( $name_and_id, $selected_project_id = null, $attrs = array(), $exclude = array(), $exclude_no_parent = false ) { if ( ! is_array( $exclude ) ) { $exclude = array( $exclude ); } $projects = GP::$project->all(); // TODO: mark which nodes are editable by the current user $tree = array(); $top = array(); foreach ( $projects as $p ) { $tree[ $p->id ]['self'] = $p; if ( $p->parent_project_id ) { $tree[ $p->parent_project_id ]['children'][] = $p->id; } else { $top[] = $p->id; } } if ( ! $exclude_no_parent ) { $options = array( '' => __( '— No parent —', 'glotpress' ) ); } else { $options = array(); } foreach ( $top as $top_id ) { $stack = array( $top_id ); while ( ! empty( $stack ) ) { $id = array_pop( $stack ); if ( in_array( $id, $exclude, true ) ) { continue; } $tree[ $id ]['level'] = gp_array_get( $tree[ $id ], 'level', 0 ); $options[ $id ] = str_repeat( '-', $tree[ $id ]['level'] ) . $tree[ $id ]['self']->name; foreach ( gp_array_get( $tree[ $id ], 'children', array() ) as $child_id ) { $stack[] = $child_id; $tree[ $child_id ]['level'] = $tree[ $id ]['level'] + 1; } } } return gp_select( $name_and_id, $options, $selected_project_id, $attrs ); } function gp_array_of_things_to_json( $array ) { return wp_json_encode( array_map( function( $thing ) { return $thing->fields(); }, $array ) ); } function gp_array_of_array_of_things_to_json( $array ) { $map_to_fields = function( $array ) { return array_map( function( $thing ) { return $thing->fields(); }, $array ); }; return wp_json_encode( array_map( $map_to_fields, $array ) ); } function things_to_fields( $data ) { if ( is_array( $data ) ) { foreach ( $data as $item_id => $item ) { $data[ $item_id ] = things_to_fields( $item ); } } elseif ( $data instanceof GP_Thing ) { $data = $data->fields(); } return $data; } function gp_preferred_sans_serif_style_tag( $locale ) { if ( ! $locale->preferred_sans_serif_font_family ) { return; } ?> $project->id ) ), __( 'New Sub-Project', 'glotpress' ) ), gp_link_get( gp_url( '/sets/-new', array( 'project_id' => $project->id ) ), __( 'New Translation Set', 'glotpress' ) ), gp_link_get( gp_url_project( $project, array( '-mass-create-sets' ) ), __( 'Mass-create Translation Sets', 'glotpress' ) ), gp_link_get( gp_url_project( $project, '-branch' ), __( 'Branch project', 'glotpress' ) ), gp_link_get( gp_url_project( $project, '-delete' ), __( 'Delete project', 'glotpress' ) ), ); /** * Project action links. * * @since 1.0.0 * * @param array $actions Links as HTML strings. * @param GP_Project $project The project. */ $actions = apply_filters( 'gp_project_actions', $actions, $project ); echo ''; } function gp_project_options_form( $project ) { return ' ' . __( 'Personal project options', 'glotpress' ) . ' ↓
    ' . sprintf( /* translators: 1: %file%, 2: %line%, 3: https://trac.example.org/browser/%file%#L%line% */ __( 'URL to a source file in the project. You can use %1$s and %2$s. Ex. %3$s', 'glotpress' ), '%file%', '%line%', 'https://trac.example.org/browser/%file%#L%line%' ) . '
    ' . gp_route_nonce_field( 'set-personal-options_' . $project->id, false ) . '
    '; } function gp_entry_actions( $seperator = ' • ' ) { $actions = array( '
    ' . ' ' . '
    ', ); /** * Filters entry action links. * * @since 1.0.0 * * @param array $actions Links as HTML strings. */ $actions = apply_filters( 'gp_entry_actions', $actions ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo implode( $seperator, $actions ); } /** * Generates a list of classes to be added to the translation row, based on translation entry properties. * * @since 2.2.0 * * @param Translation_Entry $translation The translation entry object for the row. * * @return array */ function gp_get_translation_row_classes( $translation ) { $classes = array(); $classes[] = $translation->translation_status ? 'status-' . $translation->translation_status : 'untranslated'; $classes[] = 'priority-' . gp_array_get( GP::$original->get_static( 'priorities' ), $translation->priority ); $classes[] = $translation->warnings ? 'has-warnings' : 'no-warnings'; $classes[] = count( array_filter( $translation->translations, 'gp_is_not_null' ) ) > 0 ? 'has-translations' : 'no-translations'; /** * Filters the list of CSS classes for a translation row * * @since 2.2.0 * * @param array $classes An array of translation row classes. * @param Translation_Entry $translation The translation entry object. */ $classes = apply_filters( 'gp_translation_row_classes', $classes, $translation ); return $classes; } /** * Outputs space separated list of classes for the translation row, based on translation entry properties. * * @since 2.2.0 * * @param Translation_Entry $translation The translation entry object for the row. * * @return void */ function gp_translation_row_classes( $translation ) { $classes = gp_get_translation_row_classes( $translation ); echo esc_attr( implode( ' ', $classes ) ); }