Update jQuery from 1.12.4 to 3.7.1
[phorkie.git] / src / phorkie / Repository / LinkbackReceiver.php
1 <?php
2 namespace phorkie;
3
4 class Repository_LinkbackReceiver
5     implements \PEAR2\Services\Linkback\Server\Callback\IStorage
6 {
7     protected $repo;
8
9     public function __construct($repo)
10     {
11         $this->repo = $repo;
12     }
13
14     /**
15      * Stores the linkback as remote fork in the paste repository.
16      *
17      * @param string $target     Target URI that should be linked in $source
18      * @param string $source     Linkback source URI that should link to target
19      * @param string $sourceBody Content of $source URI
20      * @param object $res        HTTP response from fetching $source
21      *
22      * @return void
23      *
24      * @throws SPb\Exception When storing the linkback fatally failed
25      */
26     public function storeLinkback(
27         $target, $source, $sourceBody, \HTTP_Request2_Response $res
28     ) {
29         //FIXME: deleted
30         //FIXME: cleanuptask
31
32         $hp = new HtmlParser();
33         $ok = $hp->extractGitUrls($source, $sourceBody);
34         if ($ok === false) {
35             //failed to extract git URL from linkback source
36             //FIXME: send exception
37             //$hp->error
38             return;
39         }
40
41         $ci = $this->repo->getConnectionInfo();
42         $forks = $ci->getForks();
43
44         $arRemoteCloneUrls = $this->localizeGitUrls($hp->getGitUrls());
45
46         $remoteCloneUrl = $remoteTitle = null;
47         if (count($arRemoteCloneUrls)) {
48             reset($arRemoteCloneUrls);
49             $remoteCloneUrl = key($arRemoteCloneUrls);
50             $remoteTitle    = current($arRemoteCloneUrls);
51         }
52         $remoteid = 'fork-' . uniqid();
53         //check if we already know this remote
54         foreach ($forks as $remote) {
55             if (isset($arRemoteCloneUrls[$remote->getCloneUrl()])) {
56                 $remoteTitle = $arRemoteCloneUrls[$remote->getCloneUrl()];
57                 $remoteid = $remote->getName();
58                 break;
59             } else if ($source == $remote->getWebURL(true)) {
60                 $remoteid = $remote->getName();
61                 break;
62             }
63         }
64
65         $vc = $this->repo->getVc();
66         if (!$this->isLocalWebUrl($source)) {
67             //only add remote homepage; we can calculate local ones ourselves
68             $vc->getCommand('config')
69                 ->addArgument('remote.' . $remoteid . '.homepage')
70                 ->addArgument($source)
71                 ->execute();
72         }
73         if ($remoteTitle !== null) {
74             $vc->getCommand('config')
75                 ->addArgument('remote.' . $remoteid . '.title')
76                 ->addArgument($remoteTitle)
77                 ->execute();
78         }
79         if ($remoteCloneUrl !== null) {
80             $vc->getCommand('config')
81                 ->addArgument('remote.' . $remoteid . '.url')
82                 ->addArgument($remoteCloneUrl)
83                 ->execute();
84         }
85     }
86
87     /**
88      * Check if the given full URL is the URL of a local repository
89      *
90      * @return Repository
91      */
92     protected function isLocalWebUrl($url)
93     {
94         $base = Tools::fullUrl();
95         if (substr($url, 0, strlen($base)) != $base) {
96             //base does not match
97             return false;
98         }
99
100         $remainder = substr($url, strlen($base));
101         if (!is_numeric($remainder)) {
102             return false;
103         }
104         try {
105             $repo = new Repository();
106             $repo->loadById($remainder);
107         } catch (\Exception $e) {
108             return false;
109         }
110         return true;
111     }
112
113     /**
114      * Convert an array of git urls to local URLs if possible and serialize them
115      * into a simple array.
116      *
117      * @param array $arGitUrls Array of array of urls. Main key is the title of
118      *                         the URL array.
119      *
120      * @return array Key is the git clone URL, value the title of the remote
121      */
122     protected function localizeGitUrls($arGitUrls)
123     {
124         $pub = $pri = null;
125         if (isset($GLOBALS['phorkie']['cfg']['git']['public'])) {
126             $pub = $GLOBALS['phorkie']['cfg']['git']['public'];
127         }
128         if (isset($GLOBALS['phorkie']['cfg']['git']['private'])) {
129             $pri = $GLOBALS['phorkie']['cfg']['git']['private'];
130         }
131
132         $arRemoteCloneUrls = array();
133         foreach ($arGitUrls as $remoteTitle => $arUrls) {
134             foreach ($arUrls as $remoteCloneUrl) {
135                 if ($pub !== null
136                     && substr($remoteCloneUrl, 0, strlen($pub)) == $pub
137                     && substr($remoteCloneUrl, -4) == '.git'
138                 ) {
139                     $id = substr($remoteCloneUrl, strlen($pub), -4);
140                     $repo = new Repository();
141                     try {
142                         $repo->loadById($id);
143                         $arRemoteCloneUrls[$repo->gitDir] = $remoteTitle;
144                     } catch (Exception $e) {
145                     }
146                 } else if ($pri !== null
147                     && substr($remoteCloneUrl, 0, strlen($pri)) == $pri
148                     && substr($remoteCloneUrl, -4) == '.git'
149                 ) {
150                     $id = substr($remoteCloneUrl, strlen($pri), -4);
151                     $repo = new Repository();
152                     try {
153                         $repo->loadById($id);
154                         $arRemoteCloneUrls[$repo->gitDir] = $remoteTitle;
155                     } catch (Exception $e) {
156                     }
157                 } else {
158                     $arRemoteCloneUrls[$remoteCloneUrl] = $remoteTitle;
159                 }
160             }
161         }
162         return $arRemoteCloneUrls;
163     }
164 }
165 ?>