633fb276e08b81740c0ea08535f42d3284666d91
[phorkie.git] / src / phorkie / Repository / Post.php
1 <?php
2 namespace phorkie;
3
4 class Repository_Post
5 {
6     public $repo;
7
8     public function __construct(Repository $repo = null)
9     {
10         $this->repo = $repo;
11     }
12
13     /**
14      * Processes the POST data, changes description and files
15      *
16      * @return boolean True if the post was successful
17      */
18     public function process($postData)
19     {
20         if (!isset($postData['files'])) {
21             return false;
22         }
23
24         if (!$this->repo) {
25             $this->repo = $this->createRepo();
26         }
27
28         $vc = $this->repo->getVc();
29
30
31         $bChanged = false;
32         $bCommit  = false;
33         if ($postData['description'] != $this->repo->getDescription()) {
34             $this->repo->setDescription($postData['description']);
35             $bChanged = true;
36         }
37
38         foreach ($postData['files'] as $num => $arFile) {
39             $bUpload = false;
40             if ($_FILES['files']['error'][$num]['upload'] == 0) {
41                 //valid file upload
42                 $bUpload = true;
43             } else if ($arFile['content'] == '' && $arFile['name'] == '') {
44                 //empty (new) file
45                 continue;
46             }
47
48             $orignalName = Tools::sanitizeFilename($arFile['original_name']);
49             $name        = Tools::sanitizeFilename($arFile['name']);
50
51             if ($name == '') {
52                 if ($bUpload) {
53                     $name = Tools::sanitizeFilename($_FILES['files']['name'][$num]['upload']);
54                 } else {
55                     $name = $this->getNextNumberedFile('phork')
56                         . '.' . $arFile['type'];
57                 }
58             }
59
60             $bNew = false;
61             $bDelete = false;
62             if (!isset($orignalName) || $orignalName == '') {
63                 //new file
64                 $bNew = true;
65                 if (strpos($name, '.') === false) {
66                     //automatically append file extension if none is there
67                     $name .= '.' . $arFile['type'];
68                 }
69             } else if (!$this->repo->hasFile($orignalName)) {
70                 //unknown file
71                 //FIXME: Show error message
72                 continue;
73             } else if (isset($arFile['delete']) && $arFile['delete'] == 1) {
74                 $bDelete = true;
75             } else if ($orignalName != $name) {
76                 if (strpos($name, '/') === false) {
77                     //ignore names with a slash in it, would be new directory
78                     //FIXME: what to do with overwrites?
79                     $vc->getCommand('mv')
80                         ->addArgument($orignalName)
81                         ->addArgument($name)
82                         ->execute();
83                     $bCommit = true;
84                 } else {
85                     $name = $orignalName;
86                 }
87             }
88
89             $file = $this->repo->getFileByName($name, false);
90             if ($bDelete) {
91                 $command = $vc->getCommand('rm')
92                     ->addArgument($file->getFilename())
93                     ->execute();
94                 $bCommit = true;
95             } else if ($bUpload) {
96                 move_uploaded_file(
97                     $_FILES['files']['tmp_name'][$num]['upload'], $file->getFullPath()
98                 );
99                 $command = $vc->getCommand('add')
100                     ->addArgument($file->getFilename())
101                     ->execute();
102                 $bCommit = true;
103             } else if ($bNew || (isset($arFile['content']) && $file->getContent() != $arFile['content'])) {
104                 file_put_contents($file->getFullPath(), $arFile['content']);
105                 $command = $vc->getCommand('add')
106                     ->addArgument($file->getFilename())
107                     ->execute();
108                 $bCommit = true;
109             }
110         }
111
112         if ($bCommit) {
113             $vc->getCommand('commit')
114                 ->setOption('message', '')
115                 ->setOption('allow-empty-message')
116                 ->setOption('author', 'Anonymous <anonymous@phorkie>')
117                 ->execute();
118             $bChanged = true;
119         }
120
121         if ($bChanged) {
122             //FIXME: index changed files only
123             //also handle file deletions
124             $db = new Database();
125             $db->getIndexer()->updateRepo($this->repo);
126         }
127
128         return true;
129     }
130
131     public function createRepo()
132     {
133         $rs = new Repositories();
134         $repo = $rs->createNew();
135         $vc = $repo->getVc();
136         $vc->getCommand('init')
137             //this should be setOption, but it fails with a = between name and value
138             ->addArgument('--separate-git-dir')
139             ->addArgument($GLOBALS['phorkie']['cfg']['gitdir'] . '/' . $repo->id . '.git')
140             ->addArgument($repo->workDir)
141             ->execute();
142
143         foreach (glob($repo->gitDir . '/hooks/*') as $hookfile) {
144             unlink($hookfile);
145         }
146
147         touch($repo->gitDir . '/git-daemon-export-ok');
148
149         return $repo;
150     }
151
152     public function getNextNumberedFile($prefix)
153     {
154         $num = -1;
155         do {
156             ++$num;
157             $files = glob($this->repo->workDir . '/' . $prefix . $num . '.*');
158         } while (count($files));
159
160         return $prefix . $num;
161     }
162 }
163
164 ?>