lib.php 10.5 KB
Newer Older
1
2
3
<?php
/**
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    mahara
 * @subpackage artefact-file-export-html
 * @author     Catalyst IT Ltd
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25
26
27
28
29
30
31
32
33
34
35
 *
 */

defined('INTERNAL') || die();

/**
 * TODO:
 *  - handle exporting when there's no files/folders
 */
class HtmlExportFile extends HtmlExportArtefactPlugin {

36
    private $artefactdata = array();
37
    private $owner;
38

39
40
41
42
    // Keep track of files not owned by the exporting user.  These should be included in the
    // export tarball, but should not appear in the browseable folder structure.
    private $otherfiles = array();

43
    public function dump_export_data() {
44
45
46

        $this->owner = $this->exporter->get('user')->get('id');

47
48
        foreach ($this->exporter->get('artefacts') as $artefact) {
            if (in_array($artefact->get('artefacttype'), PluginArtefactFile::get_artefact_types())) {
49
50
51
52
53
                $id = $artefact->get('id');
                $this->artefactdata[$id] = $artefact;
                if ($artefact->get('owner') != $this->owner) {
                    $this->otherfiles[$id] = $id;
                }
54
55
56
            }
        }

57
        // Grab all parent folders of all artefacts owned by the exporting user, so we can export
58
59
60
61
        // the files in their correct folder location
        if ($this->exporter->get('artefactexportmode') != PluginExport::EXPORT_ALL_ARTEFACTS && $this->artefactdata) {
            $folderids = array();
            foreach (array_keys($this->artefactdata) as $artefactid) {
62
                if (!isset($this->otherfiles[$artefactid])) {
63
64
                    $folderids = array_merge($folderids, array_keys(artefact_get_parents_for_cache($artefactid)));
                }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
            }
            $folderids = array_unique($folderids);

            foreach ($folderids as $folderid) {
                if (!isset($this->artefactdata[$folderid])) {
                    $artefact = artefact_instance_from_id($folderid);
                    // We grabbed all parents of the artefacts in the export, 
                    // but not all parents are folders
                    if ($artefact->get('artefacttype') == 'folder') {
                        $this->artefactdata[$folderid] = $artefact;
                    }
                }
            }

79
        }
80
81
82
83
84

        $this->populate_profileicons();
        $this->create_index_for_directory($this->fileroot, 0, null);
        $this->populate_filedir($this->fileroot, 0, null);

85
86
87
88
89
90
91
92
93
94
        // Copy other users' files into the extrafileroot directory
        foreach ($this->otherfiles as $id) {
            if (!$this->artefactdata[$id] instanceof ArtefactTypeFile) {
                continue;
            }
            $dest = $this->extrafileroot . $id . '-' . PluginExportHtml::sanitise_path($this->artefactdata[$id]->get('title'));
            if (!copy($this->artefactdata[$id]->get_path(), $dest)) {
                throw new SystemException("Unable to copy artefact $id's file");
            }
        }
95
96
97
    }

    public function get_summary() {
98
        $smarty = $this->exporter->get_smarty();
99
100
        $smarty->assign('filecount', count(array_filter($this->artefactdata, create_function('$a', 'return $a->get("artefacttype") != "folder";'))));
        $smarty->assign('foldercount', count(array_filter($this->artefactdata, create_function('$a', 'return $a->get("artefacttype") == "folder";'))));
101
102
        $smarty->assign('spaceused', $this->exporter->get('user')->get('quotaused'));

103
        return array(
104
105
            'title' => get_string('Files', 'artefact.file'),
            'description' => $smarty->fetch('export:html/file:summary.tpl'),
106
107
108
        );
    }

109
110
111
112
    public function get_summary_weight() {
        return 20;
    }

113
114
115
116
117
118
    /**
     * Puts all profile icons in the static/profileicons/ directory
     */
    private function populate_profileicons() {
        $profileiconsdir = $this->exporter->get('exportdir') . '/' . $this->exporter->get('rootdir') . '/static/profileicons/';
        $removekeys = array();
119
120
121
        foreach ($this->artefactdata as $artefactid => $artefact) {
            if ($artefact->get('artefacttype') == 'profileicon') {
                $removekeys[] = $artefactid;
122

123
                if (!copy($artefact->get_path(), $profileiconsdir . PluginExportHtml::sanitise_path($artefact->get('title')))) {
124
                    throw new SystemException("Unable to copy profile icon $artefactid into export");
125
126
127
128
                }

                // Make sure we grab a nicely resized version too
                $maxdimension = 200;
129
                $resizedpath = get_dataroot_image_path('artefact/file/profileicons/', $artefactid, $maxdimension);
130
                if (!copy($resizedpath, $profileiconsdir . $maxdimension . 'px-' . PluginExportHtml::sanitise_path($artefact->get('title')))) {
131
                    throw new SystemException("Unable to copy resized profile icon {$maxdimension}px-{$artefact->get('title')} into export");
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
                }
            }
        }
    }

