Basically a place that Chris can post solutions to problems so he can easily find them later https://cjhaas.com Just another WordPress site Wed, 18 Dec 2019 19:44:10 +0000 en-US hourly 1 https://wordpress.org/?v=5.3.2 How to create a command that holds other commands in wp-cli (WordPress CLI) https://cjhaas.com/2019/12/18/how-to-create-a-command-that-holds-other-commands-in-wp-cli-wordpress-cli/ https://cjhaas.com/2019/12/18/how-to-create-a-command-that-holds-other-commands-in-wp-cli-wordpress-cli/#respond Wed, 18 Dec 2019 19:44:08 +0000 https://cjhaas.com/?p=958 Almost every major site I work on has at least one custom wp-cli command that I’ve built to manage or automate things. But I always run into the same problem, I don’t want my command to be a root command, I want it to live in a namespace of my own. But, I also don’t […]

The post How to create a command that holds other commands in wp-cli (WordPress CLI) appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
Almost every major site I work on has at least one custom wp-cli command that I’ve built to manage or automate things. But I always run into the same problem, I don’t want my command to be a root command, I want it to live in a namespace of my own. But, I also don’t want to create a blank command that doesn’t do anything just for the sake of this namespace.

For instance, if I register a command using this:

WP_CLI::add_command('custom-command do-thing', DoThingCommand::class);

WordPress will show the below if I just type wp:

  cache                 Adds, removes, fetches, and flushes the WP Object Cache object.
  cap                   Adds, removes, and lists capabilities of a user role.
  cli                   Review current WP-CLI info, check for updates, or see defined aliases.
  comment               Creates, updates, deletes, and moderates comments.
  config                Generates and reads the wp-config.php file.
  core                  Downloads, installs, updates, and manages a WordPress installation.
  cron                  Tests, runs, and deletes WP-Cron events; manages WP-Cron schedules.
  custom-command        
  db                    Performs basic database operations using credentials stored in wp-config.php.
  embed                 Inspects oEmbed providers, clears embed cache, and more.
  eval                  Executes arbitrary PHP code.
  eval-file             Loads and executes a PHP file.

If you don’t notice or are unable to see the problem, each command listed has an “intro” description except for my command which instead just has a blank space.

Instead of grepping all of wp-cli’s code, I luckily had Yoast installed, too, so I grepped their code and saw a special class from core that you can extend call CommandNamespace which has the following comment:

Adds a command namespace without actual functionality.

This is meant to provide the means to attach meta information to a namespace when there’s no actual command needed.

In case a real command gets registered for the same name, it replaces the command namespace.

https://github.com/wp-cli/wp-cli/blob/bc37f66e25b9992813b0c50b933aefbf88718e6a/php/WP_CLI/Dispatcher/CommandNamespace.php#L8

So, just create a class that extends that (and probably make it final), register it like a normal command, and WordPress will do the rest for you.

The post How to create a command that holds other commands in wp-cli (WordPress CLI) appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/12/18/how-to-create-a-command-that-holds-other-commands-in-wp-cli-wordpress-cli/feed/ 0
How to move a Google Analytics property without admin access to both accounts https://cjhaas.com/2019/11/21/how-to-move-a-google-analytics-property-without-admin-access-to-both-accounts/ https://cjhaas.com/2019/11/21/how-to-move-a-google-analytics-property-without-admin-access-to-both-accounts/#respond Thu, 21 Nov 2019 15:57:13 +0000 https://cjhaas.com/?p=955 If you have a Google Analytics property that you want to transfer to a different account, you need to be an admin (technically have Edit Property permissions) on both accounts, and there’s no way around this. So, how can you move an account if you don’t want to grant admin access to your client, and […]

The post How to move a Google Analytics property without admin access to both accounts appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
If you have a Google Analytics property that you want to transfer to a different account, you need to be an admin (technically have Edit Property permissions) on both accounts, and there’s no way around this.

So, how can you move an account if you don’t want to grant admin access to your client, and they don’t want to grant you admin access?

The solution is super obvious when you think about it, and it was this morning, but for some reason last night it didn’t even cross my mind.

Create a third account! Duh.

Just make a brand new account with both you and the client listed as admins, then you move the property into that account, and the client can move the property out of that account. Once done, delete the temporary account.

Side note: whenever you create an account, you are required to also create a property, even if you aren’t going to use it. Just call it Delete Me or similar and remember to delete it when this is all done.

