Media Upload Error After Update of WordPress

I was updating WordPress the other day. and afterward was unable to upload anything to the media library.

Here’s the Error:

Unable to create directory uploads/2023/01. Is its parent directory writable by the server?

I had attempted to edit permissions on the uploads folder and subfolders, which ended up not being the issue.

I found this solution, which worked out great.

Edit your wp-config.php, adding the following line.

define( 'UPLOADS', 'wp-content/uploads' );

before these lines:

/** WordPress absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

Use reduce to find largest/smallest value at index in array

I recently found a chunk of code to iterate through an array and find at what index the largest or smallest value exists using the reduce method. It’s very condensed and seems super efficient.

console.log([...Array(8)]
    .map(n => parseInt(giveMeANumber()))
    .reduce((p, c, i, a) => c > a[p] ? i : p, 0));

So here is what’s happening in order. First an array is initialized. The spread operator (…) is used to create the new Array of length 8. The spread operator spreads out the elements of the array. Here’s what that looks like.

[...Array(8)]; 
[undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]

Second we are using the map method to place an integer value in each index of the Array calling the, as yet, undefined function giveMeANumber(). Which in practice would return an int or the string version of an int and not duplicate any values. Which would look like this.

[...Array(8)].map(n => parseInt(giveMeANumber())); 
[3, 5, 4, 9, 6, 1, 2, 0]

We are using the arrow function (=>) inside the map function to further simplify the code. Essentially,

n => parseInt(giveMeANumber());

Is the same as:

function (n) { parseInt(giveMeANumber()); }

Now we get to the meat of what is really happening here, the reduce method. Here is the definition from Mozilla. The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

The reducer function takes four arguments:

  1. Accumulator
  2. Current Value
  3. Current Index
  4. Source Array

Your reducer function’s returned value is assigned to the accumulator, whose value is remembered across each iteration throughout the array, and ultimately becomes the final, single resulting value.

So our reducer function in this case is:

(p, c, i, a) => c > a[p] ? i : p

“p” stands for “previous” [previous array index] or Accumulator

“c” stands for “current” [array value] or Current Value

“I” stands for current “index” [of array] or Current Index

“a” stands for the full “array” [array] or Source Array

You can see we are using the the arrow function (=>) again here. And we are also using the Conditional (ternary) operator (?,:) to make the conditional more condensed. Which makes the below two functions identical.

(p, c, i, a) => c > a[p] ? i : p 

function (p, c, i, a) { 
    if (c > a[p]) { 
        return i;
    } else { 
        return p; 
    } 
}

All we are saying here is if the current value (c) is greater than the array (a) value at the previous index (p) then return the current index (i) or else return the previous index (p).

You could just switch the operator to find the smallest:

c < a[p]

So, running the complete code would look like this given that we are getting the same array from the map method above

> console.log([...Array(8)] 
    .map(n => parseInt(giveMeANumber())) 
    .reduce((p, c, i, a) => c > a[p] ? i : p, 0)); 
> 3

So, given our array above, it is correctly returning 3. Which is the index of the highest number in the array (9).

Opening View in iOS 13

I had a legacy iPad project that began having issues with views opening in a ‘modal’ window instead of full screen. Technically, they were being instantiated as modals, but since IOS 13 the modal view is what will be presented when using instantiateViewControllerWithIdentifier. It’s a simple fix:

if (@available(iOS 13, *)) { 
   nextPage.modalPresentationStyle = UIModalPresentationCustom; 
}

Unfortunately when you dismiss the view you instantiate using this, it’s parent view no longer receives a viewDidAppear event. So I had to add a call to viewDidAppear before running dismissViewControllerAnimated like so:

if (@available(iOS 13, *)) { 
    [self.presentingViewController viewDidAppear:false]; 
}

Overriding drawLineText method of CreateJS

I needed to superscript some specific characters in a dynamic text field in CreateJS , so I built a prototype function to do just that.

createjs.Text.prototype._drawTextLine = function (ctx, text, y) {
    // Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead:
    if (this.outline) {
        ctx.strokeText(text, 0, y, this.maxWidth || 0xFFFF);
    } else {
        var x = 0;
        if (/(®|†)/.test(text)) {
            var textArr = text.split(/(®|†)/g);
           
            var pxInd = this.font.search(/px/);
            var fntSz = this.font.substring(pxInd - 2, pxInd);
            var fntFc = this.font.substring(pxInd + 2);
            var supSz = Math.round(fntSz * 0.5);
            var supFont = supSz + "px " + fntFc;
           
            var div = (this.textAlign == "center") ? 2 : 1;  // to fix placement with "center" aligned text
           
            for (var t = 0, l = textArr.length; t &lt; l; t++) {
                if (/(®|†)/.test(textArr[t])) {
                    ctx.font = supFont;
                    ctx.fillText(textArr[t], x, y, this.maxWidth || 0xFFFF);
                } else {
                    ctx.font = this.font;
                    ctx.fillText(textArr[t], x, y, this.maxWidth || 0xFFFF);
                }
                x += ctx.measureText(textArr[t]).width / div;
            }
        } else {
            ctx.fillText(text, x, y, this.maxWidth || 0xFFFF);
        }
    }
};

 

Memory limit uploading media in wordpress

I was having issues figuring out why we were reaching a hard limit on upload size even after doing all of the normal fixes though wp-config, .htaccess and apache. We found out the issue was with the all-in-one-security plugin. The all-in-one plugin overrides the apache limit size on instantiation. line 332-333 of  wp-security-utility-htaccess.php

//limit file uploads to 10mb 
$rules .= 'LimitRequestBody 10240000' . PHP_EOL;

Switched from MAMP to Ampps

I made the switch recently from MAMP to Ampps by Softaculous for localhost site development. I had been using MAMP for what seems like forever and was fine with it. I have to admit I had never purchased the pro version of MAMP and was always okay with editing httpd.conf and hosts.conf to get my virtual sites.
Just a side note, my company did recently purchase the pro version of MAMP, but installation kept failing and I was tired of dealing with it.
Back to the point, having recently found the need more and more to install CMSs and other web apps on almost every site, I was looking for another solution and Ampps is it. With it’s c-panel like manager it makes managing domains almost exactly like my hosting provider’s control panel. And it’s amazing list of one-click web app installs must number over 100. CMSs, Blogs, Forums, Wikis, E-Commerce, etc. The only issue I had with it was difficultly in modifying the localhost root directory. With this I just made a compromise and added an alias through the Ampps alias manager. So, now I have a http://localhost/dev/ where I locate all my temporary small projects that don’t require building out a unique domain.

Add Google Analytics to multiple Vimeo videos

I was working on a page earlier this week that had a number of Vimeo videos embedded within a scroller. Each video needed to have a unique identifier submitted with the analytics event tracking. The event was to be submitted only when any video started being played. Here is the small chunk of code I used for this. Don’t forget to include the Froogaloop library to access the vimeo player’s events.

var iframes = $('iframe.vimeovideo'); 
    iframes.each(function(i, obj) { 
    $(obj).load(function() { 
     var txt = $(obj).next().text(); // text from an h1 element
     var player=$f(this);
     player.addEvent('ready', function() {
       player.addEvent('play', function(data) {
         _gaq.push(['_trackEvent', 'Video', 'Start', txt,, false]);
       });
     });
   });
});