Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: alerts

  • Front Facing Alerts on Posts

    Front Facing Alerts on Posts

    Once I wrote the back-end code to show admin alerts on posts, I decided to add in some front end magic.

    Since the original code was written to be called by hooking into the admin_notices action, the obvious solution was to hook into something on the front end. But where?

    Genesis

    I’m a fan of the Genesis themes. There’s a handy hook for placement called genesis_before_content_sidebar_wrap() and the call (based on last week’s code) is this:

    add_action( 'genesis_before_content_sidebar_wrap', 'MYSITE_admin_notices' );
    

    And immediately that outputs this below the menu:

    Output message above title

    Obviously there’s no CSS going on there, but that’s okay.

    Not Genesis

    That’s lovely but what if I don’t use Genesis?

    While a filter like add_filter( 'the_title', 'MYSITE_admin_notices', 10, 2 ); would work, it also calls it for every output of the title on a page. If you happen to be using a sidebar that links to your 5 most recent posts, it can get pretty messy.

    And the problem here is that WordPress doesn’t have standard template hooks like that. You can use get_header() but that puts it at the top of every page. There just isn’t a way to say “I want this above the title” and have it work universally on all themes. Bummer.

    That said, you can totally make the get_header() call work with a little CSS magic and a little extra if-checks.

    The CSS Code

    Remember our goal in life is to load as little as possible on pages, so the best thing is to check if this is even the right post type:

    add_action( 'wp_enqueue_scripts', 'MYSITE_wp_enqueue_scripts' );
    public function MYSITE_wp_enqueue_scripts( ) {
    	wp_register_style( 'cpt-shows-styles', plugins_url('shows.css', __FILE__ ) );
    
    	if( is_single() && get_post_type() == 'post_type_shows' ){
    		wp_enqueue_style( 'cpt-shows-styles' );
    	}
    }
    

    The actual CSS is up to you, but mine looks like this and is cribbed from WordPress core:

    .wrap .notice {
    	background: #fff;
    	border-left: 4px solid #fff;
    	-webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);
    	box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);
    	margin: 5px;
    	padding: 1px 12px;
    }
    
    .wrap .notice p {
    	margin: .5em 0;
    	padding: 2px;
    }
    
    .wrap .notice p:before {
    	margin-right: 6px;
    	vertical-align: bottom;
    }
    
    .wrap .notice-error {
    	border-left-color: #dc3232;
    }
    
    .wrap .notice-info {
    	border-left-color: #00a0d2;
    }
    
    .wrap .notice-warning {
    	border-left-color: #ffb900;
    }
    
    .wrap .notice-updated,
    .wrap .notice-success {
    	border-left-color: #46b450;
    }
    

    This basically reproduces the same CSS as you’d see on the Admin Dashboard.

    The PHP Code

    While we covered the brunt of the PHP code before, we need to make a few alterations to make sure that the output only shows on the right pages and to the right people.

    The first changes will be in this section:

    if ( $message ) {
    	printf( '<div class="notice %1$s"><p><span class="dashicons dashicons-%2$s"></span> %3$s</p></div>', esc_attr( $type ), esc_attr( $dashicon ), esc_html( $message ) );
    }
    

    While it’s possible to use is_admin() to check if a visitor is on the dashboard or not, this is going to show on both front and backend. That means a better choice is is_user_logged_in() so our code will look like if ( $message && is_user_logged_in() ) and now it only shows if you’re logged in.

    But. The code shows on every page. That meant the code showed up on the static front page because it had no code and just widgets. In order to make it only show up on the right pages, I put in a check for what was called when.

    Since I have multiple CPTs, I keep the code that is post type specific in a file that matches the name, and I have an extra file called all-cpts.php that calls common code that they all use. This helps me keep my code dry (Don’t Repeat Yourself). That makes it easy for me to use a switch based the post type and output the right code on the right pages:

    function MYSITE_CPT_admin_notices() {
    
    	if ( !get_post() ) return;
    
    	$message    = '';
    	$type       = 'updated';
    	$post       = get_post();
    
    	$content    = get_post_field( 'post_content', $post->ID );
    	$word_count = str_word_count( strip_tags( $content ) );
    
    	switch ( $post->post_type ) {
    		case 'post_type_shows':
    			$worthit = get_post_meta( $post->ID, 'shows_worthit_details', true );
    
    			if ( $worthit < '1' ) {
    				$type     = 'notice-info';
    				$message  = 'Is this show worth watching? We don\'t know. Halp!';
    				$dashicon = 'heart';
    
    				if ( $word_count < '100' ) {
    					$type     = 'notice-error';
    					$message  = 'We clearly know nothing about this show. Help!';
    					$dashicon = 'warning';
    				} elseif ( $word_count < '200' ) {
    					$type     = 'notice-warning';
    					$message  = 'This post is a stub. Please edit it and make it more awesome.';
    					$dashicon = 'info';
    				}
    			}
    			break;
    	}
    
    	if ( $message && is_user_logged_in() && ( is_single() || is_admin() ) ) {
    		printf( '<div class="wrap"><div class="notice %1$s"><p><span class="dashicons dashicons-%2$s"></span> %3$s</p></div></div>', esc_attr( $type ), esc_attr( $dashicon ), esc_html( $message ) );
    	}
    
    }
    

    Now the message shows up for logged in users only, and only on the intended pages.

  • Admin Alerts on Posts

    Admin Alerts on Posts

    As the new WordPress.org plugin directory rolls out, I know a lot of people are fussing over the front end. I’m not for a very practical reason. I’m working on making the backend functional and educational.

    Information Is Key

    A lot of the information about what a various post status means is something I understand from experience. My goal is to expand the team as broadly as possible and in order to do that, I must document. But documentation is more than just writing up a doc and telling people to follow it.

    People need contextual reminders of what the status of a ‘thing’ is to understand what they must do next. With that in mind, I leveraged some code by Obenland to make reviewer alerts better. Originally, you see, our plan was to let plugin developers edit things from the admin panel. Everything’s moving to the front end except for the reviewers you see.

    On Beyond Plugins

    That’s all well and good, but what if I want to do it on my own sites? What if I wanted to have a site message for the editors on my site, so they’d know what posts are ‘done’ and which need some love? What if I wanted to encourage my fellow editors to edit a post I’d worked on?

    I made my plan, based off the old stub template from MediaWiki, because that was always a good way to know if a post did or didn’t need some love.

    1. I needed a way to ‘flag’ a post as a stub automatically
    2. I needed it to display on the page being edited
    3. I would like it to display on the front end but only to logged in users (for now)

    Stub Qualifications

    In order to flag a post automatically, I needed to come up with criteria or qualifications that would mark a post as a stub. Obviously content was part of it, but measuring the quality of the content was going to be difficult.

    My initial criteria for a stub was the following:

    • Under 100 words in post content
    • Empty meta value for “Worth it details”

    Obviously that second item is unique to my situation, but having it meant I could measure engagement by how much someone knew about a show to enter the data. That criteria seemed too strict though. So I tweaked them to be an OR and not an AND. No matter what, if there was under 100 words it was getting flagged. And no matter what, if there was no meta for worthiness, it would be flagged.

    • Info: No meta value for Worth It
    • Warning: No meta value for Worth It and post content under 200 words
    • Alert: No meta value for Worth It and post content under 100 words

    WP Admin Code

    The original code that all this is based on is from WordPress.org (not the WordPress code but the stuff that runs the domain).

    add_action( 'edit_form_after_title', 'MYSITE_admin_notices' );
    function MYSITE_admin_notices() {
    	$message    = '';
    	$type       = 'updated';
    	$post       = get_post();
    
    	switch ( $post->post_type ) {
    		case 'post_type_shows':
    
    			$content    = get_post_field( 'post_content', $post->ID );
    			$word_count = str_word_count( strip_tags( $content ) );
    			$worthit    = get_post_meta( $post->ID, 'worthit_details', true );
    
    			if ( $worthit < '1' ) {
    				$type     = 'notice-info';
    				$message  = 'Is this show worth watching? We don\'t know. Halp!';
    				$dashicon = 'heart';
    
    				if ( $word_count < '100' ) {
    					$type     = 'notice-error';
    					$message  = 'We clearly know nothing about this show. Help!';
    					$dashicon = 'warning';
    				} elseif ( $word_count < '200' ) {
    					$type     = 'notice-warning';
    					$message  = 'This post is a stub. Please edit it and make it more awesome.';
    					$dashicon = 'info';
    				}
    			}
    			break;
    	}
    
    	if ( $message ) {
    		printf( '<div class="notice %1$s"><p><span class="dashicons dashicons-%2$s"></span> %3$s</p></div>', esc_attr( $type ), esc_attr( $dashicon ), esc_html( $message ) );
    	}
    
    }
    

    The reason it uses edit_form_after_title and prints the error instead of add_settings_error is that I don’t actually want these alerts to be dismissible and I only want it to show on post editor pages.

    The Output

    This post needs some attention

    There’s some improvements to be made, but this is a start.