This is Ryan’s pseudo public cheat sheet. It gets updated sporadically with things that he forgets.

JS arrow functions

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Sass

sass --watch style.scss:style.min.css --style compressed

Switch PHP versions

sudo update-alternatives --set php /usr/bin/php7.4

Custom wp_nav_menu() without a walker

Walker classes are a pain in the butt and non-intuitive. This allows you to create a simple menu without the clutter.
The title seems to vary depending on if it matches the post title or not.

<?php

$menu_items = wp_get_nav_menu_items( 'Main Menu' );
foreach ( $menu_items as $key => $menu_item ) {
	if ( isset( $menu_item->title ) ) {
		$title = $menu_item->title;
	} else {
		$title = $menu_item->post_title;
	}

	echo "\n\t\t";
	echo '<li><a href="' . esc_url( $menu_item->url ) . '" title="' . esc_attr( $menu_item->post_title ) . '">' . esc_html( $title ) . '</a></li>';
}

Convert jpg to webp

sudo apt install webp
#!/bin/bash
clear

i=0;
for filename in *.jpg;
do
	echo $filename": "$i;
	fileslug=${filename::-4}
	cwebp $filename -o $fileslug.webp

	i=$((i + 1))
done

Detecting a specific page root via PHP

Pages like /search/var/ or /search/?var=something will be detected by this.

<?php

$request_uri = filter_input( INPUT_SERVER, 'REQUEST_URI' );
$root_path   = '/search/';
$root_length = strlen( $root_path );
if ( $root_path === mb_substr( $request_uri, 0, $root_length ) ) {
	echo 'This is that page';
	die;
}

Maybe allows for auto-SFTP with password

sshpass -p 'somepasswordhere' sftp -r 2020/* something@sftp.somethung.com:/public_html/wp-content/uploads/2020/

Diff between two directories

diff -qr before/public_html/ after/public_html/ > diff.txt

Migrating WordPress database

wp search-replace 'domain.com' 'example.com' --skip-columns=guid --all-tables;
wp search-replace 'https://example.com' 'http://example.com' --skip-columns=guid --all-tables;
wp search-replace 'https:\/\/example.com' 'http:\/\/example.com' --skip-columns=guid --all-tables;
grep -rl domain.com . | xargs sed -i 's/domain.com/example.com/g';
wp transient delete --all;

REQUEST_URI

In PHP, do not access directly, use this instead:

<?php filter_input( INPUT_SERVER, 'REQUEST_URI' ); ?>
<?php
$get = filter_input( INPUT_GET, 'strattic-search-refresh' );
if ( isset( $get ) ) {
	// Do something here.
}
?>

Bail out if on specific URL (and ignoring sub-paths/query vars)

<php
$request_uri = filter_input( INPUT_SERVER, 'REQUEST_URI' );
$path        = '/somepath/';
if ( $path !== substr( $request_uri, 0, strlen( $path ) ) ) {
	return;
}

Unzip specific folder

unzip dump.zip 'wp-content/uploads/2017/*' -d public_html/wp-content/uploads/2017/

Unzip to a specific folder

unzip backup.zip -d public_html/;

Zip specific folder

zip -r file.zip /directory_name

rsync

Copy all files in remote directory to current local directory.

rsync -chavzP -e "ssh -p 22" username@somehost.whatever:/var/www/html/ ./

Curl with http auth

curl -u username:password -I https://domain.com

Background terminal process

If your program is already running you can pause it with Ctrl-Z, pull it into the background with bg and then disown it, like this (copy/paste them in so that they’re entered before the task pops to foreground again):

bg;
disown;
exit;

SFTP command line

sftp user@bla.com
get -r public_html/
put -r *

– uploading
then use the “background terminal process” tip above if you need to shut the window whilst the transfer is happening.

MySQL migrations

Fixes weird encoding problems. I have no idea why this is like this, why it is only necessary sometimes or why they’re just not set to normal UTF-8 by default. And I have no idea what the other UTF-8’s even are. Basically I know nothing about this, just that changing these strings fixes problems on import:P

sed -i 's/utf8mb4/utf8/g' your_file.sql
sed -i 's/utf8_unicode_ci/utf8_general_ci/g' your_file.sql
sed -i 's/utf8_unicode_520_ci/utf8_general_ci/g' your_file.sql

JS entities

This decodes HTML entities in JavaScript. Super useful if you need to get rid of HTML entities from your content. Inserting them into a generated element automatically converts them for you.

/**
 * Decodes HTML and converts entities back to their real form.
 * 
 * @param string html The encoded text.
 * @return string html The decoded text without entities.
 */