The post How to move a Google Analytics property without admin access to both accounts appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/11/21/how-to-move-a-google-analytics-property-without-admin-access-to-both-accounts/feed/ 0
mySQL Recursive CTE https://cjhaas.com/2019/10/25/mysql-recursive-cte/ https://cjhaas.com/2019/10/25/mysql-recursive-cte/#respond Fri, 25 Oct 2019 09:28:14 +0000 https://cjhaas.com/?p=947 Almost 10 years ago I asked this question on Stack Overflow about how to find the deepest nodes in a recursive table using a Common Table Expression (CTE). Fast forward to today, and I need a mySQL equivalent, specifically for MariaDB. Please read the original question to get the gist, below is the table, records […]

The post mySQL Recursive CTE appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
Almost 10 years ago I asked this question on Stack Overflow about how to find the deepest nodes in a recursive table using a Common Table Expression (CTE). Fast forward to today, and I need a mySQL equivalent, specifically for MariaDB.

Please read the original question to get the gist, below is the table, records and CTE converted to mySQL (tested against MariaDB 10.2.22).

Create the table

CREATE TABLE Employees
(
   EmployeeId int NOT NULL AUTO_INCREMENT,
   ParentEmployeId int NULL,
   Name varChar(255),
   PRIMARY KEY (EmployeeId),
   CONSTRAINT FOREIGN KEY (ParentEmployeId) REFERENCES Employees(EmployeeId)
)

Insert rows

INSERT INTO Employees VALUES (1, NULL, 'Company President 1');
INSERT INTO Employees VALUES (2, NULL, 'Company President 2');
INSERT INTO Employees VALUES (3, 1, 'Company President 1 - VP');
INSERT INTO Employees VALUES (4, 2, 'Company President 2 - VP');
INSERT INTO Employees VALUES (5, 3, 'Company President 1 - VP - Secretary');
INSERT INTO Employees VALUES (6, 4, 'Company President 2 - VP - Secretary');
INSERT INTO Employees VALUES (7, 5, 'Company President 1 - VP - Secretary - Sandwich Delivery');

Query

WITH RECURSIVE EmployeeRec AS
(
    SELECT
        EmployeeId AS Master,
        EmployeeId,
        ParentEmployeId,
        Name,
        1 as Level
    FROM
        Employees
    WHERE
        ParentEmployeId IS NULL
        
    UNION ALL

    SELECT
         R.Master,
         E.EmployeeId,
         E.ParentEmployeId,
         E.Name,
         R.Level + 1
    FROM
         Employees E
    INNER JOIN
         EmployeeRec R
    ON
         E.ParentEmployeId = R.EmployeeId
)
SELECT
    er.Master,
    er.EmployeeId,
    er.ParentEmployeId,
    er.Name,
    m.Level
FROM
    EmployeeRec er
INNER JOIN
    (
      SELECT
            Master,
            MAX(Level) AS Level
      FROM
            EmployeeRec
      GROUP BY
            Master
   ) m
ON
    m.Master = er.Master
   AND
    m.Level = er.Level

Notes

  • For comparison sake, I left the typo of ParentEmployeId in, even though that messed me up several times as I typed it
  • In the result set, Master represents the root parent, and Level represents the depth (total number of nodes in the specific chain, including this node)

The post mySQL Recursive CTE appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/10/25/mysql-recursive-cte/feed/ 0
WPDB Insert automatically changing string format to number https://cjhaas.com/2019/10/16/wpdb-insert-automatically-changing-string-format-to-number/ https://cjhaas.com/2019/10/16/wpdb-insert-automatically-changing-string-format-to-number/#respond Wed, 16 Oct 2019 14:22:35 +0000 https://cjhaas.com/?p=941 The third parameter to wpdb::insert() is an array of formats that defaults to %s unless they are overridden in wpdb::$field_types. This is last part is very important. When WordPress boots, it statically sets that list to fields that should always be numbers unless someone specifies an explicit format as the third parameter. Currently there these […]

