WordPress Multisite Is Still a Valuable and Often Necessary Tool

Rob Howard rocked the boat last week in calling for the deprecation of WordPress multisite in the latest MasterWP newsletter. He argued that “the brave and noble add-on is no longer necessary or valuable to developers.” The responses via Twitter were swift and in disagreement.

Before WordPress 3.0, multisite was an entirely separate system called WPMU (WordPress MultiUser). It was a mess to set up, and one of the best things to ever happen to it was that it was rolled into core WordPress. It became a first-class citizen in the WordPress world, and its setup is now simple enough that nearly anyone can get a network up and running in no time.

I have not used multisite much in my career in the WordPress space. My primary use case has been for setting up theme and plugin demos. These are sites that I do not intend to touch much outside of their initial setup. Multisite always makes it easy to manage theme and plugin updates from the network admin.

Howard argued that this is no longer necessary in today’s world:

Likewise, sharing themes and plugins between sites no longer seems like a benefit to developers or end-users. With one click, we can deploy a parent theme from a Git repository to an unlimited number of sites hosted anywhere in the world – so what’s the real value of having a theme on the Multisite network?

Even with the vast tools available for deploying such things via Git, sometimes I prefer to avoid complicating matters. I can work in the command line well enough, but having that central location to manage all of my sites in one place is simpler. The argument also leaves out an entire segment of users who run multisite and have never even heard of Git. Multisite is sometimes a user tool.

The most complex multisite setup I have worked on was for a university. I was contracted to do some development work for another WordPress agency a few years ago. My focus area was extending the user role and permissions system.

The network had sites for each school, department, and various other projects. Setting all of this up on multisite allowed the permanent dev team to create new sites on an as-needed basis instead of spinning up an entirely new WordPress install. Everyone also had user access via their university email and password. It is possible to share a user database via multiple single-site installs, but it adds another layer of complexity that does not exist with multisite.

I cannot imagine the agency running this through 100s of individual installs. I am sure that some systems would make this easier, but a solution already exists in WordPress.

My multisite experience is limited. However, I have routinely talked with and helped fellow developers actively working on networks with 1,000s of sites in the enterprise and education sectors. It is almost a given that they are running multisite for every job.

WordPress co-founder Mike Little explained why multisite is often necessary for his work via Twitter:

Of course, I manage a hundred single instances too, a couple of them are 3-6-site multisites, but most are single (and should remain so). But one client of mine has close to 450 sub-sites on one of his multisites. That would be impossible to manage as separate sites.

Around 1K users per subsite, up to 100+pages of content created/day during an event. etc. It’s also constantly being developed.

Rolling out fortnightly code changes to 400+ single sites (not mentioning there are more than a dozen other instances with up to 50 sub sites each) would be unmanageable. And this isn’t a for profit org, so doesn’t have unlimited funds.

I have sat on this article since last Wednesday. At the time, I was ready to leap into the fire and defend multisite. However, as the responses rolled in via Twitter to the MasterWP article, I was disheartened by a few of the responses from the WordPress community. I did not want to feel like I was piling on.

The world of social media has made knee-jerk reactions all too common and uninviting to those outside of the inner WordPress circle. There is too much pressure to not say the “wrong” thing that so few end up saying anything worthwhile — or at all. Fortunately, there is still some thoughtful discourse, such as the response article by Maciek Palmowski on WP Owls and from others on Twitter.

Perhaps Howard was really just writing a click-bait article. However, because he only recently became the new owner of the MasterWP newsletter, I felt like I owed it to him to believe he was attempting to generate sincere discussion. Maybe his conclusion of deprecating a vital feature for many was off-base, but the conversation around problems with multisite is worth having.

Regardless of the merits of Howard’s argument, it did lead to an idea that might just be worth exploring. Alain Schlesser tweeted:

I’d prefer for single-site to be deprecated instead, to not have a random differentiation anymore. Everyone just has a network, but some only have a single site on them. Would simplify everything…

I do not know what such a WordPress would look like, but I do know that it could simplify the multisite installation process if there were only one way of doing it. Perhaps there would be fewer edge cases, plugin issues, and wrinkles that developers need to iron out if there were only one flavor of WordPress.

Kotlin – Lists of Lists

First, my apologies, I couldn't tag this as kotlin and I figured Java was the next closest thing. This is homework, I'm not looking for someone to do it for me, just a little help. So the first thing is that I've got a sealed interface with some subclasses (all required to be like this, this part can't change)