function decode_html( html ) {
	var txt       = document.createElement( 'textarea' );
	txt.innerHTML = html;
	return txt.value;
}

JS logger – only shows in dev environments

/**
 * Console logger.
 * Only logs when in dev environments.
 *
 * @param string text The string to log.
 */
function log( text ) {

	if (
		'domain.com' === window.location.hostname
		||
		'www.domain.com' === window.location.hostname
	) {
		return; // Do nothing if on any of the above domains.
	}

	console.log( text );
}

ffmpeg

Concatenate all files in folder together (make sure file names are in order first):

ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4

Reencode with keyframe every 10 frames, for editing

ffmpeg -i GH012185.MP4 -vcodec libx264 -x264-params keyint=10:scenecut=0 -acodec copy 1.mp4

Bash for reencoding every keyframe ….

#!/bin/bash

for filePath in kathmandu-videos/*.MP4; do
	[ -e "$filePath" ] || continue

	fileName=$(basename -- "$filePath")
	extension="${fileName##*.}"
	name="${fileName%.*}"

	ffmpeg -i kathmandu-videos/"$name.$extension" -vcodec libx264 -x264-params keyint=10:scenecut=0 -acodec copy kathmandu-videos-reencoded/"$name".mp4

done

Compress video

ffmpeg -i filename.mp4 -b:v 7000k -vcodec h264 -acodec aac filename-compressed.mp4

Stabilise a file

ffmpeg -i shaky.mp4 -vf vidstabdetect=stepsize=6:shakiness=8:accuracy=9:result=transform_vectors.trf -f null -
ffmpeg -i shaky.mp4 -vf vidstabtransform=input=transform_vectors.trf:zoom=1:smoothing=30,unsharp=5:5:0.8:3:3:0.4 -vcodec libx264 -preset slow -tune film -crf 18 -acodec copy stabilised.mp4

increase brightness

ffmpeg -i 71.MP4 -vf eq=brightness=0.2 -c:a copy 71.mp4

Increase brightness, saturation and contrast

ffmpeg -i input.mp4 -vf eq=brightness=0.2:saturation=1.5:contrast=1.3 -c:a copy output.mp4

flip vertical

ffmpeg -i 58b.mp4 -vf "transpose=2,transpose=2" 58d.mp4

flip vertical – with reencode with keyframe every 10 frames, for editing

ffmpeg -i kathmandu-videos-reencoded/GH012364.mp4 -vf "transpose=2,transpose=2" -vcodec libx264 -x264-params keyint=10:scenecut=0 -acodec copy kathmandu-clips/day8-walking-7.mp4

Concatenating lots of files:

ffmpeg -i 'concat:1.m2v|2.m2v|3.m2v|4.m2v|5.m2v|6.m2v|7.m2v|8.m2v|9.m2v|10.m2v|11.m2v|12.m2v|13.m2v|14.m2v|15.m2v|16.m2v|17.m2v|18.m2v|19.m2v|20.m2v|21.m2v|22.m2v|23.m2v|24.m2v|25.m2v|26.m2v|27.m2v|28.m2v|29.m2v|30.m2v|31.m2v|32.m2v|33.m2v|34.m2v|35.m2v|36.m2v|37.m2v|38.m2v|39.m2v|40.m2v|41.m2v|42.m2v|43.m2v|44.m2v|45.m2v|46.m2v|47.m2v|48.m2v|49.m2v|50.m2v|51.m2v|52.m2v|53.m2v|54.m2v|55.m2v|56.m2v|57.m2v|58.m2v|59.m2v|60.m2v|61.m2v|62.m2v|63.m2v|64.m2v|65.m2v|66.m2v|67.m2v|68.m2v|69.m2v|70.m2v|71.m2v|72.m2v|73.m2v|74.m2v|75.m2v|76.m2v|77.m2v|78.m2v|79.m2v|80.m2v|81.m2v|82.m2v|83.m2v|84.m2v' -vcodec libx264 output.m2v

slow down

ffmpeg -i 86.mp4 -filter:v "setpts=0.3*PTS" 86b.mp4

crop to 1080p

ffmpeg -i 10.mp4 -filter:v "crop=1920:1080:0:0" 10b.mp4

Zoom into a section of the screen

ffmpeg -i x.MP4 -vf "scale=2*iw:-1, crop=iw/4:ih/4:27000:1300" x3.MP4

Clip the first 1 second and keep the five seconds after that

ffmpeg -i long.mp4 -ss 00:00:01.0 -c copy -t 00:00:5.0 short.mp4

Rotate 180 degrees

ffmpeg -i a.mp4 -vf "transpose=2,transpose=2" b.mp4

Rotate 90 degrees
0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip

ffmpeg -i a.mp4 -vf "transpose=1" b.mp4

Lossless .mkv codec:

-c:v libx264 -preset ultrafast -crf 0
ffmpeg -i x.mp4 -ss 00:01:25.0 -c copy -t 01:08:0.0 x1.mp4
ffmpeg -i x.ogg -ss 00:00:40.8 -c copy -t 01:08:0.0 x1.ogg

Extract audio

ffmpeg -i x1.mp4 -vn -acodec copy x2.aac

Merge two audios together

ffmpeg -i x1.ogg -i x2.aac  -filter_complex amerge -c:a libmp3lame -q:a 4 x3.mp3

Merge audio and video together

ffmpeg -i x1.mp4 -i x3.mp3 -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a:0 x-f2.mp4

Trim to suit (start at 41 seconds, and total length is 1 min 8 secs)

ffmpeg -i x-f2.mp4 -ss 00:00:41.0 -c copy -t 01:08:0.0 x-f3.mp4

Compress file for upload

ffmpeg -i x-f4.mp4 -b:v 7000k -vcodec h264 -acodec aac x-compressed.mp4

Server config

https://geek.hellyer.kiwi/tools/server-setup/

PDF Unite

pdfunite belfast-ryanair1.pdf belfast-ryanair2.pdf belfast-ryanair.pdf

Compressing images

* `sudo apt-get install jpegoptim`
* `sudo apt-get install optipng`

** Batch process **
* `jpegoptim /srv/www/uploads/*.jpg`
* `optipng /srv/www/uploads/*.png`
* iterate through every subdirectory of the current folder:
* `find -type f -name “*.jpg” -exec jpegoptim –strip-all {} \;`
* `find -type f -name “*.jpeg” -exec jpegoptim –strip-all {} \;`
* `find -type f -name “*.png” -exec optpng {} \;`

** Copy all the images out of a directory after compression (for copying back to server conveniently).
* `find imagetest/ -type f \( -iname ‘*.jpg’ -o -iname ‘*.png’ \) -print0 |xargs -0 tar c |(cd imagetestimages ; tar x)`
*

** Apply JPEG compression **
* `jpegoptim -m75 /srv/www/uploads/*.jpg`

** Limiting image width using ImageMagick **
mogrify -resize ‘600×400>’ *.jpg

Resetting a Git branch

This is useful for when you get the error “Your branch is ahead of ‘origin/master’ by 3 commits.
“.

# Loop through every file and process the ones with relevant image extensions.
for FILE in $(find_files .); do

FILEWITHOUTDOT=”${FILE:1}”

NAME=`echo “$FILEWITHOUTDOT” | cut -d’.’ -f1`
EXTENSION=`echo “$FILEWITHOUTDOT” | cut -d’.’ -f2`

if [ “$EXTENSION” = “jpg” ]; then
echo $FILE
jpegoptim $FILE
elif [ “$EXTENSION” = “png” ]; then
echo $FILE
optipng $FILE
fi

done

echo ” ”
echo “COMPLETE!”

git reset --hard origin/master

Git diff via Meld

git difftool -d qa feature/inactive_site_dialog

WordPress debug log

define(‘WP_DEBUG_LOG’, true);
define(‘WP_DEBUG’, true);
Sticks errors into
/wp-content/debug.log

BtSync

# sudo dpkg-reconfigure btsync

SCP

Use this for moving complete folders between servers:

scp -r -P 22 remoteuser@thehostname:/remote_path/html/ /local_path/html/

Manually creating excerpts

Use wp_trim_words(). Do NOT use wp_trim_excerpt().
http://codex.wordpress.org/Function_Reference/wp_trim_words

Using Grunt

  1. package.json and Gruntfile.js needed
  2. Install each module … sudo npm install grunt-wp-i18n
  3. (If you don’t have the module in your package.json file) Add the module to “node_modules” … sudo npm install grunt-wp-i18n --save-dev
  4. Install all modules in the package.json file … sudo npm install
  5. This installs a bunch of stuff it seems … sudo npm install load-grunt-tasks --save-dev
  6. I think you need to run this before Grunt becomes useful … npm install -g grunt-cli
  7. Actually run a command … sudo grunt makepot
  8. Add this to grunt.js to run multiple commands at once … grunt.registerTask('default', ['jsvalidate','makepot','jshint']);

sed

sed -i 's/before_/after_/g' /path/file.sql

Add a Git submodule

git submodule add git@github.com:ryanhellyer/xxx.git
git submodule init
git submodule update

Create MySQL database

mysql -u root -p66536653 -h localhost -e "create database dbname";

Get diff file from SVN

svn diff -r r101 > diff-r102.txt

Between two revisions:
svn diff -r 157:158 > diff-r158.txt

Switching and merging

svn switch --ignore-ancestry ^/trunk .

svn switch --ignore-ancestry ^/branches/staging .

svn merge -c 173 ^/trunk

Info from specific revision

svn log -v -r 118 https://svn.ryan.hellyer.kiwi/

This will provide output like the following:

R118 | rhellyer | 2014-02-27 08:58:50 +0100 (Do, 27 Feb 2014) | 1 line
Changed paths:
   M /branches/staging
   M /branches/staging/css/global.css
   M /branches/staging/js/scripts.js

Merging CSS and JS changes from trunk R118 into staging

// Checkout specific revision

svn co -r <revision_you_like> repo_url out_folder_name

ie: svn co -r 138 https://svn.ryan.hellyer.kiwi/projectname  .

 

Bash

http://www.tomjn.com/531/wordpress-bash-magic/

Model .gitignore

*.sass-cache
pingdom.php
wp-config.php
wp-content/upgrade
.htaccess
wp-content/uploads
/wp-content/debug.log
/migration/error.log
*.sql.gz

# OS or Editor folders
/.idea/
.DS_Store
.cache
.project
.settings
.tmproj
nbproject
Thumbs.db
.vim
/wp-content/cache/
/wp-content/plugins/p3-profiler
/wp-content/mu-plugins/p3-profiler.php

/nginx.conf

Fix file permissions/ownership

Run from current directory.

sudo chown ryan:www-data * -R;
sudo find . -type d -exec chmod 755 {} \;
sudo find . -type f -exec chmod 644 {} \;

Pull img src’s from HTML

<?php
preg_match_all( '/<img[^>]+>/i', $html, $imgTags ); 
for ( $i = 0; $i < count( $imgTags[0] ); $i++ ) {
	preg_match( '/src="([^"]+)/i', $imgTags[0][$i], $imgage );
	$result[] = str_ireplace( 'src="', '',  $imgage[0] );
}
?>

Setting variables – shorthand

Useful for setting variables without dicking around longhand.

$type = isset( $option['type'] ) ? $option['type'] : '';

Crude dump of code for rewrite rules

	/**
	 * Class constructor.
	 */
	public function __construct() {

		// Load the parent constructor
		parent::__construct();

		add_action( 'init', array( $this, 'rewrites' ) );
		add_filter( 'locale', array( $this, 'switch_lang' ) );

		// Add query var for 'lang'
		add_filter(
			'query_vars',
			function( $vars ) {
				$vars[] = 'lang';
				return $vars;
			}
		);
	}

	/**
	 * Switch the language.
	 */
	public function switch_lang( $lang ) {

		// Grab lang to use
		$request_uri_bits = explode( '/', $_SERVER['REQUEST_URI'] ); // Split up URI
		$request_uri_bits = array_filter( $request_uri_bits ); // Remove empty values
		$lang_slug        = end( $request_uri_bits ); // Grab last string
		$lang_slug = get_query_var( 'lang' );

		// Grab the ISO
		foreach( $this->langs as $iso => $language ) {
			if ( $language['slug'] == $lang_slug ) {
				$lang = $iso;
			}
		}

		if ( ! isset( $lang ) ) {
			return; // Bail out since language not set
		} else {

			// Change language based on slug used
			return $lang;
		}

	}

	/**
	 * Add rewrite rules.
	 */
	public function rewrites() {
		add_rewrite_rule( 'questionnaire/([^/]+)/([^/]+)/?$', 'index.php?questionnaire=$matches[1]&lang=$matches[2]', 'top' );
	}

Redis

To find out Redis stats, keys used, memory resources used etc.

# redis-cli info

Asynchronous http requests in PHP

/**
 * Asynchronous curl request.
 *
 * From https://stackoverflow.com/questions/124462/how-to-make-asynchronous-http-requests-in-php.
 */
function async_curl( $background_process = '' ) {

	$ch = curl_init( $background_process );
	curl_setopt_array(
		$ch,
		array(
			CURLOPT_HEADER         => 0,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_NOSIGNAL       => 1, //to timeout immediately if the value is < 1000 ms. CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute.
			CURLOPT_VERBOSE        => 1,
			CURLOPT_HEADER         => 1
		)
	);
	$out = curl_exec( $ch );

	curl_close( $ch );

	return true;
}