1<?php
2/**
3 * Sphinx Search Indexer Wrapper with Real-time Progress and Permission Handling
4 * Recommended usage: php lib/plugins/sphinxsearchwas/indexer.php
5 */
6
7// 1. Setup DokuWiki environment
8if (!defined('DOKU_INC')) {
9    $inc_path = realpath(__DIR__ . '/../../../') . '/';
10    if (!file_exists($inc_path . 'inc/init.php')) {
11        die("Error: Could not find DokuWiki core. Run this script from within the plugin directory.\n");
12    }
13    define('DOKU_INC', $inc_path);
14}
15
16define('NOSESSION', 1);
17require_once(DOKU_INC . 'inc/init.php');
18
19if (PHP_SAPI !== 'cli') {
20    header('HTTP/1.1 403 Forbidden');
21    die("Access Denied: This script must be run from the command line.\n");
22}
23
24// 2. Load Plugin Configuration
25/** @var action_plugin_sphinxsearchwas $plugin */
26$plugin = plugin_load('action', 'sphinxsearchwas');
27if (!$plugin) {
28    die("Error: Sphinxsearch plugin is not installed or enabled.\n");
29}
30
31$indexName = $plugin->getConf('index') ?: 'dk_main';
32$configFile = __DIR__ . '/sphinx.conf';
33$indexerBin = 'indexer';
34$targetUser = 'www-data';
35$targetGroup = 'www-data';
36
37// 3. Directory Validation
38if (!file_exists($configFile)) {
39    die("Error: Sphinx configuration file not found at $configFile\n");
40}
41
42$idxPath = DOKU_INC . 'data/sphinxsearchwas';
43if (!is_dir($idxPath)) {
44    mkdir($idxPath, 0777, true);
45}
46
47// 4. CHANGE DIRECTORY: Resolve paths relative to DokuWiki Root
48chdir(DOKU_INC);
49
50// 5. Build Command
51$cmd = sprintf(
52    '%s -c %s --rotate %s 2>&1',
53    $indexerBin,
54    escapeshellarg($configFile),
55    escapeshellarg($indexName)
56);
57
58echo "Starting Sphinx Indexer for index: $indexName...\n";
59echo "Working Directory: " . getcwd() . "\n";
60echo "--------------------------------------------------\n";
61
62// 6. Execute and Stream Output
63$handle = popen($cmd, 'r');
64
65if ($handle) {
66    while (!feof($handle)) {
67        $line = fgets($handle);
68        if ($line !== false) {
69            echo $line;
70            if (ob_get_level() > 0) ob_flush();
71            flush();
72        }
73    }
74    $returnCode = pclose($handle);
75} else {
76    echo "Error: Failed to execute indexer binary.\n";
77    $returnCode = 1;
78}
79
80// 7. Post-Indexing: Permission and Ownership Update
81if ($returnCode === 0) {
82    echo "--------------------------------------------------\n";
83    echo "Updating file ownership and permissions in $idxPath...\n";
84
85    try {
86        $iterator = new RecursiveIteratorIterator(
87            new RecursiveDirectoryIterator($idxPath, RecursiveDirectoryIterator::SKIP_DOTS),
88            RecursiveIteratorIterator::SELF_FIRST
89        );
90
91        // Also process the root directory itself
92        $paths = iterator_to_array($iterator);
93        $paths[] = new SplFileInfo($idxPath);
94
95        foreach ($paths as $fileInfo) {
96            $path = $fileInfo->getRealPath();
97
98            // Set Ownership
99            if (!@chown($path, $targetUser)) {
100                echo "Warning: Could not change owner of $path to $targetUser\n";
101            }
102            if (!@chgrp($path, $targetGroup)) {
103                echo "Warning: Could not change group of $path to $targetGroup\n";
104            }
105
106            // Set Access Flags
107            if (is_dir($path)) {
108                chmod($path, 0775); // rwxrwxr-x
109            } else {
110                chmod($path, 0664); // rw-rw-r--
111            }
112        }
113        echo "[SUCCESS] Permissions and ownership updated to $targetUser:$targetGroup.\n";
114    } catch (Exception $e) {
115        echo "[ERROR] Failed to update permissions: " . $e->getMessage() . "\n";
116    }
117}
118
119// 8. Final Report
120echo "--------------------------------------------------\n";
121if ($returnCode === 0) {
122    echo "[SUCCESS] Indexing completed successfully.\n";
123    exit(0);
124} else {
125    echo "[ERROR] Indexing failed with exit code: $returnCode\n";
126    exit($returnCode);
127}
128