    /**
     * Given a filesystem directory and the id of an artefact, fill the 
     * filesystem directory with the files and folders that Mahara considers 
     * are inside the artefact.
     *
     * This method is recursive, creating the file/directory structure for all 
     * directories under the one passed.
     *
     * This method also creates index.htmls in each directory created.
     *
     * @param string $filesystemdirectory The file system directory to populate
     * @param int    $level               How deep the directory is
     * @param int    $parentid            The folder to start from - can be null
     */
    private function populate_filedir($filesystemdirectory, $level, $parentid) {
152
        foreach ($this->artefactdata as $artefactid => $artefact) {
153
            if ($artefact->get('parent') == $parentid && $artefact->get('owner') == $this->owner) {
154
                if ($artefact->get('artefacttype') == 'folder') {
155
                    $directory = $filesystemdirectory . PluginExportHtml::sanitise_path($artefact->get('title')) . '/';
156
                    check_dir_exists($directory);
157
158
                    $this->create_index_for_directory($directory, $level + 1, $artefact);
                    $this->populate_filedir($directory, $level + 1, $artefactid);
159
160
                }
                else {
161
                    $artefact = artefact_instance_from_id($artefactid);
162
163
                    if (!$artefact->get_path() || !copy($artefact->get_path(), $filesystemdirectory . PluginExportHtml::sanitise_path($artefact->get('title')))) {
                        throw new SystemException(get_string('nonexistentfile', 'export', $artefact->get('title')));
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
                    }
                }
            }
        }
    }

    /**
     * Given a filesystem directory and the artefact data corresponding to that 
     * directory, creates an index.html for it.
     *
     * @param string $filesystemdirectory The file system directory to make the 
     *                                    index.html inside
     * @param int    $level               How deep this directory index is
     * @param object $artefactdata        Artefact data relating to the folder 
     *                                    represented by this directory
     */
180
    private function create_index_for_directory($filesystemdirectory, $level, ArtefactTypeFolder $artefact=null) {
181
        $smarty = $this->exporter->get_smarty(str_repeat('../', $level + 2), 'file');
182
        $smarty->assign('page_heading', get_string('Files', 'artefact.file'));
Nigel McNie's avatar
Nigel McNie committed
183
        $smarty->assign('breadcrumbs', array(array('text' => 'Files', 'path' => 'index.html')));
184

185
186
        if ($artefact) {
            $smarty->assign('folder', ArtefactTypeFileBase::get_full_path($artefact->get('id'), $this->artefactdata));
187
188
189
190
191
        }
        else {
            $smarty->assign('folder', '/');
        }

192
193
194
        $id = ($artefact) ? $artefact->get('id') : null;
        $smarty->assign('folders', $this->prepare_artefacts_for_smarty($id, true));
        $smarty->assign('files',   $this->prepare_artefacts_for_smarty($id, false));
195
196
197

        $content = $smarty->fetch('export:html/file:index.tpl');
        if (false === file_put_contents($filesystemdirectory . 'index.html', $content)) {
198
            throw new SystemException("Unable to create index.html for directory $id");
199
200
        }
    }
201
202
203
204
205
206
207
208
209
210
211
212
213

    /**
     * Helper to convert artefacts into smarty-friendly data
     *
     * @param int $parent   The ID of the parent folder for the artefact to 
     *                      convert
     * @param bool $folders True to get folders, false to get everything but 
     *                      folders
     */
    private function prepare_artefacts_for_smarty($parent, $folders) {
        $data = array();
        $equality = ($folders) ? '==' : '!=';
        $parent = (is_null($parent)) ? 'null': intval($parent);
214
215
216
217
218
        $artefacts = array_filter($this->artefactdata, create_function('$a',
            'return $a->get("parent") == ' . $parent
            . ' && $a->get("artefacttype") ' . $equality . ' "folder"'
            . ' && $a->get("owner") == ' . $this->owner . ';'
        ));
219
        foreach ($artefacts as $artefact) {
220
221
222
223
224
            $size = '';
            if ($artefact->get('artefacttype') != 'folder') {
                $size = $artefact->get('size');
                $size = ($size) ? display_size($size) : '';
            }
225
226
227
            $data[] = array(
                'icon'        => '',
                'title'       => $artefact->get('title'),
228
                'path'        => PluginExportHtml::sanitise_path($artefact->get('title')),
229
230
231
232
233
234
235
236
                'description' => $artefact->get('description'),
                'size'        => $size,
                'date'        => strftime(get_string('strftimedaydatetime'), $artefact->get('ctime')),
            );
        }

        return $data;
    }
237

238
}