The post WPDB Insert automatically changing string format to number appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
The third parameter to wpdb::insert() is an array of formats that defaults to %s unless they are overridden in wpdb::$field_types. This is last part is very important. When WordPress boots, it statically sets that list to fields that should always be numbers unless someone specifies an explicit format as the third parameter. Currently there these 34 in the file (I was tripped up by object_id which my system is storing as a string).

    'post_author'      => '%d',
    'post_parent'      => '%d',
    'menu_order'       => '%d',
    'term_id'          => '%d',
    'term_group'       => '%d',
    'term_taxonomy_id' => '%d',
    'parent'           => '%d',
    'count'            => '%d',
    'object_id'        => '%d',
    'term_order'       => '%d',
    'ID'               => '%d',
    'comment_ID'       => '%d',
    'comment_post_ID'  => '%d',
    'comment_parent'   => '%d',
    'user_id'          => '%d',
    'link_id'          => '%d',
    'link_owner'       => '%d',
    'link_rating'      => '%d',
    'option_id'        => '%d',
    'blog_id'          => '%d',
    'meta_id'          => '%d',
    'post_id'          => '%d',
    'user_status'      => '%d',
    'umeta_id'         => '%d',
    'comment_karma'    => '%d',
    'comment_count'    => '%d',
    // multisite:
    'active'           => '%d',
    'cat_id'           => '%d',
    'deleted'          => '%d',
    'lang_id'          => '%d',
    'mature'           => '%d',
    'public'           => '%d',
    'site_id'          => '%d',
    'spam'             => '%d',

You might be tempted to do something like wpdb->insert('table', $values, ['object_id' => '%s']) but that won’t work, either. The logic for looking up a format by columns is only used for the core fields, which you can see here.

If everything to be inserted is a string (or should be inserted as a string) then you can just pass %s or [%s] as the third parameter (the former gets converted to the latter) and WordPress will use it for items.

Unfortunately, if anything else needs to be inserted in a non-string way, you need to explicitly set each placeholder.

