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