sealed interface Mammal{
    abstract val name: String
    abstract val age: Int
    abstract val friends: List<Mammal>
}

data class Human(override val name: String = "",
                 override val age: Int,
                 val nickName: String,
                 override val friends: List<Mammal> = emptyList()
                ) : Mammal

data class Dog(override val name: String,
               override val age: Int,
               val favoriteTreat: String,
               override val friends: List<Mammal> = emptyList()
              ) : Mammal

data class Cat(override val name: String,
               override val age: Int,
               val numberOfMiceSlain: Int,
               override val friends: List<Mammal> = emptyList()
              ) : Mammal

Then I've got some functions, which are required to be top-level extension functions on List<Mammal>. I think if I just have help with one, the rest will fall in line and make more sense, so this is the one I'd like help with. The only thing required in the function is fun List<Mammal>.getNamesAndFriendsAges(){}, the rest is me fighting with it trying to make it work. This should return

//  Names and sums of their friends' ages
//      Fido=229
//      Blackie=55
//      Patrick=148

And this is what I have so far (this is the part I need help with).

// creates a map of the name of each mammal and the sum of the ages of their friends
fun List<Mammal>.getNamesAndFriendsAges(): Map<String, Mammal> {
    return this
       // .flatMap { it.friends.groupBy { it.name } }
        //.groupBy { it.name }
     //   .associateBy{it.name + it.friends + sumOf { it.age }}
     //   .associateBy{it.name + sumOf { it.age }}
     //   .associateBy { it.name }
        .sortedBy { it.name }
        .flatMap { it.friends }
        .associateBy { it.name }
}

And this is the important part of main (none of which can change):

    fun main() {
        val mammals = listOf(
            Dog("Fido", 1, "Gravy Train",
                friends = listOf(
                    Human("Scott", 53, "Scooter"),
                    Human("Steven", 53, "Steve"),
                    Cat("Thunderbean", 10, 42),
                    Cat("Puffball", 101, 13),
                    Dog("Fifi", 5, "Milk Bone"),
                    Dog("Rover", 7, "Real Bone")
                )
            ),
            Cat("Blackie", 2, 22,
                friends = listOf(
                    Human("Mike", 23, "Mikey"),
                    Human("Sue", 26, "Susie"),
                    Cat("Thing", 5, 3),
                    Cat("Little One", 1, 0)
                )
            ),
            Human("Patrick", 79, "Jean Luc",
                friends = listOf(
                    Human("Ian", 80, "Gandalf"),
                    Human("Hugh", 51, "Wolverine"),
                    Cat("Q", 5, 3468),
                    Dog("Worf", 12, "Gagh")
                )
            )
        )

        println()
        println("Names and sums of their friends' ages")
        mammals.getNamesAndFriendsAges().forEach { println("    $it") }

    }

Evolving Your RESTful APIs: A Step-by-Step Approach

Designing an intuitive, user-friendly RESTful API is a tough job. It might already be a massive task if it’s your first attempt. Planning for the lifecycle management of your API is likely to be an afterthought. But it’s possible anyway: In this post, I’d like to propose a no-nonsense approach to evolving your APIs, even if it was not planned.

The Initial Situation

Let’s consider a sample application that says "Hello" when using it.

IE Down, Edge Up… Global Browser Usage Stats Are for Cocktail Parties and Conference Slides

I enjoy articles like Hartley Charlton’s “Microsoft Edge Looks Set to Overtake Safari as World’s Second Most Popular Desktop Browser.” It’s juicy! We know these massive players in the browser market care very much about their market share, so when one passes another it’s news. Like an Olympic speed skater favored for the gold getting a bronze instead, or the like.

Microsoft Edge is now used on 9.54 percent of desktops worldwide, a mere 0.3 percent behind Apple’s Safari, which stands at 9.84 percent. Google Chrome continues to hold first place with an overwhelming 65.38 percent of the market. Mozilla Firefox takes fourth place with 9.18 percent.

In January 2021, Safari held a 10.38 percent market share and appears to be gradually losing users to rival browsers over time. If the trend continues, Apple is likely to slip to third or fourth place in the near future.

Scoping the data down even by continent is entirely different. Like in Europe, Edge has already passed Safari, but in North America, the gap is still 5%.

Source: MacRumors.com

What does it matter to you or me? Nothing, I hope. These global stats should mean very little to us, outside a little casual nerdy cocktail party chatter. Please don’t make decisions about what to support and not support based on global statistics. Put some kind of basic analytics in place on your site, get data from actual visits, and make choices on that data. That’s the only data that matters.