(Okay, technically, if your first parameter is a string, you only need to provide formats up till the last non-string, because the logic for missing placeholders is to use the first provided one, but that’s just begging to either break or get yourself punched, possibly by your future self.

The post WPDB Insert automatically changing string format to number appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/10/16/wpdb-insert-automatically-changing-string-format-to-number/feed/ 0
WP 5.3 – Breaking changes https://cjhaas.com/2019/10/09/wp-5-3-breaking-changes/ https://cjhaas.com/2019/10/09/wp-5-3-breaking-changes/#respond Wed, 09 Oct 2019 13:31:20 +0000 https://cjhaas.com/?p=935 This is pretty big, and I’m guessing that a good number of people that have WP_DEBUG_LOG turned on (like me, sorry Scott) might see it filling up fast when 5.3 lands, and there might be some fatal errors, too. The discussion is here: https://core.trac.wordpress.org/ticket/47678 The gist is that they are introducing some modern PHP-isms (where […]

The post WP 5.3 – Breaking changes appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
This is pretty big, and I’m guessing that a good number of people that have WP_DEBUG_LOG turned on (like me, sorry Scott) might see it filling up fast when 5.3 lands, and there might be some fatal errors, too.

The discussion is here:

https://core.trac.wordpress.org/ticket/47678

The gist is that they are introducing some modern PHP-isms (where “modern” is 5.6 from 2014) and although they fix some performance issues, they do break compatibility with some code.

The fix is overall pretty trivial, basically any code that is overriding core’s code that is changing will need to update function signatures (and it appears that there were about 50 cases of this).

For instance, the old signature might be:

function walk( $elements, $max_depth )

And the new signature would be:

function walk( $elements, $max_depth, ...$args )

No actual logic needs to be changed, just the function/method signature. This is similar to when PHP enforced the __construct() method in 7.0.

The most problematic change is a fatal error (not a warning) with the Walker class which WordPress uses for a lot of different things.

The recommendation is to grep for something like:

find /var/www/ -type f -name "*.php" | grep -v "/wp-includes/" | xargs grep -PHns "function (?:paged_)?walk\s*\(\s*\\$"

Ignore anything from core and only focus on plugins and themes. There will false-positives (specifically there’s something in ACF that matches this but isn’t affected) but you are generally looking for something that has two parameters, $elements and $max_depth. Then just update with the signature above.

For other warnings no related to the Walker class you might just need to poke around and see what’s changed.

The post WP 5.3 – Breaking changes appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/10/09/wp-5-3-breaking-changes/feed/ 0
Turn on spellcheck for any web page https://cjhaas.com/2019/07/09/turn-on-spellcheck-for-any-web-page/ https://cjhaas.com/2019/07/09/turn-on-spellcheck-for-any-web-page/#respond Tue, 09 Jul 2019 13:38:51 +0000 https://cjhaas.com/?p=930 Bring up the console and enter these two: document.body.contentEditable='true';document.body.spellcheck='true';

The post Turn on spellcheck for any web page appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
Bring up the console and enter these two:

document.body.contentEditable='true';document.body.spellcheck='true';

The post Turn on spellcheck for any web page appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/07/09/turn-on-spellcheck-for-any-web-page/feed/ 0
MySQL DUAL table https://cjhaas.com/2019/05/21/mysql-dual-table/ https://cjhaas.com/2019/05/21/mysql-dual-table/#respond Tue, 21 May 2019 22:03:44 +0000 https://cjhaas.com/?p=925 Here’s code that should work on any MySQL server regardless of databases and tables: SELECT 1 FROM DUAL Apparently they copied it from Oracle.

The post MySQL DUAL table appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
Here’s code that should work on any MySQL server regardless of databases and tables:

SELECT 1 FROM DUAL

Apparently they copied it from Oracle.

The post MySQL DUAL table appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/05/21/mysql-dual-table/feed/ 0
PHP Include Path Surprises https://cjhaas.com/2019/05/21/php-include-path-surprises/ https://cjhaas.com/2019/05/21/php-include-path-surprises/#respond Tue, 21 May 2019 19:36:00 +0000 https://cjhaas.com/?p=916 While diagnosing a potential unconfirmed problem with a certain popular WordPress plugin I did something that every good developer should do every once in a while, which is to humble themselves and read the most basic and obvious documentation for the simplest parts of a language or framework that you know by heart. If you […]

The post PHP Include Path Surprises appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
While diagnosing a potential unconfirmed problem with a certain popular WordPress plugin I did something that every good developer should do every once in a while, which is to humble themselves and read the most basic and obvious documentation for the simplest parts of a language or framework that you know by heart.

If you aren’t a programmer, what I mean is the equivalent of reading a driver’s education book even though you’ve been driving for years or decades. And I don’t necessarily mean “what’s the yellow blinking arrow mean”, I mean basic like “how do I make the car go left?”

And when I say read, I don’t mean skim, I really mean thoroughly read. For instance, to make a car go left, you don’t “turn the wheel left” but instead, when going forward you turn the wheel counter/anti-clockwise! The top of the wheel goes left but the bottom of the wheel goes right. Stupid and obvious, I know. But how about when going backward. Puzzle that through, I think there’s actually a two-part answer there (for how most people use reverse at least). And then, just for fun, work through the scenario with a trailer (although I don’t think they teach that in driver’s ed).

Anyhow, back to code.

I’ve always known that there have been peculiarities about PHP’s include system, and I’ve always tried to use absolute paths just to avoid the peculiarities, but I never really dove into what the specific nuances were until this morning.

The below code is talking about include however it applies to require and require_once just the same.

From the documentation:

Files are included based on the file path given or, if none is given, the include_path specified. If the file isn’t found in the include_path, include will finally check in the calling script’s own directory and the current working directory before failing

That might be a “duh” moment for some people, and maybe you’ll stop reading this because you think I’m an idiot for writing about obvious stuff.

But here’s the problem: what do they mean by “file path” exactly? Going to the next paragraph in the documentation it says:

If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..)

Do you get where I’m going yet?

Let’s look at a common bit of code:

require_once 'file.php';

The second quote above basically says that for the argument to this code to be considered path-based, the string must begin with either a slash (be absolute) or one or two periods (relative). If these neither of these two conditions are met, the current folder will not be looked at until after the include path is checked.

Read that again. Or let me say it again. If the argument to require/include doesn’t start with a slash or dot, multiple directories will be (potentially) scanned before the current directory.

Let’s make a quick proof-of-concept demo:

<?php

//Make a subfolder if it doesn't exist
if(!is_dir('sub_folder')){mkdir('sub_folder');}

//The PHP script that we'll write to each file, just echoing the script's directory
$contents = '<?php echo __DIR__ . "\n";';

//Create two files, one "here" and one in a sub folder
file_put_contents('sub_folder/file.php', $contents);
file_put_contents('file.php', $contents);

//Unless you have this file in your own path, these two should be the same
require 'file.php';
require './file.php';

