Skip to content

Instantly share code, notes, and snippets.

@rmpel
Last active July 9, 2020 22:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rmpel/ec500221be9f6e6969991cee1fac1e6a to your computer and use it in GitHub Desktop.
Save rmpel/ec500221be9f6e6969991cee1fac1e6a to your computer and use it in GitHub Desktop.
Local By Flywheel (unofficial) CLI for MacOS
#!/usr/bin/env bash
PRIMARY_LOCATION=~/Development
SECONDARY_LOCATION=/Volumes/Macintosh\ HD/Development
BROWSER=
CLOPS=
VERBOSE=true
SHOWHELP=false
SCHEME=http:
SQLPRO="$(ls -1d {~,}/Applications/Sequel\ Pro*.app 2>/dev/null | grep Applications | sort | head -n 1)"
LCLAPP="$(ls -1d {~,}/Applications/Local\ by\ Flywheel*.app 2>/dev/null | grep Applications | sort | head -n 1)"
DOCMAC="${LCLAPP}"/Contents/Resources/extraResources/virtual-machine/vendor/docker/osx/docker-machine
while [ "" != "$1" ]; do
case "$1" in
--ssl)
SCHEME=https:
;;
--silent)
VERBOSE=false
;;
-h|--help)
SHOWHELP=true
;;
-p|--project|--site)
SITE=$2
shift
;;
-s=*|--site=*)
SITE=${1#*=}
;;
-b|--browser)
_BROWSER="$2"
shift
;;
-b=*|--browser=*)
_BROWSER=${1#*=}
shift
;;
-ff|--firefox)
_BROWSER=Firefox
;;
-fd|--firefox-dev|--firefox-developer-edition)
_BROWSER=Firefox\ Developer\ Edition
;;
-c|--chrome)
_BROWSER=Google\ Chrome
;;
-cd|--chromium|--chrome-dev)
_BROWSER=Chromium
;;
-o|--opera)
_BROWSER=Opera
;;
-s|--safari)
_BROWSER=Safari
;;
*)
P=$1
[ ">" = "${P}" ] && P="'${P}'"
[ ">=" = "${P}" ] && P="'${P}'"
[ "<" = "${P}" ] && P="'${P}'"
[ "<=" = "${P}" ] && P="'${P}'"
[ "|" = "${P}" ] && P="'${P}'"
[ "" != "$OP" ] && CLOPS="${CLOPS} ${P}"
[ "" = "$OP" ] && OP=$1
;;
esac
shift;
done
CLOPS=${CLOPS## }
__local_get_browser() {
local BROWSER
# resolve browser
[ -d "$1" ] && [[ "$1" =~ \.app/?$ ]] && BROWSER="$1"
[ -d "/Applications/$1" ] && BROWSER="$1"
[ -d "/Applications/$1.app" ] && BROWSER="$1"
[ -d ~/"Applications/$1" ] && BROWSER="$1"
[ -d ~/"Applications/$1.app" ] && BROWSER="$1"
[ "" != "$BROWSER" ] && echo $BROWSER;
}
BROWSER="$(__local_get_browser "$_BROWSER")"
[ "" != "$_BROWSER" ] && [ "" = "$BROWSER" ] && echo "Browser ${_BROWSER} not installed, or not found." && exit 9
[ "true" = "$SHOWHELP" ] && OP=
if [ "${OP}" = "" ]; then
echo "Local By Flywheel is great, but sometimes you need to use the terminal, so, with this script"
echo $0
echo You can
echo ' '$(basename "$0") 'list List all sites'
echo ' '$(basename "$0") 'raw View all info Local has on this site'
echo ' '$(basename "$0") 'open Open the site in your default browser'
echo ' '$(basename "$0") 'mailhog Open the mailhog software for this site in your default browser'
echo ' '$(basename "$0") 'db Open Sequel Pro with the database of this site'
echo ' '$(basename "$0") 'ssh Open the docker shell of this site'
echo ' '$(basename "$0") 'ssh commandline Execute commandline in shell of this site'
echo ' '$(basename "$0") 'wp commandline Perform WP-CLI operation on site'
echo ' '$(basename "$0") 'wpdr Perform wp search-replace <current domain> <local domain>'
echo ""
echo You can use --site, --project or -p to specify a site, either by Name, ID or Path to operate on
echo You can use --browser or -b to specify a WebBrowser either by AppName or AppPath to use for \'open\' and \'mailhog\'
echo You can use --ssl to use https with operation \'open\' and \'wpdr\'
echo Browser shortcuts;
echo ' -ff or --firefox Firefox'
echo ' -fd or --firefox-dev or --firefox-developer-edition Firefox Developer Edition'
echo ' -c or --chrome Google Chrome'
echo ' -cd or --chrome-dev or --chromium Chromium'
echo ' -o or --opera Opera'
echo ' -s or --safari Safari'
echo ""
echo It should come as no surprise you need to be inside the folder structure of your Local site.
exit;
fi
[ "wp" = "${OP}" ] && VERBOSE=false
FLWL=/Applications/Local\ by\ Flywheel.app
[ ! -d "$FLWL" ] && FLWL=~/Applications/Local\ by\ Flywheel.app
[ ! -d "$FLWL" ] && FLWL=$(mdfind Local\ by\ Flywheel.app | egrep '\.app$' | head -n 1)
[ ! -d "$FLWL" ] && echo "Sorry, looks like Local by Flywheel is not installed." && exit 1;
CWD=$(pwd -P);
STATUS=$("${DOCMAC}" status local-by-flywheel)
if [ "vm" = "${OP}" ]; then
case "$CLOPS" in
start|restart)
[ "Running" != "$STATUS" ] && "${DOCMAC}" start local-by-flywheel || "${DOCMAC}" restart local-by-flywheel
;;
stop)
[ "Running" = "$STATUS" ] && "${DOCMAC}" stop local-by-flywheel
;;
esac
exit;
fi
[ "Running" != "$STATUS" ] && echo "Local Machine not running, attempting to wake it up" && "${DOCMAC}" start local-by-flywheel
__local_find_root () {
local DIR=$CWD
[ "" != "$1" ] && DIR="$1"
_DIR=$(echo "$DIR" | awk -F'/app/' '{print $1}')
[ "" != "$_DIR" ] && [ "$DIR" != "$_DIR" ] && DIR="$_DIR"
while [ "$DIR" != "" ] && [ "$DIR" != '.' ] && [ "$DIR" != "/" ] && [ ! -d "${DIR}/app" ]; do
DIR="$( dirname "$DIR" )"
echo "DEBUG: $DIR";
done;
echo "$DIR"
}
__local_get_ids() {
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $home=getenv("HOME"); $db=json_decode(file_get_contents("'${DB}'"));foreach($db as $i => $a){ print "$i "; }' | php
}
__local_get_id() {
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $home=getenv("HOME"); $db=json_decode(file_get_contents("'${DB}'"));foreach($db as $i => $a){ if (str_replace("~",$home,$a->path)=="'${1}'") { print $i; } }' | php
}
__local_get_id_by_name() {
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $home=getenv("HOME"); $db=json_decode(file_get_contents("'${DB}'"));foreach($db as $i => $a){ if (strtolower($a->name)==strtolower("'${1}'")) { print $i; } }' | php
}
__local_verify_id() {
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $home=getenv("HOME"); $db=json_decode(file_get_contents("'${DB}'"));foreach($db as $i => $a){ if (strtolower($i)==strtolower("'${1}'")) { print $i; } }' | php
}
__local_get_data() {
# $1 = ID, #2 = key
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $db=json_decode(file_get_contents("'${DB}'"));$a=$db->{"'${1}'"}; $result = $a->{"'${2}'"}; if (is_object($result)) {$result = $result->{"'${3}'"};} print $result;' | php | sed 's^~^'${HOME}'^g'
}
__local_fix_sites() {
# $1 = ID, #2 = key
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $db=json_decode(file_get_contents("'${DB}'")); foreach($db as &$site) { $site->path = realpath($site->path); } file_put_contents("'${DB}'", json_encode($db, 128));' | php
}
__local_fix_sites;
__local_get_docker() {
# $1 = key
DB=~/Library/Application\ Support/Local\ By\ Flywheel/dockerode-options.json
echo '<?php $db=json_decode(file_get_contents("'${DB}'"));$result=$db->{"'${1}'"}; print $result;' | php | sed 's^~^'${HOME}'^g'
}
__local_get_data_raw() {
# $1 = ID, #2 = key
DB=~/Library/Application\ Support/Local\ By\ Flywheel/sites.json
echo '<?php $db=json_decode(file_get_contents("'${DB}'"));$a=$db->{"'${1}'"}; print json_encode($a, JSON_PRETTY_PRINT);' | php
}
__local_site_status() {
# $1 = ID
DB=~/Library/Application\ Support/Local\ By\ Flywheel/site-statuses.json
echo '<?php $db=json_decode(file_get_contents("'${DB}'"));$a=$db->{"'${1}'"}; print $a;' | php
}
# $1: $SITE
__local_db_spf_generate() {
db=$(__local_get_data $1 mysql database);
dbu=$(__local_get_data $1 mysql user);
pwd=$(__local_get_data $1 mysql password);
prt=$(__local_get_data $1 ports MYSQL);
ip=$(__local_get_docker host);
site=$(__local_get_data $1 name);
echo '<?xml version=1.0 encoding=UTF-8?>
<!DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version=1.0>
<dict>
<key>ContentFilters</key>
<dict/>
<key>auto_connect</key>
<true/>
<key>data</key>
<dict>
<key>connection</key>
<dict>
<key>database</key>
<string>'$db'</string>
<key>host</key>
<string>'$ip'</string>
<key>name</key>
<string>Local by Flywheel - '$site'</string>
<key>password</key>
<string>'$pwd'</string>
<key>port</key>
<integer>'$prt'</integer>
<key>rdbms_type</key>
<string>mysql</string>
<key>sslCACertFileLocation</key>
<string></string>
<key>sslCACertFileLocationEnabled</key>
<integer>0</integer>
<key>sslCertificateFileLocation</key>
<string></string>
<key>sslCertificateFileLocationEnabled</key>
<integer>0</integer>
<key>sslKeyFileLocation</key>
<string></string>
<key>sslKeyFileLocationEnabled</key>
<integer>0</integer>
<key>type</key>
<string>SPTCPIPConnection</string>
<key>useSSL</key>
<integer>0</integer>
<key>user</key>
<string>'$dbu'</string>
</dict>
<key>session</key>
<dict/>
</dict>
<key>encrypted</key>
<false/>
<key>format</key>
<string>connection</string>
<key>queryFavorites</key>
<array/>
<key>queryHistory</key>
<array/>
<key>rdbms_type</key>
<string>mysql</string>
<key>version</key>
<integer>1</integer>
</dict>
</plist>
'
}
printTable() {
local -r delimiter="${1}"
local -r data="$(__table__removeEmptyLines "${2}")"
if [[ "${delimiter}" != '' && "$(__table__isEmptyString "${data}")" = 'false' ]]
then
local -r numberOfLines="$(wc -l <<< "${data}")"
if [[ "${numberOfLines}" -gt '0' ]]
then
local table=''
local i=1
for ((i = 1; i <= "${numberOfLines}"; i = i + 1))
do
local line=''
line="$(sed "${i}q;d" <<< "${data}")"
local numberOfColumns='0'
numberOfColumns="$(awk -F "${delimiter}" '{print NF}' <<< "${line}")"
# Add Line Delimiter
if [[ "${i}" -eq '1' ]]
then
table="${table}$(printf '%s#+' "$(__table__repeatString '#+' "${numberOfColumns}")")"
fi
# Add Header Or Body
table="${table}\n"
local j=1
for ((j = 1; j <= "${numberOfColumns}"; j = j + 1))
do
table="${table}$(printf '#| %s' "$(cut -d "${delimiter}" -f "${j}" <<< "${line}")")"
done
table="${table}#|\n"
# Add Line Delimiter
if [[ "${i}" -eq '1' ]] || [[ "${numberOfLines}" -gt '1' && "${i}" -eq "${numberOfLines}" ]]
then
table="${table}$(printf '%s#+' "$(__table__repeatString '#+' "${numberOfColumns}")")"
fi
done
if [[ "$(__table__isEmptyString "${table}")" = 'false' ]]
then
echo -e "${table}" | column -s '#' -t | awk '/^\+/{gsub(" ", "-", $0)}1'
fi
fi
fi
}
__table__removeEmptyLines() {
local -r content="${1}"
echo -e "${content}" | sed '/^\s*$/d'
}
__table__repeatString() {
local -r string="${1}"
local -r numberToRepeat="${2}"
if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
then
local -r result="$(printf "%${numberToRepeat}s")"
echo -e "${result// /${string}}"
fi
}
__table__isEmptyString() {
local -r string="${1}"
if [[ "$(__table__trimString "${string}")" = '' ]]
then
echo 'true' && return 0
fi
echo 'false' && return 1
}
__table__trimString() {
local -r string="${1}"
sed 's,^[[:blank:]]*,,' <<< "${string}" | sed 's,[[:blank:]]*$,,'
}
#debugging
# __local_find_root; exit;
# __local_get_id "$(__local_find_root)";exit;
if [ "list" = "${OP}" ]; then
printf "working...\r"
TABLE='SiteID,Status,Name,Path\n';
for SITE in $(__local_get_ids); do
TABLE=${TABLE}$SITE,$(__local_site_status $SITE),$(__local_get_data $SITE name),$(__local_get_data $SITE path)$'\n'
done
printTable , "$TABLE"
exit;
fi
if [ "" != "$SITE" ]; then
PRESET_SITE="$SITE"
SITE=$(__local_verify_id "$PRESET_SITE")
[ "" = "$SITE" ] && SITE=$(__local_get_id_by_name "$PRESET_SITE")
if [ "" = "$SITE" ] && [ -d "$PRESET_SITE" ]; then
PRESET_SITE="`cd "${PRESET_SITE}";pwd`";
SITE=$(__local_get_id "$PRESET_SITE" )
[ "" = "$SITE" ] && [ -d "$PRESET_SITE"/public ] && SITE=$(__local_get_id "$PRESET_SITE"/public )
[ "" = "$SITE" ] && [ -d "$PRESET_SITE"/app/public ] && SITE=$(__local_get_id "$PRESET_SITE"/app/public )
[ "" = "$SITE" ] && [ -d "$PRESET_SITE" ] && SITE=$(__local_get_id "$(__local_find_root "$PRESET_SITE")" )
PRESET_SITE="`cd "${PRESET_SITE}";pwd -P`";
SITE=$(__local_get_id "$PRESET_SITE" )
[ "" = "$SITE" ] && [ -d "$PRESET_SITE"/public ] && SITE=$(__local_get_id "$PRESET_SITE"/public )
[ "" = "$SITE" ] && [ -d "$PRESET_SITE"/app/public ] && SITE=$(__local_get_id "$PRESET_SITE"/app/public )
[ "" = "$SITE" ] && [ -d "$PRESET_SITE" ] && SITE=$(__local_get_id "$(__local_find_root "$PRESET_SITE")" )
fi
fi
[ "" = "$SITE" ] && SITE=$(__local_get_id "$(__local_find_root)" )
#debugging
# __local_get_data $SITE name;exit;
NAME=$(__local_get_data $SITE name);
[ "" = "$SITE" ] && echo "Not a Local site" && exit 2;
[ "" = "$NAME" ] && echo "Not a Local site" && exit 2;
STATUS=$(__local_site_status $SITE);
if [ "true" = "${VERBOSE}" ]; then
echo "Root: "$(__local_get_data $SITE path);
echo "Name: $NAME";
echo "SiteID: $SITE";
echo "Status: $STATUS"
fi
[ "halted" = "$STATUS" ] && echo "Please enable site in Local by Flywheel" && exit 3;
[ "raw" = "${OP}" ] && __local_get_data_raw $SITE && exit 0;
[ "open" = "${OP}" ] && [ "" != "$BROWSER" ] && open -a "$BROWSER" ${SCHEME}//$(__local_get_data $SITE domain) && exit 0;
[ "open" = "${OP}" ] && [ "" = "$BROWSER" ] && open ${SCHEME}//$(__local_get_data $SITE domain) && exit 0;
[ "ngrok" = "${OP}" ] && echo "ngrok not yet available" && exit 4;
[ "mailhog" = "${OP}" ] && [ "" != "$BROWSER" ] && open -a "$BROWSER" http://$(__local_get_data $SITE domain):$(__local_get_data $SITE ports MAILCATCHER) && exit 0;
[ "mailhog" = "${OP}" ] && [ "" = "$BROWSER" ] && open http://$(__local_get_data $SITE domain):$(__local_get_data $SITE ports MAILCATCHER) && exit 0;
[ "db" = "${OP}" ] && spf="$(__local_get_data $SITE path)"/sequel-pro.spf && __local_db_spf_generate $SITE > "$spf" && open -a "$SQLPRO" "$spf" && exit 0;
CONTAINER=$(__local_get_data $SITE container);
if [ "wpdr" = "${OP}" ]; then
OP=ssh
N=${SCHEME}//$(__local_get_data $SITE domain)
CLOPS="cd app/public"
CLOPS=" $CLOPS; D=\$(WP_ENV=local-by-flywheel wp --allow-root option get siteurl | sed -E 's@https?://(www\.)?@@') ; echo Base domain: https?://\(www.\)?\$D ; echo Replace with $N"
CLOPS=" $CLOPS; WP_ENV=local-by-flywheel wp --allow-root search-replace http://www.\$D '$N'"
CLOPS=" $CLOPS; WP_ENV=local-by-flywheel wp --allow-root search-replace https://www.\$D '$N'"
CLOPS=" $CLOPS; WP_ENV=local-by-flywheel wp --allow-root search-replace http://\$D '$N'"
CLOPS=" $CLOPS; WP_ENV=local-by-flywheel wp --allow-root search-replace https://\$D '$N'"
fi
if [ "wp" = "${OP}" ]; then
OP=ssh
CLOPS="cd app/public; WP_ENV=local-by-flywheel wp --allow-root $CLOPS"
fi
if [ "ssh" = "${OP}" ]; then
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://"$(__local_get_docker host)":"$(__local_get_docker port)
export DOCKER_CERT_PATH="$(dirname "$(__local_get_docker ca)")"
export DOCKER_MACHINE_NAME="$(basename "$(dirname "$(__local_get_docker ca)")")"
LINES=$(tput lines)
COLUMNS=$(tput cols)
echo -n -e "\033]0;Local: ${NAME}\007"
[ "" = "$CLOPS" ] && "${FLWL}/Contents/Resources/extraResources/virtual-machine/vendor/docker/osx/docker" exec -it -e LINES=$LINES -e COLUMNS=$COLUMNS $CONTAINER /bin/bash;
[ "" != "$CLOPS" ] && "${FLWL}/Contents/Resources/extraResources/virtual-machine/vendor/docker/osx/docker" exec -it -e LINES=$LINES -e COLUMNS=$COLUMNS $CONTAINER /bin/bash -c "$CLOPS";
echo -n -e "\033]0;\007"
fi
#if [ "move-to-primary" = "${OP}"]; then
# quit Local
# find current project root
# move data
# rename in json file
# restart Local
#fi
#if [ "move-to-secondary" = "${OP}"]; then
# quit Local
# find current project root
# move data
# rename in json file
# restart Local
#fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment