xref: /plugin/gitbacked/classes/GitBackedUtil.php (revision 2762023dfb29a64197cb442f664aa321f9f5bc87)
1b08c3d51SMarkus Hoffrogge<?php
2b08c3d51SMarkus Hoffrogge
3*2762023dSMarkus Hoffroggenamespace woolfg\dokuwiki\plugin\gitbacked;
4*2762023dSMarkus Hoffrogge
5b08c3d51SMarkus Hoffrogge/*
6b08c3d51SMarkus Hoffrogge * GitBackedUtil.php
7b08c3d51SMarkus Hoffrogge *
8b08c3d51SMarkus Hoffrogge * PHP common utility function lib
9b08c3d51SMarkus Hoffrogge *
10b08c3d51SMarkus Hoffrogge * @package    GitBackedUtil.php
11b08c3d51SMarkus Hoffrogge * @version    1.0
12b08c3d51SMarkus Hoffrogge * @author     Markus Hoffrogge
13b08c3d51SMarkus Hoffrogge * @copyright  Copyright 2023 Markus Hoffrogge
14b08c3d51SMarkus Hoffrogge * @repo       https://github.com/woolfg/dokuwiki-plugin-gitbacked
15b08c3d51SMarkus Hoffrogge */
16b08c3d51SMarkus Hoffrogge
17*2762023dSMarkus Hoffrogge// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols
18*2762023dSMarkus Hoffrogge// must be run within Dokuwiki
19*2762023dSMarkus Hoffroggeif (!defined('DOKU_INC')) die();
20b08c3d51SMarkus Hoffrogge
21b08c3d51SMarkus Hoffrogge// ------------------------------------------------------------------------
22b08c3d51SMarkus Hoffrogge
23b08c3d51SMarkus Hoffrogge/**
24b08c3d51SMarkus Hoffrogge * GitBacked Utility Class
25b08c3d51SMarkus Hoffrogge *
26b08c3d51SMarkus Hoffrogge * This class provides common utility functions.
27b08c3d51SMarkus Hoffrogge *
28b08c3d51SMarkus Hoffrogge * @class  GitBackedUtil
29b08c3d51SMarkus Hoffrogge */
30*2762023dSMarkus Hoffroggeclass GitBackedUtil
31*2762023dSMarkus Hoffrogge{
32b08c3d51SMarkus Hoffrogge    /**
33b08c3d51SMarkus Hoffrogge     * GitBacked temp directory
34b08c3d51SMarkus Hoffrogge     *
35b08c3d51SMarkus Hoffrogge     * @var string
36b08c3d51SMarkus Hoffrogge     */
37b08c3d51SMarkus Hoffrogge    protected static $temp_dir = '';
38b08c3d51SMarkus Hoffrogge
39b08c3d51SMarkus Hoffrogge    /**
40b08c3d51SMarkus Hoffrogge     * Checks, if a given path name is an absolute path or not.
41b08c3d51SMarkus Hoffrogge     * This function behaves like absolute path determination in dokuwiki init.php fullpath() method.
42b08c3d51SMarkus Hoffrogge     * The relevant code has been copied from there.
43b08c3d51SMarkus Hoffrogge     *
44b08c3d51SMarkus Hoffrogge     * @access  public
45b08c3d51SMarkus Hoffrogge     * @param   string $path    a file path name
46b08c3d51SMarkus Hoffrogge     * @return  bool
47b08c3d51SMarkus Hoffrogge     */
48*2762023dSMarkus Hoffrogge    public static function isAbsolutePath($path)
49*2762023dSMarkus Hoffrogge    {
50b08c3d51SMarkus Hoffrogge        $ret = false;
51b08c3d51SMarkus Hoffrogge
52b08c3d51SMarkus Hoffrogge        $iswin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' || !empty($GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']));
53b08c3d51SMarkus Hoffrogge        // check for the (indestructable) root of the path - keeps windows stuff intact
54b08c3d51SMarkus Hoffrogge        if ($path[0] == '/') {
55b08c3d51SMarkus Hoffrogge            $ret = true;
56b08c3d51SMarkus Hoffrogge        } elseif ($iswin) {
57b08c3d51SMarkus Hoffrogge            // match drive letter and UNC paths
58b08c3d51SMarkus Hoffrogge            if (preg_match('!^([a-zA-z]:)(.*)!', $path, $match)) {
59b08c3d51SMarkus Hoffrogge                $ret = true;
60b08c3d51SMarkus Hoffrogge            } elseif (preg_match('!^(\\\\\\\\[^\\\\/]+\\\\[^\\\\/]+[\\\\/])(.*)!', $path, $match)) {
61b08c3d51SMarkus Hoffrogge                $ret = true;
62b08c3d51SMarkus Hoffrogge            }
63b08c3d51SMarkus Hoffrogge        }
64b08c3d51SMarkus Hoffrogge
65b08c3d51SMarkus Hoffrogge        return $ret;
66b08c3d51SMarkus Hoffrogge    }
67b08c3d51SMarkus Hoffrogge
68b08c3d51SMarkus Hoffrogge    /**
69b08c3d51SMarkus Hoffrogge     * Returns the $path as is, if it is an absolute path.
70b08c3d51SMarkus Hoffrogge     * Otherwise it will prepend the base path appropriate
71b08c3d51SMarkus Hoffrogge     * to the type of DW instance.
72b08c3d51SMarkus Hoffrogge     *
73b08c3d51SMarkus Hoffrogge     * @access  public
74b08c3d51SMarkus Hoffrogge     * @param   string $path    a file path name
75b08c3d51SMarkus Hoffrogge     * @return  string          an appropriate absolute path
76b08c3d51SMarkus Hoffrogge     */
77*2762023dSMarkus Hoffrogge    public static function getEffectivePath($path)
78*2762023dSMarkus Hoffrogge    {
79b08c3d51SMarkus Hoffrogge        $ret = $path;
80b08c3d51SMarkus Hoffrogge
81b08c3d51SMarkus Hoffrogge        if (self::isAbsolutePath($ret)) {
82b08c3d51SMarkus Hoffrogge            return $ret;
83b08c3d51SMarkus Hoffrogge        }
84b08c3d51SMarkus Hoffrogge        if (defined('DOKU_FARM')) {
85b08c3d51SMarkus Hoffrogge            $ret = DOKU_CONF . '../' . $ret;
86b08c3d51SMarkus Hoffrogge        } else {
87b08c3d51SMarkus Hoffrogge            $ret = DOKU_INC . $ret;
88b08c3d51SMarkus Hoffrogge        }
89b08c3d51SMarkus Hoffrogge        return $ret;
90b08c3d51SMarkus Hoffrogge    }
91b08c3d51SMarkus Hoffrogge
92b08c3d51SMarkus Hoffrogge    /**
93b08c3d51SMarkus Hoffrogge     * Returns the temp dir for GitBacked plugin.
94b08c3d51SMarkus Hoffrogge     * It ensures that the temp dir will be created , if not yet existing.
95b08c3d51SMarkus Hoffrogge     *
96b08c3d51SMarkus Hoffrogge     * @access  public
97b08c3d51SMarkus Hoffrogge     * @return  string          the gitbacked temp directory name
98b08c3d51SMarkus Hoffrogge     */
99*2762023dSMarkus Hoffrogge    public static function getTempDir()
100*2762023dSMarkus Hoffrogge    {
101b08c3d51SMarkus Hoffrogge        if (empty(self::$temp_dir)) {
102b08c3d51SMarkus Hoffrogge            global $conf;
103b08c3d51SMarkus Hoffrogge            self::$temp_dir = $conf['tmpdir'] . '/gitbacked';
104b08c3d51SMarkus Hoffrogge            io_mkdir_p(self::$temp_dir);
105b08c3d51SMarkus Hoffrogge        }
106b08c3d51SMarkus Hoffrogge        return self::$temp_dir;
107b08c3d51SMarkus Hoffrogge    }
108b08c3d51SMarkus Hoffrogge
109b08c3d51SMarkus Hoffrogge    /**
110b08c3d51SMarkus Hoffrogge     * Creates a temp file and writes the $message to it.
111b08c3d51SMarkus Hoffrogge     * It ensures that the temp dir will be created , if not yet existing.
112b08c3d51SMarkus Hoffrogge     *
113b08c3d51SMarkus Hoffrogge     * @access  public
114b08c3d51SMarkus Hoffrogge     * @param   string $message the text message
115b08c3d51SMarkus Hoffrogge     * @return  string          the temp filename created
116b08c3d51SMarkus Hoffrogge     */
117*2762023dSMarkus Hoffrogge    public static function createMessageFile($message)
118*2762023dSMarkus Hoffrogge    {
119b08c3d51SMarkus Hoffrogge        $tmpfname = tempnam(self::getTempDir(), 'gitMessage_');
120b08c3d51SMarkus Hoffrogge        $handle = fopen($tmpfname, "w");
121b08c3d51SMarkus Hoffrogge        if (!empty($message)) {
122b08c3d51SMarkus Hoffrogge            fwrite($handle, $message);
123b08c3d51SMarkus Hoffrogge        }
124b08c3d51SMarkus Hoffrogge        fclose($handle);
125b08c3d51SMarkus Hoffrogge        return $tmpfname;
126b08c3d51SMarkus Hoffrogge    }
127b08c3d51SMarkus Hoffrogge
128*2762023dSMarkus Hoffrogge    /**
129*2762023dSMarkus Hoffrogge     * Determine closest git repository path for a given path as absolute PHP realpath().
130*2762023dSMarkus Hoffrogge     * This search starts in $path - if $path does not contain .git,
131*2762023dSMarkus Hoffrogge     * it will iterate the directories upwards as long as it finds a directory
132*2762023dSMarkus Hoffrogge     * containing a .git folder.
133*2762023dSMarkus Hoffrogge     *
134*2762023dSMarkus Hoffrogge     * @access  public
135*2762023dSMarkus Hoffrogge     * @return  string  the next git repo root dir as absolute PHP realpath()
136*2762023dSMarkus Hoffrogge     *                  or empty string, if no git repo found.
137*2762023dSMarkus Hoffrogge     */
138*2762023dSMarkus Hoffrogge    public static function getClosestAbsoluteRepoPath($path)
139*2762023dSMarkus Hoffrogge    {
140*2762023dSMarkus Hoffrogge        $descriptorspec = array(
141*2762023dSMarkus Hoffrogge            1 => array('pipe', 'w'),
142*2762023dSMarkus Hoffrogge            2 => array('pipe', 'w'),
143*2762023dSMarkus Hoffrogge        );
144*2762023dSMarkus Hoffrogge        $ret = '';
145*2762023dSMarkus Hoffrogge        $pipes = array();
146*2762023dSMarkus Hoffrogge        // Using --git-dir rather than --absolute-git-dir for a wider git versions compatibility
147*2762023dSMarkus Hoffrogge        //$command = Git::getBin()." rev-parse --absolute-git-dir";
148*2762023dSMarkus Hoffrogge        $command = Git::getBin() . " rev-parse --git-dir";
149*2762023dSMarkus Hoffrogge        //dbglog("GitBacked - Command: ".$command);
150*2762023dSMarkus Hoffrogge        $resource = proc_open($command, $descriptorspec, $pipes, $path);
151*2762023dSMarkus Hoffrogge        $stdout = stream_get_contents($pipes[1]);
152*2762023dSMarkus Hoffrogge        $stderr = stream_get_contents($pipes[2]);
153*2762023dSMarkus Hoffrogge        foreach ($pipes as $pipe) {
154*2762023dSMarkus Hoffrogge            fclose($pipe);
155*2762023dSMarkus Hoffrogge        }
156*2762023dSMarkus Hoffrogge
157*2762023dSMarkus Hoffrogge        $status = trim(proc_close($resource));
158*2762023dSMarkus Hoffrogge        if ($status == 0) {
159*2762023dSMarkus Hoffrogge            $repo_git_dir = trim($stdout);
160*2762023dSMarkus Hoffrogge            //dbglog("GitBacked - $command: '".$repo_git_dir."'");
161*2762023dSMarkus Hoffrogge            if (!empty($repo_git_dir)) {
162*2762023dSMarkus Hoffrogge                if (strcmp($repo_git_dir, ".git") === 0) {
163*2762023dSMarkus Hoffrogge                    // convert to absolute path based on this command execution directory
164*2762023dSMarkus Hoffrogge                    $repo_git_dir = $path . '/' . $repo_git_dir;
165*2762023dSMarkus Hoffrogge                }
166*2762023dSMarkus Hoffrogge                $repo_path = dirname(realpath($repo_git_dir));
167*2762023dSMarkus Hoffrogge                $doku_inc_path = dirname(realpath(DOKU_INC));
168*2762023dSMarkus Hoffrogge                if (strlen($repo_path) < strlen($doku_inc_path)) {
169*2762023dSMarkus Hoffrogge                    // This code should never be reached!
170*2762023dSMarkus Hoffrogge                    // If we get here, then we are beyond DOKU_INC - so this not supposed to be for us!
171*2762023dSMarkus Hoffrogge                    return '';
172*2762023dSMarkus Hoffrogge                }
173*2762023dSMarkus Hoffrogge                //dbglog('GitBacked - $repo_path: '.$repo_path);
174*2762023dSMarkus Hoffrogge                if (file_exists($repo_path . "/.git") && is_dir($repo_path . "/.git")) {
175*2762023dSMarkus Hoffrogge                    return $repo_path;
176*2762023dSMarkus Hoffrogge                }
177*2762023dSMarkus Hoffrogge            }
178*2762023dSMarkus Hoffrogge        }
179*2762023dSMarkus Hoffrogge        return '';
180*2762023dSMarkus Hoffrogge    }
181b08c3d51SMarkus Hoffrogge}
182b08c3d51SMarkus Hoffrogge/* End of file */
183