//Change the current include path
set_include_path(__DIR__ . '/sub_folder');

//Re-run the exact same code as above, the first result is now different than the second!
require 'file.php';
require './file.php';

You can save that somewhere as runner.php and then run php -f runner.php from that directory.

What do you get when you run it? Here’s what I get:

/home/demo_user
/home/demo_user
/home/demo_user/sub_folder
/home/demo_user

Did you notice that third one? That’s the call to just require 'file.php' which, because it doesn’t start with a slash or a period, searched the include path first looking for a match, not the current folder!

Now, if you’re running in your own private code base and server, this might not be a big deal. The perf problems of this are probably very negligible, too, to the point that I don’t think you’d ever notice.

But if you’re creating code for other people to consume, you cannot guarantee that they don’t have an include path set, and you also cannot guarantee that they don’t have a file with your exact structure in that path. Probably not, or, hopefully not.

But the fix is actually easy. Just always use absolute or relative paths.

If you want a file in the current directory, just always prepend with ./. (However, scroll to the additional problem to see why this breaks, too!)

Or, better yet, in whatever you think should be your “entrance file(s)”, define a constant that holds the value of __DIR__ for that file and use that with concatenation for your files.

//In your entrance file
define('MY_APP_ROOT', __DIR__);

//In your other files
require_once MY_APP_ROOT . '/path/to/my/file.php';

That’s exactly what WordPress does.

Even better than all of this is to avoid require and include in general and always use composer to handle things on your behalf, but that’s not always an option.

A thought from a security perspective

As I write this, I’m thinking about a pretty interesting exploit that would be hard-ish to debug. First, you’d need to get code onto someone’s server and second, you’d need to get it into the execution path. We’ll wave our hand and pretend that’s done somehow. Once that happens, that code could set the include path to include its own code just by naming files the same as other code that gets included with a true path. This exploit code could even then re-require the legitimate code, effectively making it a trojan that no one notices (depending on what the payload does).

Once again, they’d need to have elevation to start with, but once in, this would be almost impossible to notice if the payload is silent enough, like logging passwords or something.

An additional problem

I’m going to take the initial code same I gave and tweak it a little bit. This time, we’re going to create an extra sub folder that has the same file.php with the exact same contents as the others. Also in that folder we’re going to create one additional file with the only job of running our main original code via require.

(Also, I’m using better ABS paths for creating things because with the jumping around for demo purposes things get weird otherwise. The actual spirit of the original demo is still here, just more specific.)

 <?php

//Save this file as runner.php

//We're going to use two sub folders
$FOLDER_ALPHA  = __DIR__ . '/sub_folder';
$FOLDER_RUNNER = __DIR__ . '/sub_runner';

//Make them if they don't exist
if(!is_dir($FOLDER_ALPHA)){mkdir($FOLDER_ALPHA);}
if(!is_dir($FOLDER_RUNNER)){mkdir($FOLDER_RUNNER);}

//The PHP script that we'll write to each file, just echo'ing the script's directory
$contents = '<?php echo __DIR__ . "\n";';

//Create three files, one "here" and one in each sub folder
file_put_contents("${FOLDER_ALPHA}/file.php",    $contents);
file_put_contents("${FOLDER_RUNNER}/file.php",   $contents);
file_put_contents('file.php',                    $contents);

$second_runner_contents = '<?php require dirname(__DIR__) . "/runner.php";';
file_put_contents("${FOLDER_RUNNER}/runner.php", $second_runner_contents);

//Unless you have this file in your own path, these two should be the same
require 'file.php';
require './file.php';

//Change the current include path
set_include_path($FOLDER_ALPHA);

//Re-run the exact same code as above, the first result is now different than the second!
require 'file.php';
require './file.php';

Now, from a command line where you saved the above run php -f runner.php and you’ll get something like:

/home/demo_user
/home/demo_user
/home/demo_user/sub_folder
/home/demo_user

No surprises, the previous code talked about this. From that same folder now run php -f sub_runner/runner.php and you’ll get:

/home/demo_user
/home/demo_user
/home/demo_user/sub_folder
/home/demo_user

Once again, still the same.

Lastly, we’re going to cd into our new inner folder and run that runner:

cd sub_runner/
php -f runner.php

Which now gives:

/home/demo_user/sub_runner
/home/demo_user/sub_runner
/home/demo_user/sub_folder
/home/demo_user/sub_runner

