man - Bloc 3

Derniers cours : man

Les cours sont classés par ordre où ils ont été donnés, du plus récent au plus ancien.

Create ios app with WebViewGold & Firebase push notifications

First i purchased the WebViewGold app template

The I followed the official documentation

 

To setup Firebase I followed the awesome tut:

Firebase

  1. Create new project
  2. Step 3: Register Your App

    Click Register app to complete the registration process.

    Step 4: Download GoogleService-Info.plist

    Download this configuration file and replace the placeholder in your WebViewGold project with the downloaded GoogleService-Info.plist file.

    Step 5: Activate Firebase in WebViewGold

    In the Config.swift file, set the kFirebasePushEnabled variable to true to enable Firebase functionalities.

  3. Step 6: Set Up APN and Sign Your App

    Generate an APN key for Firebase, upload it, and then sign your app using the Firebase provisioning profile. For a detailed guide, visit Firebase documentation on iOS certificates.

  4. Declare Your App’s Use of Encryption –> ITSAppUsesNonExemptEncryption  –> NO

 

How do you add custom color swatches to all WYSIWYG editors?

How do you add custom color swatches to all WYSIWYG editors?

				
					function my_mce4_options($init) {

    $custom_colours = '
        "8D9C35", "vert",
        "812437", "bordeau",
        "EF9CAC", "Rose",
		"E5262A", "rouge",
		"382848", "noir-mauve",
		"FC6050", "orange"
		

    ';

    // build colour grid default+custom colors
    $init['textcolor_map'] = '['.$custom_colours.']';

    // change the number of rows in the grid if the number of colors changes
    // 8 swatches per row
    $init['textcolor_rows'] = 1;

    return $init;
}
add_filter('tiny_mce_before_init', 'my_mce4_options');
				
			

Customiser admin WordPress

<?php






/**
 * Enqueue a script in the WordPress admin on edit.php.
 *
 * @param int $hook Hook suffix for the current admin page.
 */
function wpdocs_selectively_enqueue_admin_script( $hook ) {
    if ( 'post.php' != $hook ) {
        return;
    }
    wp_enqueue_script( 'my_custom_script', get_stylesheet_directory_uri() . '/js/scripts-admin.js', array(), '1.0' );
  }
  add_action( 'admin_enqueue_scripts', 'wpdocs_selectively_enqueue_admin_script', PHP_INT_MAX );




  // pour pouvoir styliser admin (et masquer éléments)
  // custom admin style sheet
  function my_admin_head() {
    echo '<link href="'.get_stylesheet_directory_uri().'/css/wp-admin.css" rel="stylesheet" type="text/css">';
  }
  add_action('admin_head', 'my_admin_head');










/************************************************************************** */


// add pages to admin menu
//https://stackoverflow.com/questions/39978561/how-to-add-custom-link-on-wordpress-admin-sidebar
add_action( 'admin_menu', 'linked_url' );
function linked_url() {
// add_menu_page( 'linked_url', 'FAQ', 'read', '/post.php?post=29&action=edit', '', 'dashicons-text', 50 );
// add_menu_page( 'linked_url', 'Liens utiles', 'read', '/post.php?post=49&action=edit', '', 'dashicons-admin-links', 55 );
// on va ajouter le lien vers la page d'accueil uniquement pour éditeur plus bas
}




// si lien externe dans admin menu
// add_action( 'admin_menu' , 'linkedurl_function' );
// function linkedurl_function() {
// global $menu;
// $menu[1][2] = "http://www.example.com";
// }


/************************************************************************** */


add_action( 'admin_menu', 'add_admin_menu_separator' );
function add_admin_menu_separator()
{
    add_menu_page( '', '', 'read', 'wp-menu-separator', '', '', '21' );
    add_menu_page( '', '', 'read', 'wp-menu-separator', '', '', '56' );
    // add_submenu_page( 'edit.php?post_type=page', 'wp-menu-separator', '', 'read', '11', '' );
}






// add_action('admin_init','dump_admin_menu');
// function dump_admin_menu() {
//   if (is_admin()) {
//     header('Content-Type:text/plain');
//     var_dump($GLOBALS['menu']);
//     exit;
//   }
// }




/* COMMENTS // https://www.powderkegwebdesign.com/quickly-easily-remove-comments-backend-wordpress/
* Remove comments in its entirety
*/


// Removes from admin menu
add_action( 'admin_menu', 'pk_remove_admin_menus' );
function pk_remove_admin_menus() {
    remove_menu_page( 'edit-comments.php' );
}


