WordPress multisite allows plugins and themes to be Network Active. This prevents them from being deactivated on any site in the network.
To change a plugin from Network Active on every site to individually active on each site:
Manually Network Deactivate the plugin from the network plugins page. The wp network command does not yet support plugin deactivation.
Connect to the server via SSH and run this WP CLI command: wp site list --field=url | xargs -n1 -I % wp --url=% plugin activate hello.php (where hello.php is the plugin file or folder name)
The | operator passes the results from wp site list to xargs. xargs can take the output from one command and send it to another command as parameters.
wp --url=% plugin activate hello.php is the command to which xargs is passing the site URLs. It activates the Hello Dolly plugin on each site specified by URL.
Blocking spam on WordPress websites is heavy work. Akismet comes pre-installed on every site, but it’s not free for businesses or the only way to stop spam.
If you’re building blocks for WordPress, and the error TypeError: c is not a function is logged in your browser’s developer console, you may have created a TextControl component and failed to include both value and onChange attributes.
If you see the default “Thanks for contacting us! We will get in touch with you shortly.” even if you’ve created a custom confirmation for your Gravity Form, your entry may have been marked as spam.
All entries deemed spam are shown the default message. Login and try again–logged in users will not get caught in the spam filter.
Also, visit the Entries list in the dashboard, and look for the Spam folder. Your entry may have been saved with the other Spam.
Where in the Gravity Forms source code does this happen?
If you’re building blocks for WordPress, and the error TypeError: b.map is not a function is logged in your browser’s developer console, you may have created a SelectControl component and failed to wrap the options in brackets to create an array.
I recently gifted myself a Bosch 1617EVSPK router, and the first project is mounting it to a old Craftsman 171.253512 router table that came with the used contractor table saw I bought myself for my 37th birthday.
An adapter plate is needed. None of the threaded mounting holes on the fixed router base line up with holes in the table. A friend advised me to cut the plate out of metal or acrylic rather than wood. I may do that. First, I’m making a prototype out of 1/2 inch birch plywood.
The challenge is that a hole is needed in the center to line up with the hole in the center of the router table. The hole is 2 and 7/8 inches. The first thing you learn when you get a router is that you need a guide for every cut. To cut a hole, you need a bigger hole, or circle jig, in which to run the tool.
I migrated a Time Machine backup from a 2015 Intel High Sierra to a 2021 M1 Monterey. I love the computer, and the migration was largely a success.
I use Laravel Valet to run and develop local websites. They break every time I restart the new machine. php -v from Terminal always returns 8.0, but calling phpInfo(); from one of the local sites reveals PHP 7.2.34 is running and none of the sites can find MySQL.
If I run valet use [email protected], I get: Valet is already using version: [email protected]. To re-link and re-configure use the --force parameter.
Then I run valet use [email protected] --force and I get this output:
I suspect this has something to do with having to install a different version of homebrew for the M1 processor architecture and the old version of homebrew still existing because of the migration, but I don’t understand what is happening.
Things I’ve Tried
valet install Updating valet does not fix this problem.
Entry approval is a Gravity View feature I use often. Even if I’m not using Gravity View on a project that needs to filter out some entries, I’ll save the same data in the $wpdb->_gf_entry_meta table to be compatible. The meta key is_approved contains one of the values in the table below.
I learned that the .org docs page content is generated by scanning the project source code, extracting PHPDoc comments, and parsing them into custom post types. The piece of software that does that is https://github.com/WordPress/phpdoc-parser.
Build the Data
Add PHPDoc comments to all classes and methods in your plugin.
SIDE NOTE: I would like to include wporg-developer in my theme or child theme instead of copying files, but step 2 below makes it hard to use wporg-developer as a dependency. It must be edited. I would enjoy having easy access to updates, and perhaps I could contribute to the theme to add necessary filters someday in the future.
How to download wordpress.org source code
This SVN command will download the whole theme. Paste the command into a terminal or command prompt window:
svn co https://meta.svn.wordpress.org/sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/
Copy these files from wporg-developer into your child theme
/inc
/js
/reference
/stylesheets
content-reference.php
content-reference-archive.php
functions.php (comingle it with your functions.php)
Theme Mods
Change option value wp_parser_root_import_dir to contain a path to the project. For me, this path points to a plugin in the wp-content/plugins folder.
Change get_template_directory_uri() calls to get_stylesheet_directory_uri() calls
Create single.php by taking a copy from the parent theme. Modify it to serve a different content template for the post types populated by phpdoc-parser. Here is a code sample that shows what to change to create a Twenty Twenty-One child theme.
Optional: Change “View on Trac” links I added two filters that wrap the URL and the text in the “View on Trac” link below the source code section of each page. These changes allow me to change the links to “View on Github” or wherever I want.
If no source code is displaying, edit the option wp_parser_root_import_dir to contain a full path to the directory of the plugin. Example: /corey/sites/inventorypress/wp-content/plugins/inventory-presser
My Observations So Far
I love it, but I didn’t try anything else. Writing code comments is now also writing web pages and a great motivator to do it right.
Done! See Add-on Pluginsphpdoc-parser reruns do not delete items. I need to write code that deletes functions, methods, hooks, and classes that are removed from the project.
Done! See Automating Updates to DocsI want to write a Github action to automate wp-parser runs on new versions of the plugin. When I push updates to the public repo, a copy of the plugin is written to the webserver, and wp-parser is run to generate new docs.
Automating Updates to Docs
Four months after I published this post, I designed a Github Action to automate the creation and updating of the docs pages. When I push to the master branch of my plugin’s repo, the plugin is deployed to the site on WP Engine where the docs pages are hosted, and the wp-cli command that generates the docs is run.
I wrote two add-on plugins to modify the behavior of phpdoc-parser.
phpdoc-ignorer instructs phpdoc-parser to ignore the /vendor folder in my plugin
phpdoc-deleter keeps track of every post created or updated by phpdoc-parser. After the run is complete, it deletes all posts that were not touched and then empty taxonomy terms.
I built a WordPress plugin that saves a copy of all Gravity Forms entries in a Google Sheet as they are received. Entries to Google Sheet is the glue between a Gravity Form and a Google Sheet.
This is confusing: calls to get_fields() find no Advanced Custom Fields values saved with a specific post, but calls to get_field() find values for the same post.
This happens when ACF did not insert the field values, and the secondary value with the meta_key beginning with an underscore does not exist.
The post has the values, but the Advanced Custom Fields plugin expects an additional value in a hidden field for each field.
Anytime xDebug examines PHP files, it will create log entries if its configuration specifies a log file location. I found that log entries were created when Valet was starting up but not when pages were loaded in the browser.
The remote_log and remote_log_level settings are commented-out with semicolons because my configuration is now working. A log level value of 10 will grow the log file to hundreds of megabytes in just a few hours of loading pages.
Do not try to prettify the ext-xdebug.ini file by putting spaces around the equals signs. My breakthrough to a working debugger occurred shortly after I removed spaces from ext-xdebug.ini, updated Valet, and restarted my computer.
Contents of VS .code-workspace file
{
"folders": [
{
"path": "."
}
],
"settings": {},
"launch": {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9001
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"stopOnEntry": true,
"cwd": "${fileDirname}",
"port": 9001,
"runtimeExecutable": "/usr/local/Cellar/php/7.4.9/bin/php",
"pathMappings": {
"/Users/Corey/Sites/sitename": "${workspaceFolder}"
}
}
]
}
}
The runtimeExecutable value points to the PHP executable installed by homebrew. The pathMappings value points to the place where this website lives on my computer.
Stop and restart the debugger in VS Code everytime you change the workspace file or the web server is restarted.
M1 Processor
I got a new Macbook, and restored my old Intel processor back up to it. That means there are two versions of homebrew on my computer now, and I got into a situation where phpInfo() calls on web pages returned a different version of PHP than php -v in terminal. This fixed that, but I do not know why: