Skip to content

Instantly share code, notes, and snippets.

@sharmashivanand
Last active September 24, 2025 05:37
Show Gist options
  • Select an option

  • Save sharmashivanand/d6e7cd09826288434fca5afd157e3af1 to your computer and use it in GitHub Desktop.

Select an option

Save sharmashivanand/d6e7cd09826288434fca5afd157e3af1 to your computer and use it in GitHub Desktop.

Revisions

  1. sharmashivanand revised this gist Sep 24, 2025. 1 changed file with 52 additions and 29 deletions.
    81 changes: 52 additions & 29 deletions install_phpcbf.sh
    Original file line number Diff line number Diff line change
    @@ -1,34 +1,35 @@
    #!/usr/bin/env bash
    # Install phpcbf (via PHP_CodeSniffer) + WordPress Coding Standards globally.
    # Focus: phpcbf. Idempotent & non-destructive.
    # Install phpcbf/phpcs + WordPress Coding Standards + PHPCSExtra globally
    # Focus: phpcbf-first (auto-fixing). Safe to re-run. Non-destructive.

    set -euo pipefail

    log() { printf "\033[1;32m==>\033[0m %s\n" "$*"; }
    warn() { printf "\033[1;33m[warn]\033[0m %s\n" "$*"; }
    die() { printf "\033[1;31m[err]\033[0m %s\n" "$*" >&2; exit 1; }

    # 0) Requirements
    # --- 0) Requirements ---------------------------------------------------------
    command -v php >/dev/null 2>&1 || die "PHP not found. Install PHP and re-run."
    command -v composer >/dev/null 2>&1 || die "Composer not found. Install from https://getcomposer.org"

    # 1) Composer home & vendor/bin
    # --- 1) Resolve Composer home & vendor/bin -----------------------------------
    COMPOSER_HOME="$(composer global config home 2>/dev/null || true)"
    [ -n "${COMPOSER_HOME:-}" ] || die "Could not determine Composer home."
    [ -n "${COMPOSER_HOME:-}" ] || die "Could not determine Composer home (composer global config home)."
    VENDOR_BIN="$COMPOSER_HOME/vendor/bin"
    PHPCS_BIN="$VENDOR_BIN/phpcs"
    PHPCBF_BIN="$VENDOR_BIN/phpcbf"

    log "Composer home: $COMPOSER_HOME"
    log "Vendor bin: $VENDOR_BIN"

    # 2) Ensure vendor/bin on PATH now & later
    # --- 2) Ensure vendor/bin is on PATH now and persistently --------------------
    ensure_path() {
    case "${SHELL:-}" in
    */zsh) PROFILE="$HOME/.zshrc" ;;
    */fish) PROFILE="$HOME/.config/fish/config.fish" ;;
    *) PROFILE="$HOME/.bashrc" ;;
    esac

    if ! echo ":$PATH:" | grep -q ":$VENDOR_BIN:"; then
    if [[ "$PROFILE" = *fish* ]]; then
    mkdir -p "$(dirname "$PROFILE")"
    @@ -43,39 +44,56 @@ ensure_path() {
    }
    ensure_path

    # 3) Minimal install: PHPCS engine (phpcbf) + WPCS
    log "Installing/updating PHP_CodeSniffer (phpcbf/phpcs) + WPCS…"
    # --- 3) Install PHPCS (phpcs/phpcbf) + WPCS + PHPCSExtra ---------------------
    log "Installing/updating PHP_CodeSniffer (phpcbf/phpcs), WPCS, and PHPCSExtra…"
    # Clean up any old/bad plugin names silently
    composer global remove dealerdirect/phpcodesniffer-plugin >/dev/null 2>&1 || true

    composer global require \
    squizlabs/php_codesniffer:* \
    wp-coding-standards/wpcs:* \
    phpcsstandards/phpcsextra:^1.2 \
    phpcsstandards/phpcsutils:^1.0 \
    --no-interaction

    # 4) Register WPCS & set default standard to WordPress
    # --- 4) Register standards in installed_paths (WPCS + PHPCSExtra) ------------
    WPCS_PATH="$COMPOSER_HOME/vendor/wp-coding-standards/wpcs"
    [ -d "$WPCS_PATH" ] || die "WPCS not found at $WPCS_PATH (Composer install failed?)"

    EXISTING="$("$PHPCS_BIN" --config-show installed_paths 2>/dev/null | awk -F': ' 'NF>1{print $2}')"
    TARGETS="$WPCS_PATH"
    if [ -n "${EXISTING:-}" ] && [ "$EXISTING" != "." ] && [ "$EXISTING" != "null" ]; then
    ALL="$EXISTING,$TARGETS"
    DEDUP="$(echo "$ALL" | tr ',' '\n' | awk 'NF' | awk '!seen[$0]++' | paste -sd',' -)"
    "$PHPCS_BIN" --config-set installed_paths "$DEDUP" >/dev/null
    else
    "$PHPCS_BIN" --config-set installed_paths "$TARGETS" >/devnull
    fi
    EXTRA_PATH="$COMPOSER_HOME/vendor/phpcsstandards/phpcsextra"
    [ -d "$WPCS_PATH" ] || die "WPCS not found at $WPCS_PATH (Composer install failed?)."
    [ -d "$EXTRA_PATH" ] || die "PHPCSExtra not found at $EXTRA_PATH (Composer install failed?)."

    merge_installed_paths() {
    local existing targets all dedup
    existing="$("$PHPCS_BIN" --config-show installed_paths 2>/dev/null | awk -F': ' 'NF>1{print $2}')"
    targets="$WPCS_PATH,$EXTRA_PATH"

    if [ -n "${existing:-}" ] && [ "$existing" != "." ] && [ "$existing" != "null" ]; then
    all="$existing,$targets"
    else
    all="$targets"
    fi

    # >>> SET DEFAULT STANDARD TO WORDPRESS <<<
    # Deduplicate, keep order of first occurrence
    dedup="$(echo "$all" | tr ',' '\n' | awk 'NF' | awk '!seen[$0]++' | paste -sd',' -)"
    "$PHPCS_BIN" --config-set installed_paths "$dedup" >/dev/null
    }
    merge_installed_paths

    # Set default standard to WordPress (so phpcbf runs without flags)
    "$PHPCS_BIN" --config-set default_standard WordPress >/dev/null || true

    # 5) Add wpcbf helper
    # --- 5) Add a convenience wrapper: wpcbf ------------------------------------
    USER_BIN="${HOME}/.local/bin"
    mkdir -p "$USER_BIN"
    WPCBF="$USER_BIN/wpcbf"
    cat > "$WPCBF" <<'WRAP'
    #!/usr/bin/env bash
    set -euo pipefail
    # wpcbf: WordPress-first auto-fixer (phpcbf wrapper)
    # Usage:
    # wpcbf # fix current dir
    # wpcbf file.php # fix a file
    # wpcbf src tests # fix multiple paths
    ARGS=("$@")
    if [ ${#ARGS[@]} -eq 0 ]; then ARGS=("."); fi
    exec phpcbf \
    @@ -87,7 +105,7 @@ exec phpcbf \
    WRAP
    chmod +x "$WPCBF"

    # Ensure ~/.local/bin on PATH
    # Ensure ~/.local/bin is on PATH too
    if ! echo ":$PATH:" | grep -q ":$USER_BIN:"; then
    case "${SHELL:-}" in
    */fish)
    @@ -105,7 +123,7 @@ if ! echo ":$PATH:" | grep -q ":$USER_BIN:"; then
    esac
    fi

    # 6) Sanity
    # --- 6) Sanity checks --------------------------------------------------------
    log "Sanity check:"
    "$PHPCBF_BIN" --version || true
    "$PHPCS_BIN" -i || true
    @@ -116,14 +134,19 @@ cat <<'NOTE'
    Done. You now have:
    • phpcbf installed globally (via PHP_CodeSniffer)
    • WordPress Coding Standards registered
    • WordPress Coding Standards + PHPCSExtra registered globally
    • DEFAULT STANDARD set to: WordPress
    • wpcbf helper command (WordPress preset):
    wpcbf # auto-fix current directory
    wpcbf path/… # auto-fix specific paths
    • 'wpcbf' helper command for quick fixing
    Quick start:
    wpcbf .
    phpcs --config-show
    phpcs -i
    If PATH doesn't refresh immediately, run:
    If your editor reports "spawn phpcbf ENOENT":
    export PATH="$COMPOSER_HOME/vendor/bin:$HOME/.local/bin:$PATH"
    # Then point your editor’s "phpcbf executablePath" to:
    # $COMPOSER_HOME/vendor/bin/phpcbf
    NOTE

    log "All set for phpcbf-first WordPress fixing."
  2. sharmashivanand created this gist Sep 24, 2025.
    129 changes: 129 additions & 0 deletions install_phpcbf.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,129 @@
    #!/usr/bin/env bash
    # Install phpcbf (via PHP_CodeSniffer) + WordPress Coding Standards globally.
    # Focus: phpcbf. Idempotent & non-destructive.

    set -euo pipefail

    log() { printf "\033[1;32m==>\033[0m %s\n" "$*"; }
    warn() { printf "\033[1;33m[warn]\033[0m %s\n" "$*"; }
    die() { printf "\033[1;31m[err]\033[0m %s\n" "$*" >&2; exit 1; }

    # 0) Requirements
    command -v php >/dev/null 2>&1 || die "PHP not found. Install PHP and re-run."
    command -v composer >/dev/null 2>&1 || die "Composer not found. Install from https://getcomposer.org"

    # 1) Composer home & vendor/bin
    COMPOSER_HOME="$(composer global config home 2>/dev/null || true)"
    [ -n "${COMPOSER_HOME:-}" ] || die "Could not determine Composer home."
    VENDOR_BIN="$COMPOSER_HOME/vendor/bin"
    PHPCS_BIN="$VENDOR_BIN/phpcs"
    PHPCBF_BIN="$VENDOR_BIN/phpcbf"

    log "Composer home: $COMPOSER_HOME"
    log "Vendor bin: $VENDOR_BIN"

    # 2) Ensure vendor/bin on PATH now & later
    ensure_path() {
    case "${SHELL:-}" in
    */zsh) PROFILE="$HOME/.zshrc" ;;
    */fish) PROFILE="$HOME/.config/fish/config.fish" ;;
    *) PROFILE="$HOME/.bashrc" ;;
    esac
    if ! echo ":$PATH:" | grep -q ":$VENDOR_BIN:"; then
    if [[ "$PROFILE" = *fish* ]]; then
    mkdir -p "$(dirname "$PROFILE")"
    grep -q "$VENDOR_BIN" "$PROFILE" 2>/dev/null || echo "set -Ux PATH $VENDOR_BIN \$PATH" >> "$PROFILE"
    warn "Added vendor/bin to Fish PATH. Restart shell or run: exec fish"
    else
    grep -q "$VENDOR_BIN" "$PROFILE" 2>/dev/null || echo "export PATH=\"$VENDOR_BIN:\$PATH\"" >> "$PROFILE"
    export PATH="$VENDOR_BIN:$PATH"
    warn "Added vendor/bin to PATH. Restart shell or run: export PATH=\"$VENDOR_BIN:\$PATH\""
    fi
    fi
    }
    ensure_path

    # 3) Minimal install: PHPCS engine (phpcbf) + WPCS
    log "Installing/updating PHP_CodeSniffer (phpcbf/phpcs) + WPCS…"
    composer global remove dealerdirect/phpcodesniffer-plugin >/dev/null 2>&1 || true
    composer global require \
    squizlabs/php_codesniffer:* \
    wp-coding-standards/wpcs:* \
    --no-interaction

    # 4) Register WPCS & set default standard to WordPress
    WPCS_PATH="$COMPOSER_HOME/vendor/wp-coding-standards/wpcs"
    [ -d "$WPCS_PATH" ] || die "WPCS not found at $WPCS_PATH (Composer install failed?)"

    EXISTING="$("$PHPCS_BIN" --config-show installed_paths 2>/dev/null | awk -F': ' 'NF>1{print $2}')"
    TARGETS="$WPCS_PATH"
    if [ -n "${EXISTING:-}" ] && [ "$EXISTING" != "." ] && [ "$EXISTING" != "null" ]; then
    ALL="$EXISTING,$TARGETS"
    DEDUP="$(echo "$ALL" | tr ',' '\n' | awk 'NF' | awk '!seen[$0]++' | paste -sd',' -)"
    "$PHPCS_BIN" --config-set installed_paths "$DEDUP" >/dev/null
    else
    "$PHPCS_BIN" --config-set installed_paths "$TARGETS" >/devnull
    fi

    # >>> SET DEFAULT STANDARD TO WORDPRESS <<<
    "$PHPCS_BIN" --config-set default_standard WordPress >/dev/null || true

    # 5) Add wpcbf helper
    USER_BIN="${HOME}/.local/bin"
    mkdir -p "$USER_BIN"
    WPCBF="$USER_BIN/wpcbf"
    cat > "$WPCBF" <<'WRAP'
    #!/usr/bin/env bash
    set -euo pipefail
    # wpcbf: WordPress-first auto-fixer (phpcbf wrapper)
    ARGS=("$@")
    if [ ${#ARGS[@]} -eq 0 ]; then ARGS=("."); fi
    exec phpcbf \
    --standard=WordPress \
    --extensions=php,php5,phtml \
    --report=summary \
    --parallel="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" \
    "${ARGS[@]}"
    WRAP
    chmod +x "$WPCBF"

    # Ensure ~/.local/bin on PATH
    if ! echo ":$PATH:" | grep -q ":$USER_BIN:"; then
    case "${SHELL:-}" in
    */fish)
    PROFILE="$HOME/.config/fish/config.fish"
    mkdir -p "$(dirname "$PROFILE")"
    grep -q "$USER_BIN" "$PROFILE" 2>/dev/null || echo "set -Ux PATH $USER_BIN \$PATH" >> "$PROFILE"
    warn "Added $USER_BIN to Fish PATH. Restart shell or run: exec fish"
    ;;
    *)
    PROFILE="${PROFILE:-$HOME/.bashrc}"
    grep -q "$USER_BIN" "$PROFILE" 2>/dev/null || echo "export PATH=\"$USER_BIN:\$PATH\"" >> "$PROFILE"
    export PATH="$USER_BIN:$PATH"
    warn "Added $USER_BIN to PATH. Restart shell or run: export PATH=\"$USER_BIN:\$PATH\""
    ;;
    esac
    fi

    # 6) Sanity
    log "Sanity check:"
    "$PHPCBF_BIN" --version || true
    "$PHPCS_BIN" -i || true
    "$PHPCS_BIN" --config-show default_standard | sed 's/^/ /'

    cat <<'NOTE'
    Done. You now have:
    • phpcbf installed globally (via PHP_CodeSniffer)
    • WordPress Coding Standards registered
    • DEFAULT STANDARD set to: WordPress
    • wpcbf helper command (WordPress preset):
    wpcbf # auto-fix current directory
    wpcbf path/… # auto-fix specific paths
    If PATH doesn't refresh immediately, run:
    export PATH="$COMPOSER_HOME/vendor/bin:$HOME/.local/bin:$PATH"
    NOTE

    log "All set for phpcbf-first WordPress fixing."