// Removes from post and pages
add_action('init', 'pk_remove_comment_support', 100);
  function pk_remove_comment_support() {
   remove_post_type_support( 'post', 'comments' );
   remove_post_type_support( 'page', 'comments' );
}


// Removes from admin bar
add_action( 'wp_before_admin_bar_render', 'pk_remove_comments_admin_bar' );
function pk_remove_comments_admin_bar() {
    global $wp_admin_bar;
    $wp_admin_bar->remove_menu('comments');
  }








/************************************************************************** */


// remove elements from editor menu


function remove_menus(){
  // get current login user's role
  $roles = wp_get_current_user()->roles;


  // test role
  if( !in_array('editor',$roles)){
  return;
  }


  //remove menu from site backend.
//   remove_menu_page( 'index.php' ); //Dashboard
  remove_menu_page( 'edit.php' ); //Posts
  remove_menu_page( 'upload.php' ); //Media
  remove_menu_page( 'edit-comments.php' ); //Comments
  remove_menu_page( 'themes.php' ); //Appearance
  remove_menu_page( 'plugins.php' ); //Plugins


  // remove_menu_page( 'profile.php' ); //profile
  remove_menu_page( 'users.php' ); //Users
  remove_menu_page( 'tools.php' ); //Tools
  remove_menu_page( 'options-general.php' ); //Settings
  remove_menu_page( 'edit.php?post_type=page' ); //Pages
  // remove_menu_page('edit.php?post_type=testimonial'); // Custom post type 1
  // remove_menu_page('edit.php?post_type=homeslider'); // Custom post type 2


  // remove_menu_page( 'WPML' );
  // remove_menu_page( 'Traductions' );
  // remove_menu_page( 'wpml_manage_languages' );
  // remove_menu_page( 'sitepress-multilingual-cms/menu/languages.php' );
  // remove_menu_page( 'admin.php?page=wpml-translation-management/menu/translations-queue.php' );
  // remove_menu_page( 'admin.php' );
  // remove_menu_page( '#toplevel_page_wpml-translation-management-menu-translations-queue' );
  remove_menu_page( 'edit.php?post_type=elementor_library' );




  // ajout lien vers page d'accueil
  add_menu_page( 'linked_url', 'Page d\'accueil', 'read', '/post.php?post=147&action=elementor', '', 'dashicons-admin-home', 10 );
  add_menu_page( 'linked_url', 'Menu', 'read', '/post.php?post=22&action=edit', '', 'dashicons-food', 11 );




  }
  add_action( 'admin_menu', 'remove_menus' , 100 );

Launch Youtube video when video enters viewport

man

How to launch an emnedded Youtube video when it enters the viewport: This can be achieved by leveraging the Intersection Observer API, which allows you to configure a callback function that executes when an observed element enters or exits the viewport.

Important Notes:

    • The YouTube iframe API requires that you append ?enablejsapi=1 to the URL to enable control of the iframe via postMessage.
    • The postMessage method is used to send commands to the YouTube video player, such as playVideo and pauseVideo.

For a single video

				
					<!-- for 1 video -->

<iframe id="youtubeVideo" width="560" height="315" 
        src="https://www.youtube.com/embed/EDkABFzGTGg?enablejsapi=1&mute=1" 
        title="YouTube video player" frameborder="0" 
        allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
        referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<script>
document.addEventListener("DOMContentLoaded", function() {
    var video = document.getElementById('youtubeVideo');
    var options = {
        root: null, // observing relative to viewport
        rootMargin: '0px',
        threshold: 0.5 // trigger when at least 50% of the video is visible
    };

    function handleIntersect(entries, observer) {
        entries.forEach(function(entry) {
            if (entry.isIntersecting) {
                // Video enters the viewport - play the video
                video.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', 'https://www.youtube.com');
            } else {
                // Video exits the viewport - pause the video
                video.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', 'https://www.youtube.com');
            }
        });
    }

    var observer = new IntersectionObserver(handleIntersect, options);
    observer.observe(video);
});
</script>

				
			

For multiple videos

				
					<!-- for several videos  -->

<iframe id="youtubeVideo1" width="560" height="315" 
        src="https://www.youtube.com/embed/EDkABFzGTGg?enablejsapi=1&mute=1" 
        title="YouTube video player" frameborder="0" 
        allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
        referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
        
<hr style="margin-bottom:50vh">

<iframe id="youtubeVideo2" width="560" height="315" 
        src="https://www.youtube.com/embed/_AOA6M9Ta2I?enablejsapi=1&mute=1" 
        title="YouTube video player" frameborder="0" 
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
        referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<script>
