xref: /plugin/gitbacked/classes/GitBackedUtil.php (revision c365e7db171e13fc94915621164a0270ac12db2e)
1b08c3d51SMarkus Hoffrogge<?php
2b08c3d51SMarkus Hoffrogge
32762023dSMarkus Hoffroggenamespace woolfg\dokuwiki\plugin\gitbacked;
42762023dSMarkus 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
172762023dSMarkus Hoffrogge// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols
182762023dSMarkus Hoffrogge// must be run within Dokuwiki
192762023dSMarkus 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 */
302762023dSMarkus Hoffroggeclass GitBackedUtil
312762023dSMarkus 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     */
482762023dSMarkus Hoffrogge    public static function isAbsolutePath($path)
492762023dSMarkus 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     */
772762023dSMarkus Hoffrogge    public static function getEffectivePath($path)
782762023dSMarkus 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     */
992762023dSMarkus Hoffrogge    public static function getTempDir()
1002762023dSMarkus 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     */
1172762023dSMarkus Hoffrogge    public static function createMessageFile($message)
1182762023dSMarkus 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
1282762023dSMarkus Hoffrogge    /**
1292762023dSMarkus Hoffrogge     * Determine closest git repository path for a given path as absolute PHP realpath().
1302762023dSMarkus Hoffrogge     * This search starts in $path - if $path does not contain .git,
1312762023dSMarkus Hoffrogge     * it will iterate the directories upwards as long as it finds a directory
1322762023dSMarkus Hoffrogge     * containing a .git folder.
1332762023dSMarkus Hoffrogge     *
1342762023dSMarkus Hoffrogge     * @access  public
1352762023dSMarkus Hoffrogge     * @return  string  the next git repo root dir as absolute PHP realpath()
1362762023dSMarkus Hoffrogge     *                  or empty string, if no git repo found.
1372762023dSMarkus Hoffrogge     */
1382762023dSMarkus Hoffrogge    public static function getClosestAbsoluteRepoPath($path)
1392762023dSMarkus Hoffrogge    {
140*c365e7dbSmhoffrog        $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
141*c365e7dbSmhoffrog        $pipes = [];
1422762023dSMarkus Hoffrogge        // Using --git-dir rather than --absolute-git-dir for a wider git versions compatibility
1432762023dSMarkus Hoffrogge        //$command = Git::getBin()." rev-parse --absolute-git-dir";
1442762023dSMarkus Hoffrogge        $command = Git::getBin() . " rev-parse --git-dir";
1452762023dSMarkus Hoffrogge        //dbglog("GitBacked - Command: ".$command);
1462762023dSMarkus Hoffrogge        $resource = proc_open($command, $descriptorspec, $pipes, $path);
1472762023dSMarkus Hoffrogge        $stdout = stream_get_contents($pipes[1]);
148*c365e7dbSmhoffrog        stream_get_contents($pipes[2]);
1492762023dSMarkus Hoffrogge        foreach ($pipes as $pipe) {
1502762023dSMarkus Hoffrogge            fclose($pipe);
1512762023dSMarkus Hoffrogge        }
1522762023dSMarkus Hoffrogge
1532762023dSMarkus Hoffrogge        $status = trim(proc_close($resource));
1542762023dSMarkus Hoffrogge        if ($status == 0) {
1552762023dSMarkus Hoffrogge            $repo_git_dir = trim($stdout);
1562762023dSMarkus Hoffrogge            //dbglog("GitBacked - $command: '".$repo_git_dir."'");
1572762023dSMarkus Hoffrogge            if (!empty($repo_git_dir)) {
1582762023dSMarkus Hoffrogge                if (strcmp($repo_git_dir, ".git") === 0) {
1592762023dSMarkus Hoffrogge                    // convert to absolute path based on this command execution directory
1602762023dSMarkus Hoffrogge                    $repo_git_dir = $path . '/' . $repo_git_dir;
1612762023dSMarkus Hoffrogge                }
1622762023dSMarkus Hoffrogge                $repo_path = dirname(realpath($repo_git_dir));
1632762023dSMarkus Hoffrogge                $doku_inc_path = dirname(realpath(DOKU_INC));
1642762023dSMarkus Hoffrogge                if (strlen($repo_path) < strlen($doku_inc_path)) {
1652762023dSMarkus Hoffrogge                    // This code should never be reached!
1662762023dSMarkus Hoffrogge                    // If we get here, then we are beyond DOKU_INC - so this not supposed to be for us!
1672762023dSMarkus Hoffrogge                    return '';
1682762023dSMarkus Hoffrogge                }
1692762023dSMarkus Hoffrogge                //dbglog('GitBacked - $repo_path: '.$repo_path);
1702762023dSMarkus Hoffrogge                if (file_exists($repo_path . "/.git") && is_dir($repo_path . "/.git")) {
1712762023dSMarkus Hoffrogge                    return $repo_path;
1722762023dSMarkus Hoffrogge                }
1732762023dSMarkus Hoffrogge            }
1742762023dSMarkus Hoffrogge        }
1752762023dSMarkus Hoffrogge        return '';
1762762023dSMarkus Hoffrogge    }
177b08c3d51SMarkus Hoffrogge}
178b08c3d51SMarkus Hoffrogge/* End of file */
179