Alan Dávalos’ “The baseline for web development in 2022” paints a picture of what we should be supporting based again on global browser usage statistics.

Globally, IE’s current market share is under 0.5%. And even in Japan, which has a higher market share of IE compared to other countries, IE’s market share is close to 2% and has a downward tendency.

Until now we kept supporting IE due to its market share. But now, there are basically no good reasons to keep supporting IE.

Again it seems so bizarre to me that any of us would make a choice on what to support based on a global usage statistic. Even when huge players make choices, they do it based on their own data. When Google “dropped” IE 11 (they still serve a perfectly fine baseline experience), they “did the math.” WordPress, famously powering somewhere in the “a third of the whole internet” range, factored in usage of their own product.

Even if you’re building a brand new product and trying to make these choices, you’ll have analytic data soon enough, and can make future-facing support choices based on that as it rolls in.


IE Down, Edge Up… Global Browser Usage Stats Are for Cocktail Parties and Conference Slides originally published on CSS-Tricks. You should get the newsletter.

Xignite Adds Cryptocurrency Data API to its Platform

Xignite, a provider of market data APIs, has announced the release of a new Cryptocurrency Data API that is intended to provide the company’s partners with a more holistic view of investment opportunities and data. This new API exposes data related to real-time and historical quotes for over 900 cryptocurrencies.

Test Case vs. Test Scenario

Test Case

A test case is a set of activities that are carried out to verify the functionality of a certain component or feature of your product application. A test case is a set of test steps, test information, preconditions, and postconditions built for specific test cases to ensure that all prerequisites are met.

It's a collection of circumstances or elements. When a tester determines whether an application, programming framework, or one of its features is performing as expected.

Configure SSO for CockroachDB Dedicated With Microsoft Identity Platform and OpenID

Motivation

CockroachDB Dedicated is a fully-managed, reserved CockroachDB cluster ideal for a cloud database. We frequently get asked how to set up SSO for the individual CockroachDB Dedicated clusters and we have a detailed tutorial to walk you through that with a local, self-hosted cluster. What was unclear was that you can use the same steps to set up SSO with Dedicated. Based on this detailed document, CockroachDB Dedicated supports OIDC authentication for the DB Console today. In a future release, we are going to bring OIDC integration across the stack. Today, we're going to provide details on how to leverage OIDC specifically with the CockroachDB Dedicated DB Console and Microsoft using the OpenID Connect protocol.


Previous Articles on OpenID Connect

High-Level Steps

  • Provision a dedicated cluster
  • Configure Microsoft identity platform integration
  • Configure CockroachDB with the OpenID details
  • Verify

Step-by-Step Instructions

Provision a Dedicated Cluster

Follow this tutorial to set up a Dedicated cluster.

FOSDEM 2022 Conference Report

FOSDEM took place February 5-6. The European-based event is one of the most significant gatherings worldwide focused on all things Open Source. Named the "Friends of OpenJDK", in recent years the event has added a devroom/track dedicated to Java. The effort is led by my friend and former colleague Geertjan Wielenga. Due to the pandemic, the 2022 event was virtual once again. I delivered a couple of talks on Jakarta EE as well as Diversity & Inclusion.

Fundamentals of Diversity & Inclusion for Technologists

I opened the second day of the conference with my newest talk titled "Fundamentals of Diversity and Inclusion for Technologists". I believe this is an overdue and critically important subject. I am very grateful to FOSDEM for accepting the talk. The reality for our industry remains that many people either have not yet started or are at the very beginning of their Diversity & Inclusion journey. This talk aims to start the conversation in earnest by explaining the basics. Concepts covered include unconscious bias, privilege, equity, allyship, covering, and microaggressions. I punctuate the topic with experiences from my own life and examples relevant to technologists. The slides for the talk are available on SpeakerDeck. The video for the talk is now posted on YouTube.

Peculiarities Of Choosing a Extreme Casino

  Table of Contents Why is it necessary to start your way with Extreme Casino? Loyalty program in Extreme Casino Roulette Live extreme casino Successful gameplay depends not only on character, but also on the quality of the gambling and entertainment site. It is the quality of the portal that affects how transparent and honest […]

WPExperts Acquires Post SMTP Plugin

WPExperts, a Pakistan and Egypt-based WordPress development agency with more than 120 employees, has acquired the Post SMTP plugin from its former developer, Yehuda Hassine. This is the agency’s second acquisition this year, after picking up Rich Tabor’s Login Designer plugin in January.

