xref: /plugin/gitbacked/action/editcommit.php (revision b92b117a1c63763201438a5fdb8410884b3a4dee)
1<?php
2/**
3 * DokuWiki Plugin gitbacked (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Wolfgang Gassler <wolfgang@gassler.org>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) die();
11
12if (!defined('DOKU_LF')) define('DOKU_LF', "\n");
13if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t");
14if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
15
16require_once DOKU_PLUGIN.'action.php';
17require_once(DOKU_PLUGIN.'gitbacked/lib/Git.php');
18
19class action_plugin_gitbacked_editcommit extends DokuWiki_Action_Plugin {
20
21    public function register(Doku_Event_Handler &$controller) {
22
23		$controller->register_hook('IO_WIKIPAGE_WRITE', 'AFTER', $this, 'handle_io_wikipage_write');
24		$controller->register_hook('MEDIA_UPLOAD_FINISH', 'AFTER', $this, 'handle_media_upload');
25		$controller->register_hook('MEDIA_DELETE_FILE', 'AFTER', $this, 'handle_media_deletion');
26		$controller->register_hook('DOKUWIKI_DONE', 'AFTER', $this, 'handle_periodic_pull');
27    }
28
29	public function handle_periodic_pull(Doku_Event &$event, $param) {
30		if ($this->getConf('periodicPull')) {
31			$lastPullFile = DOKU_PLUGIN.'gitbacked/action/lastpull.txt';
32			//check if the lastPullFile exists
33			if (is_file($lastPullFile)) {
34				$lastPull = unserialize(file_get_contents($lastPullFile));
35			} else {
36				$lastPull = 0;
37			}
38			//calculate time between pulls in seconds
39			$timeToWait = $this->getConf('periodicMinutes')*60;
40			$now = time();
41
42			//if it is time to run a pull request
43			if ($lastPull+$timeToWait < $now) {
44				$repo = $this->initRepo();
45
46				//execute the pull request
47				$repo->pull('origin',$repo->active_branch());
48
49				//save the current time to the file to track the last pull execution
50				file_put_contents($lastPullFile,serialize(time()));
51			}
52		}
53	}
54
55	private function initRepo() {
56		//get path to the repo root (by default DokuWiki's savedir)
57		$repoPath = DOKU_INC.$this->getConf('repoPath');
58		//init the repo and create a new one if it is not present
59		$repo = new GitRepo($repoPath, true, true);
60
61		$params = $this->getConf('addParams');
62		if ($params) {
63			$repo->git_path .= ' '.$params;
64		}
65		return $repo;
66	}
67
68	private function commitFile($filePath,$message) {
69
70		$repo = $this->initRepo();
71
72		//add the changed file and set the commit message
73		$repo->add($filePath);
74		$repo->commit($message);
75
76		//if the push after Commit option is set we push the active branch to origin
77		if ($this->getConf('pushAfterCommit')) {
78			$repo->push('origin',$repo->active_branch());
79		}
80
81	}
82
83	private function getAuthor() {
84		return $GLOBALS['USERINFO']['name'];
85	}
86
87	public function handle_media_deletion(Doku_Event &$event, $param) {
88		$mediaPath = $event->data['path'];
89		$mediaName = $event->data['name'];
90
91		$message = str_replace(
92			array('%media%','%user%'),
93			array($mediaName,$this->getAuthor()),
94			$this->getConf('commitMediaMsgDel')
95		);
96
97		$this->commitFile($mediaPath,$message);
98
99	}
100
101	public function handle_media_upload(Doku_Event &$event, $param) {
102
103		$mediaPath = $event->data[1];
104		$mediaName = $event->data[2];
105
106		$message = str_replace(
107			array('%media%','%user%'),
108			array($mediaName,$this->getAuthor()),
109			$this->getConf('commitMediaMsg')
110		);
111
112		$this->commitFile($mediaPath,$message);
113
114	}
115
116    public function handle_io_wikipage_write(Doku_Event &$event, $param) {
117
118		$rev = $event->data[3];
119
120		/* On update to an existing page this event is called twice,
121		* once for the transfer of the old version to the attic (rev will have a value)
122		* and once to write the new version of the page into the wiki (rev is false)
123		*/
124		if (!$rev) {
125
126			$pagePath = $event->data[0][0];
127			$pageName = $event->data[2];
128			$pageContent = $event->data[0][1];
129
130			// get the summary directly from the form input
131			// as the metadata hasn't updated yer
132			$editSummary = $GLOBALS['INPUT']->str('summary');
133
134			// empty content indicates a page deletion
135			if ($pageContent == '') {
136				// get the commit text for deletions
137				$msgTemplate = $this->getConf('commitPageMsgDel');
138
139				// bad hack as DokuWiki deletes the file after this event
140				// thus, let's delete the file by ourselves, so git can recognize the deletion
141				// DokuWiki uses @unlink as well, so no error should be thrown if we delete it twice
142				@unlink($pagePath);
143
144			} else {
145				//get the commit text for edits
146				$msgTemplate = $this->getConf('commitPageMsg');
147			}
148
149			$message = str_replace(
150				array('%page%','%summary%','%user%'),
151				array($pageName,$editSummary,$this->getAuthor()),
152				$msgTemplate
153			);
154
155			$this->commitFile($pagePath,$message);
156
157		}
158
159    }
160
161}
162
163// vim:ts=4:sw=4:et:
164