Wow, that’s new. We’re invoking almost the exact same code, just in a slightly different way. This time, we’re tripping a different rule from the include documentation (same as above, sub-setted below):

include will finally check in the calling script’s own directory and the current working directory before failing

I’m not actually sure the documentation is correct here, or, more specifically, I can’t get “calling scripts own directory” to be any different than “current working directory”. If someone can get me an actual working difference I’d love to see that.

Back to the results, because are working directory was changed, and because there was a new magic-named file in that folder, our main script used that file for the non-path version. But also notice that the explicitly relative paths also broke!

The path ./file.php isn’t relative to the file it is written in, it is relative to the current working directory! This basically means that the only absolutely safe method to include files is to always use the absolute path format, unless you have 100% absolute control over everything.

The post PHP Include Path Surprises appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/05/21/php-include-path-surprises/feed/ 0
Drupal Status Color Codes https://cjhaas.com/2019/05/16/drupal-status-color-codes/ https://cjhaas.com/2019/05/16/drupal-status-color-codes/#respond Thu, 16 May 2019 18:51:13 +0000 https://cjhaas.com/?p=910 This has bugged me for a long time. If you visit any project issue page on Drupal.org you’ll find a bunch of different color-coded table rows. What the heck do the colors mean!!! It has always bothered me, but today I decided to finally dig in. This process wasn’t hard in any way, I just […]

The post Drupal Status Color Codes appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
This has bugged me for a long time. If you visit any project issue page on Drupal.org you’ll find a bunch of different color-coded table rows.

Example of multiple issues on Drupal.org's website for the Feeds module showing many different colored rows, where the specific usage of color for the row isn't obvious.

What the heck do the colors mean!!!

It has always bothered me, but today I decided to finally dig in. This process wasn’t hard in any way, I just really wanted a key somewhere to understand the rationality behind the order. Below I present that.

1Active#f9f9f9
13Needs work#ffece8
14Reviewed & tested by the community#f1ffe8
15Patch (to be ported)#f1ffe8
16Postponed (maintainer needs more info)#eff1fe
17Closed (outdated)#eff1fe
18Closed (cannot reproduce)#fddddd
2Fixed#d7ffd8
3Closed (duplicate)#eff1fe
4Postponed#eff1fe
5Closed (won’t fix)#eff1fe
6Closed (works as designed)#eff1fe
7Closed (fixed)#fddddd
8Needs review#ffffdd
  • Generally speaking, green-like status represent done or mostly done things
  • Yellow means a review is needed
  • Blue-ish/purple-ish is “not going to fix” for many different reasons
  • Red-ish is either fixed or confusingly, needs to be worked on (the latter has a different shade of red but it is hard to tell unless it is side-by-side with the former)
  • Grey is an active bug

To be clear, this isn’t a judgment of any of the statuses, this is just a key which I needed.

The post Drupal Status Color Codes appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/05/16/drupal-status-color-codes/feed/ 0
You have requested a non-existent service “media_entity.cli” https://cjhaas.com/2019/05/07/you-have-requested-a-non-existent-service-media_entity-cli/ https://cjhaas.com/2019/05/07/you-have-requested-a-non-existent-service-media_entity-cli/#respond Tue, 07 May 2019 18:58:42 +0000 https://cjhaas.com/?p=907 We upgraded a Drupal site to 8.7 that had used media_entity previously and we needed to get it converted over to core’s media module. We followed all of the directions but we kept running into the error: You have requested a non-existent service "media_entity.cli" After a bunch of trial and error we decided to just […]

The post You have requested a non-existent service “media_entity.cli” appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
We upgraded a Drupal site to 8.7 that had used media_entity previously and we needed to get it converted over to core’s media module. We followed all of the directions but we kept running into the error:

You have requested a non-existent service "media_entity.cli"

After a bunch of trial and error we decided to just hack the module by adding a test for the existence of the service before consuming it.

In the file media_entity/media_entity.drush.inc before the line the contains \Drupal::service('media_entity.cli') we added:

if(!\Drupal::hasService('media_entity.cli.cli')){
return TRUE;
}

The post You have requested a non-existent service “media_entity.cli” appeared first on Basically a place that Chris can post solutions to problems so he can easily find them later.

]]>
https://cjhaas.com/2019/05/07/you-have-requested-a-non-existent-service-media_entity-cli/feed/ 0