The Post SMTP plugin is a fork of the Postman SMTP plugin, which was closed by WordPress.org in 2017 due to an unfixed security vulnerability. Hassine, a longtime user of the plugin, fixed the vulnerability, forked it, and renamed it to Post SMTP Mailer/Email Log. He grew the plugin to more than 300,000 active users, managing its development and support by himself, before becoming too busy with his full-time job.

Post SMTP improves the delivery of emails that WordPress generates and it logs the causes of failed emails to help eliminate configuration mistakes. Its chief competitors include WP Mail SMTP by WPForms (2 million+ installs) and Easy WP SMTP (600,000 installs). WPExperts plans to continue the plugin’s free version and does not plan to release a commercial version. Instead, they are working towards monetizing it with paid add-ons.

“This is the biggest acquisition for WPExperts in terms of acquired plugin active users (300,000+),” WPExperts community manager Zubair Siddiq said. “WPExperts will enhance Post SMTP’s current UI, features, and support.”

Before selling Post SMTP, Hassine was working on six paid add-ons, which were included in the deal with WPExperts but they are still under development. The add-ons in progress include the following:

  • Office 365
  • Amazon SES
  • Sendinblue
  • Mail Control
  • Twilio Notification
  • Better logger

WPExperts founder Saad Iqbal said the acquisition is aimed at building additional revenue streams for the agency’s plugin shop. Post SMTP joins WPExperts’ collection of nearly 60 free plugins hosted on WordPress.org.

“I normally find plugins in .org and then contact the owner to see if they want to sell,” Iqbal said. “We are always looking to acquire cool WordPress plugins.”

Now that Post SMTP has moved to its new owner, users can expect development and support from a much larger team of professionals, as well as new commercial add-ons in the near future.

Top 7 T-shirt Design Tool Providers For the Printing Industry

Customized t-shirts are liked by the youngsters a lot. They often wear t-shirts with witty one-liners, logos of football teams and many other things. With the T-shirt business becoming more and more user-centric, it is imperative that customers have a design tool that can be used for creating designs on t-shirts with ease. Unlike complex...

The post Top 7 T-shirt Design Tool Providers For the Printing Industry appeared first on DesignrFix.

How to Extract URLs from HYPERLINK Function in Google Sheets

The HYPERLINK formula of Google Sheets lets you insert hyperlinks into your spreadsheets. The function takes two arguments:

  1. The full URL of the link
  2. The description or the anchor text of the link

The URL and anchor text can either be specified as a string or as a cell reference.

If you insert a hyperlink into a cell using the HYPERLINK function, there’s no direct way to extract the URL from the formula. You may consider writing a complicated Regular Expression to match and extract the hyperlink in the cell formula or use Apps Script with Google Sheets API.

const extractHyperlinksInSheet = () => {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = SpreadsheetApp.getActiveSheet();

  const hyperlinks = [];

  const spreadsheedId = ss.getId();
  const sheetName = sheet.getName();

  const getRange = (row, col) => {
    const address = sheet.getRange(row + 1, col + 1).getA1Notation();
    return `${sheetName}!${address}`;
  };

  const getHyperlink = (rowIndex, colIndex) => {
    const { sheets } = Sheets.Spreadsheets.get(spreadsheedId, {
      ranges: [getRange(rowIndex, colIndex)],
      fields: 'sheets(data(rowData(values(formattedValue,hyperlink))))',
    });
    const [{ formattedValue, hyperlink }] = sheets[0].data[0].rowData[0].values;
    hyperlinks.push({ rowIndex, colIndex, formattedValue, hyperlink });
  };

  sheet
    .getDataRange()
    .getFormulas()
    .forEach((dataRow, rowIndex) => {
      dataRow.forEach((cellValue, colIndex) => {
        if (/=HYPERLINK/i.test(cellValue)) {
          getHyperlink(rowIndex, colIndex);
        }
      });
    });

  Logger.log(hyperlinks);
};

Also see: Replace Text in Google Docs with RegEx

Remote Debugging Cloud Foundry Apps

Context

While debugging Java applications in an IDE like IntelliJ Idea is straightforward, it involves slightly more effort to debug a remotely running app. While debugging a remotely running app in production is generally not a good idea, the ability to remote debug apps in lower environments, like integration testing, may be useful.

Cloud Foundry is a platform that allows you to deploy and run your workloads easily and intuitively. IntelliJ Idea is a popular IDE, especially for Java developers.