From 2e7fe8ed4f0888496ee73e551c4116c430fda5d6 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <230051081+jmiller-moko@users.noreply.github.com> Date: Tue, 24 Mar 2026 10:36:22 -0500 Subject: [PATCH] chore: add Makefile from MokoStandards --- Makefile | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ec94cc9 --- /dev/null +++ b/Makefile @@ -0,0 +1,333 @@ +# Makefile for Joomla Extensions +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# +# This is a reference Makefile for building Joomla extensions. +# Copy this to your repository root as "Makefile" and customize as needed. +# +# Supports: Modules, Plugins, Components, Packages, Templates + +# ============================================================================== +# CONFIGURATION - Customize these for your extension +# ============================================================================== + +# Extension Configuration +EXTENSION_NAME := mokoexample +EXTENSION_TYPE := module +# Options: module, plugin, component, package, template +EXTENSION_VERSION := 1.0.0 + +# Module Configuration (for modules only) +MODULE_TYPE := site +# Options: site, admin + +# Plugin Configuration (for plugins only) +PLUGIN_GROUP := system +# Options: system, content, user, authentication, etc. + +# Directories +SRC_DIR := . +BUILD_DIR := build +DIST_DIR := dist +DOCS_DIR := docs + +# Joomla Installation (for local testing - customize paths) +JOOMLA_ROOT := /var/www/html/joomla +JOOMLA_VERSION := 4 + +# Tools +PHP := php +COMPOSER := composer +NPM := npm +PHPCS := vendor/bin/phpcs +PHPCBF := vendor/bin/phpcbf +PHPUNIT := vendor/bin/phpunit +ZIP := zip + +# Coding Standards +PHPCS_STANDARD := Joomla + +# Colors for output +COLOR_RESET := \033[0m +COLOR_GREEN := \033[32m +COLOR_YELLOW := \033[33m +COLOR_BLUE := \033[34m +COLOR_RED := \033[31m + +# ============================================================================== +# TARGETS +# ============================================================================== + +.PHONY: help +help: ## Show this help message + @echo "$(COLOR_BLUE)╔════════════════════════════════════════════════════════════╗$(COLOR_RESET)" + @echo "$(COLOR_BLUE)║ Joomla Extension Makefile ║$(COLOR_RESET)" + @echo "$(COLOR_BLUE)╚════════════════════════════════════════════════════════════╝$(COLOR_RESET)" + @echo "" + @echo "Extension: $(EXTENSION_NAME) ($(EXTENSION_TYPE)) v$(EXTENSION_VERSION)" + @echo "" + @echo "$(COLOR_GREEN)Available targets:$(COLOR_RESET)" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " $(COLOR_BLUE)%-20s$(COLOR_RESET) %s\n", $$1, $$2}' + @echo "" + @echo "$(COLOR_YELLOW)Quick Start:$(COLOR_RESET)" + @echo " 1. make install-deps # Install dependencies" + @echo " 2. make build # Build extension package" + @echo " 3. make test # Run tests" + @echo "" + +.PHONY: install-deps +install-deps: ## Install all dependencies (Composer + npm) + @echo "$(COLOR_BLUE)Installing dependencies...$(COLOR_RESET)" + @if [ -f "composer.json" ]; then \ + $(COMPOSER) install; \ + echo "$(COLOR_GREEN)✓ Composer dependencies installed$(COLOR_RESET)"; \ + fi + @if [ -f "package.json" ]; then \ + $(NPM) install; \ + echo "$(COLOR_GREEN)✓ npm dependencies installed$(COLOR_RESET)"; \ + fi + +.PHONY: update-deps +update-deps: ## Update all dependencies + @echo "$(COLOR_BLUE)Updating dependencies...$(COLOR_RESET)" + @if [ -f "composer.json" ]; then \ + $(COMPOSER) update; \ + echo "$(COLOR_GREEN)✓ Composer dependencies updated$(COLOR_RESET)"; \ + fi + @if [ -f "package.json" ]; then \ + $(NPM) update; \ + echo "$(COLOR_GREEN)✓ npm dependencies updated$(COLOR_RESET)"; \ + fi + +.PHONY: lint +lint: ## Run PHP linter (syntax check) + @echo "$(COLOR_BLUE)Running PHP linter...$(COLOR_RESET)" + @find . -name "*.php" ! -path "./vendor/*" ! -path "./node_modules/*" ! -path "./$(BUILD_DIR)/*" \ + -exec $(PHP) -l {} \; | grep -v "No syntax errors" || true + @echo "$(COLOR_GREEN)✓ PHP linting complete$(COLOR_RESET)" + +.PHONY: phpcs +phpcs: ## Run PHP CodeSniffer (Joomla standards) + @echo "$(COLOR_BLUE)Running PHP CodeSniffer...$(COLOR_RESET)" + @if [ -f "$(PHPCS)" ]; then \ + $(PHPCS) --standard=$(PHPCS_STANDARD) --extensions=php --ignore=vendor,node_modules,$(BUILD_DIR) .; \ + else \ + echo "$(COLOR_YELLOW)⚠ PHP CodeSniffer not installed. Run: make install-deps$(COLOR_RESET)"; \ + fi + +.PHONY: phpcbf +phpcbf: ## Fix coding standards automatically + @echo "$(COLOR_BLUE)Running PHP Code Beautifier...$(COLOR_RESET)" + @if [ -f "$(PHPCBF)" ]; then \ + $(PHPCBF) --standard=$(PHPCS_STANDARD) --extensions=php --ignore=vendor,node_modules,$(BUILD_DIR) .; \ + echo "$(COLOR_GREEN)✓ Code formatting applied$(COLOR_RESET)"; \ + else \ + echo "$(COLOR_YELLOW)⚠ PHP Code Beautifier not installed. Run: make install-deps$(COLOR_RESET)"; \ + fi + +.PHONY: validate +validate: lint phpcs ## Run all validation checks + @echo "$(COLOR_GREEN)✓ All validation checks passed$(COLOR_RESET)" + +.PHONY: test +test: ## Run PHPUnit tests + @echo "$(COLOR_BLUE)Running tests...$(COLOR_RESET)" + @if [ -f "$(PHPUNIT)" ] && [ -f "phpunit.xml" ]; then \ + $(PHPUNIT); \ + else \ + echo "$(COLOR_YELLOW)⚠ PHPUnit not configured$(COLOR_RESET)"; \ + fi + +.PHONY: test-coverage +test-coverage: ## Run tests with coverage report + @echo "$(COLOR_BLUE)Running tests with coverage...$(COLOR_RESET)" + @if [ -f "$(PHPUNIT)" ] && [ -f "phpunit.xml" ]; then \ + $(PHPUNIT) --coverage-html $(BUILD_DIR)/coverage; \ + echo "$(COLOR_GREEN)✓ Coverage report: $(BUILD_DIR)/coverage/index.html$(COLOR_RESET)"; \ + else \ + echo "$(COLOR_YELLOW)⚠ PHPUnit not configured$(COLOR_RESET)"; \ + fi + +.PHONY: clean +clean: ## Clean build artifacts + @echo "$(COLOR_BLUE)Cleaning build artifacts...$(COLOR_RESET)" + @rm -rf $(BUILD_DIR) $(DIST_DIR) + @echo "$(COLOR_GREEN)✓ Build artifacts cleaned$(COLOR_RESET)" + +.PHONY: build +build: clean validate ## Build extension package + @echo "$(COLOR_BLUE)Building Joomla extension package...$(COLOR_RESET)" + @mkdir -p $(DIST_DIR) $(BUILD_DIR) + + # Determine package prefix based on extension type + @case "$(EXTENSION_TYPE)" in \ + module) \ + PACKAGE_PREFIX="mod_$(EXTENSION_NAME)"; \ + BUILD_TARGET="$(BUILD_DIR)/$$PACKAGE_PREFIX"; \ + ;; \ + plugin) \ + PACKAGE_PREFIX="plg_$(PLUGIN_GROUP)_$(EXTENSION_NAME)"; \ + BUILD_TARGET="$(BUILD_DIR)/$$PACKAGE_PREFIX"; \ + ;; \ + component) \ + PACKAGE_PREFIX="com_$(EXTENSION_NAME)"; \ + BUILD_TARGET="$(BUILD_DIR)/$$PACKAGE_PREFIX"; \ + ;; \ + package) \ + PACKAGE_PREFIX="pkg_$(EXTENSION_NAME)"; \ + BUILD_TARGET="$(BUILD_DIR)/$$PACKAGE_PREFIX"; \ + ;; \ + template) \ + PACKAGE_PREFIX="tpl_$(EXTENSION_NAME)"; \ + BUILD_TARGET="$(BUILD_DIR)/$$PACKAGE_PREFIX"; \ + ;; \ + *) \ + echo "$(COLOR_RED)✗ Unknown extension type: $(EXTENSION_TYPE)$(COLOR_RESET)"; \ + exit 1; \ + ;; \ + esac; \ + \ + mkdir -p "$$BUILD_TARGET"; \ + \ + echo "Building $$PACKAGE_PREFIX..."; \ + \ + rsync -av --progress \ + --exclude='$(BUILD_DIR)' \ + --exclude='$(DIST_DIR)' \ + --exclude='.git*' \ + --exclude='vendor/' \ + --exclude='node_modules/' \ + --exclude='tests/' \ + --exclude='Makefile' \ + --exclude='composer.json' \ + --exclude='composer.lock' \ + --exclude='package.json' \ + --exclude='package-lock.json' \ + --exclude='phpunit.xml' \ + --exclude='*.md' \ + --exclude='.editorconfig' \ + . "$$BUILD_TARGET/"; \ + \ + cd $(BUILD_DIR) && $(ZIP) -r "../$(DIST_DIR)/$${PACKAGE_PREFIX}-$(EXTENSION_VERSION).zip" "$${PACKAGE_PREFIX}"; \ + \ + echo "$(COLOR_GREEN)✓ Package created: $(DIST_DIR)/$${PACKAGE_PREFIX}-$(EXTENSION_VERSION).zip$(COLOR_RESET)" + +.PHONY: package +package: build ## Alias for build + @echo "$(COLOR_GREEN)✓ Package ready for distribution$(COLOR_RESET)" + +.PHONY: install-local +install-local: build ## Install to local Joomla (upload via admin) + @echo "$(COLOR_BLUE)Package ready for installation$(COLOR_RESET)" + @case "$(EXTENSION_TYPE)" in \ + module) PACKAGE="mod_$(EXTENSION_NAME)";; \ + plugin) PACKAGE="plg_$(PLUGIN_GROUP)_$(EXTENSION_NAME)";; \ + component) PACKAGE="com_$(EXTENSION_NAME)";; \ + package) PACKAGE="pkg_$(EXTENSION_NAME)";; \ + template) PACKAGE="tpl_$(EXTENSION_NAME)";; \ + esac; \ + echo "$(COLOR_YELLOW)Upload $(DIST_DIR)/$${PACKAGE}-$(EXTENSION_VERSION).zip via Joomla Administrator$(COLOR_RESET)"; \ + echo "Admin URL: $(JOOMLA_ROOT) → Extensions → Install" + +.PHONY: dev-install +dev-install: ## Create symlink for development (Joomla 4+) + @echo "$(COLOR_BLUE)Creating development symlink...$(COLOR_RESET)" + @if [ ! -d "$(JOOMLA_ROOT)" ]; then \ + echo "$(COLOR_RED)✗ Joomla root not found at $(JOOMLA_ROOT)$(COLOR_RESET)"; \ + echo "Update JOOMLA_ROOT in Makefile"; \ + exit 1; \ + fi + + @case "$(EXTENSION_TYPE)" in \ + module) \ + if [ "$(MODULE_TYPE)" = "admin" ]; then \ + TARGET="$(JOOMLA_ROOT)/administrator/modules/mod_$(EXTENSION_NAME)"; \ + else \ + TARGET="$(JOOMLA_ROOT)/modules/mod_$(EXTENSION_NAME)"; \ + fi; \ + ;; \ + plugin) \ + TARGET="$(JOOMLA_ROOT)/plugins/$(PLUGIN_GROUP)/$(EXTENSION_NAME)"; \ + ;; \ + component) \ + echo "$(COLOR_YELLOW)⚠ Components require complex symlink setup$(COLOR_RESET)"; \ + echo "Manual setup recommended for component development"; \ + exit 1; \ + ;; \ + *) \ + echo "$(COLOR_RED)✗ dev-install not supported for $(EXTENSION_TYPE)$(COLOR_RESET)"; \ + exit 1; \ + ;; \ + esac; \ + \ + rm -rf "$$TARGET"; \ + ln -s "$(PWD)" "$$TARGET"; \ + echo "$(COLOR_GREEN)✓ Development symlink created at $$TARGET$(COLOR_RESET)" + +.PHONY: watch +watch: ## Watch for changes and rebuild + @echo "$(COLOR_BLUE)Watching for changes...$(COLOR_RESET)" + @echo "$(COLOR_YELLOW)Press Ctrl+C to stop$(COLOR_RESET)" + @while true; do \ + inotifywait -r -e modify,create,delete --exclude '($(BUILD_DIR)|$(DIST_DIR)|vendor|node_modules)' . 2>/dev/null || \ + (echo "$(COLOR_YELLOW)⚠ inotifywait not installed. Install: apt-get install inotify-tools$(COLOR_RESET)" && sleep 5); \ + make build; \ + done + +.PHONY: version +version: ## Display version information + @echo "$(COLOR_BLUE)Extension Information:$(COLOR_RESET)" + @echo " Name: $(EXTENSION_NAME)" + @echo " Type: $(EXTENSION_TYPE)" + @echo " Version: $(EXTENSION_VERSION)" + @if [ "$(EXTENSION_TYPE)" = "module" ]; then \ + echo " Module: $(MODULE_TYPE)"; \ + fi + @if [ "$(EXTENSION_TYPE)" = "plugin" ]; then \ + echo " Group: $(PLUGIN_GROUP)"; \ + fi + +.PHONY: docs +docs: ## Generate documentation + @echo "$(COLOR_BLUE)Generating documentation...$(COLOR_RESET)" + @mkdir -p $(DOCS_DIR) + @echo "$(COLOR_YELLOW)⚠ Documentation generation not configured$(COLOR_RESET)" + @echo "Consider adding phpDocumentor or similar" + +.PHONY: release +release: validate test build ## Create a release (validate + test + build) + @echo "$(COLOR_GREEN)✓ Release package ready$(COLOR_RESET)" + @echo "" + @echo "$(COLOR_BLUE)Release Checklist:$(COLOR_RESET)" + @echo " [ ] Update CHANGELOG.md" + @echo " [ ] Update version in XML manifest" + @echo " [ ] Test installation in clean Joomla" + @echo " [ ] Tag release in git: git tag v$(EXTENSION_VERSION)" + @echo " [ ] Push tags: git push --tags" + @echo " [ ] Create GitHub release" + @echo "" + @case "$(EXTENSION_TYPE)" in \ + module) PACKAGE="mod_$(EXTENSION_NAME)";; \ + plugin) PACKAGE="plg_$(PLUGIN_GROUP)_$(EXTENSION_NAME)";; \ + component) PACKAGE="com_$(EXTENSION_NAME)";; \ + package) PACKAGE="pkg_$(EXTENSION_NAME)";; \ + template) PACKAGE="tpl_$(EXTENSION_NAME)";; \ + esac; \ + echo "$(COLOR_GREEN)Package: $(DIST_DIR)/$${PACKAGE}-$(EXTENSION_VERSION).zip$(COLOR_RESET)" + +.PHONY: security-check +security-check: ## Run security checks on dependencies + @echo "$(COLOR_BLUE)Running security checks...$(COLOR_RESET)" + @if [ -f "composer.json" ]; then \ + $(COMPOSER) audit || echo "$(COLOR_YELLOW)⚠ Vulnerabilities found$(COLOR_RESET)"; \ + fi + @if [ -f "package.json" ]; then \ + $(NPM) audit || echo "$(COLOR_YELLOW)⚠ Vulnerabilities found$(COLOR_RESET)"; \ + fi + +.PHONY: all +all: install-deps validate test build ## Run complete build pipeline + @echo "$(COLOR_GREEN)✓ Complete build pipeline finished$(COLOR_RESET)" + +# Default target +.DEFAULT_GOAL := help