document.addEventListener("DOMContentLoaded", function() {
    var videos = document.querySelectorAll('iframe[id^="youtubeVideo"]'); // Selects iframes with IDs starting with 'youtubeVideo'
    var options = {
        root: null, // observing relative to viewport
        rootMargin: '0px',
        threshold: 0.5 // trigger when at least 50% of the video is visible
    };

    function handleIntersect(entries, observer) {
        entries.forEach(function(entry) {
            if (entry.isIntersecting) {
                // Video enters the viewport - play the video
                entry.target.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', 'https://www.youtube.com');
            } else {
                // Video exits the viewport - pause the video
                entry.target.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', 'https://www.youtube.com');
            }
        });
    }

    var observer = new IntersectionObserver(handleIntersect, options);
    videos.forEach(function(video) {
        observer.observe(video); // Observe each video
    });
});
</script>

				
			

Comment inclure les données des Champs Personnalisés Avancés (Advanced Custom Fields) dans la recherche WordPress

man

WordPress ne recherche pas dans les champs personnalisés !

Bien qu’ACF fasse un excellent travail en utilisant les champs personnalisés de WordPress (post meta) pour le stockage de données structurées, WordPress ne recherche aucun de ces contenus !

De nombreux sites construits par WordPress qui utilisent ACF placent la grande majorité du contenu dans des champs personnalisés (et non dans l’éditeur principal) et ce, pour de bonnes raisons, cela offre une interface beaucoup plus agréable à utiliser et réduit les erreurs.

Malheureusement, un effet secondaire de cela signifie que presque aucun contenu de votre site n’est pris en compte lors de l’exécution des recherches. C’est un énorme problème !

Pour résoudre cela, nous devons modifier la requête de recherche de WordPress pour inclure les champs personnalisés.

Tout d’abord, créer le formulaire de recherche

				
					<?php
//https://curious-human-b.medium.com/how-to-include-advanced-custom-fields-data-into-wordpress-search-77247f0aa23e
/**  
* Join posts and postmeta tables  
*  
* http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join  */ 
function customfields_search_join( $join ) {     
   global $wpdb;      
   if ( is_search() ) {             
      $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';     
   }      
  return $join; 
} 
add_filter('posts_join', 'customfields_search_join' );

function customfields_search_where( $where) {
   global $pagenow, $wpdb;
   
   if( is_search() ) {
      $where = preg_replace(
"/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/","(".$wpdb->posts.".post_title LIKE $1) OR 
(".$wpdb->postmeta.".meta_value LIKE $1)", $where );
     
    }
    
    return $where;
}
add_filter('posts_where', 'customfields_search_where' );

function customfields_search_distinct( $where ) {     
      global $wpdb;
      if ( is_search() ) {
         return "DISTINCT";
     }
  return $where;
} 
add_filter( 'posts_distinct', 'customfields_search_distinct' );

?>

				
			
				
					// rechercher aussi parmi les taxonomies

function customfields_taxonomies_search_join( $join ) {
    global $wpdb;
    if ( is_search() ) {
        // Join to the term_relationships table to access term_taxonomy_id
        $join .= " LEFT JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id) ";
        
        // Join to the term_taxonomy table to ensure we can filter by taxonomy
        $join .= " LEFT JOIN {$wpdb->term_taxonomy} ON ({$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id) ";
        
        // Join to the terms table to access the name of the term
        $join .= " LEFT JOIN {$wpdb->terms} ON ({$wpdb->term_taxonomy}.term_id = {$wpdb->terms}.term_id) ";
    }
    return $join;
}
add_filter('posts_join', 'customfields_taxonomies_search_join');

function customfields_taxonomies_search_where( $where ) {
    global $wpdb;
    
    if ( is_search() ) {
        $where .= " OR ({$wpdb->terms}.name LIKE '%".get_search_query()."%' AND {$wpdb->term_taxonomy}.taxonomy IN ('your_custom_taxonomy_here', 'another_taxonomy'))";
    }
    
    return $where;
}
add_filter('posts_where', 'customfields_taxonomies_search_where');

// You might still want to use your customfields_search_distinct function to avoid duplicate results:
// add_filter('posts_distinct', 'customfields_search_distinct');

				
			

man

Une amie graphiste peinait à créer une grille de boucle dont les articles devaient être illustrés par un hexagone. Avec beaucoup de café un peu d'aide d'une IA j'ai réussi à faire ceci.