lib.php 12.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php
/**
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
 * Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
 *
 * 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-blog-import-leap
 * @author     Catalyst IT Ltd
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
 * @copyright  (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
 *
 */

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

/**
 * Implements LEAP2A import of blog related entries into Mahara
 *
 * For more information about LEAP blog importing, see:
 * http://wiki.mahara.org/Developer_Area/Import%2f%2fExport/LEAP_Import/Blog_Artefact_Plugin
 *
 * TODO:
 * - Get entries that feel they're part of the blog, not just entries the blog feels are part of it
 * - Import raw ATOM feed entries as blog posts
 * - Provide a default strategy for importing anything into a 'miscellaneous' blog
 * - Handle importing things that don't have inline entry content into a blogpost
 */
class LeapImportBlog extends LeapImportArtefactPlugin {

    /**
     * Import an entry as a blog, with associated blog posts and attachments
     */
    const STRATEGY_IMPORT_AS_BLOG = 1;

    /**
     * Import entry as an simple blog post into a catch-all blog
     */
    const STRATEGY_IMPORT_AS_ENTRY = 2;

    public static function get_import_strategies_for_entry(SimpleXMLElement $entry, PluginImport $importer) {
        $strategies = array();

        // TODO: when the xpath has an error in it, count(error) == 1 also.. so should check return type
        $correctrdftype = count($entry->xpath('rdf:type['
            . $importer->curie_xpath('@rdf:resource', PluginImportLeap::NS_LEAPTYPE, 'selection') . ']')) == 1;
        $correctcategoryscheme = count($entry->xpath('a:category[('
            . $importer->curie_xpath('@scheme', PluginImportLeap::NS_CATEGORIES, 'selection_type#') . ') and @term="Blog"]')) == 1;

        if ($correctrdftype && $correctcategoryscheme) {
            $otherrequiredentries = array();

            // Get entries that this blog feels are a part of it
            foreach ($entry->link as $link) {
                if ($importer->curie_equals($link['rel'], PluginImportLeap::NS_LEAP, 'has_part') && isset($link['href'])) {
                    $otherrequiredentries[] = (string)$link['href'];
                }
            }

            // TODO: Get entries that feel they should be a part of this blog. 
            // We can compare the lists and perhaps warn if they're different
            //    $otherentries = $importer->xml->xpath('//a:feed/a:entry/a:link[@rel="leap:is_part_of" and @href="' . $entryid . '"]/../a:id');

            $otherrequiredentries = array_unique($otherrequiredentries);
            $strategies[] = array(
                'strategy' => self::STRATEGY_IMPORT_AS_BLOG,
                'score'    => 100,
                'other_required_entries' => $otherrequiredentries,
            );
        }
        else {
            // The blog can import any entry as a literal blog post
            $strategies[] = array(
                'strategy' => self::STRATEGY_IMPORT_AS_ENTRY,
                'score'    => 10,
                'other_required_entries' => array(),
            );
        }

        return $strategies;
    }

    public static function import_using_strategy(SimpleXMLElement $entry, PluginImport $importer, $strategy, array $otherentries) {
        $artefactmapping = array();
        switch ($strategy) {
        case self::STRATEGY_IMPORT_AS_BLOG:
            // First, the blog
            $blog = new ArtefactTypeBlog();
            $blog->set('title', (string)$entry->title);
            $blog->set('description', PluginImportLeap::get_entry_content($entry, $importer));
            $blog->set('owner', $importer->get('usr'));
            if ($published = strtotime((string)$entry->published)) {
                $blog->set('ctime', $published);
            }
            if ($updated = strtotime((string)$entry->updated)) {
                $blog->set('mtime', $updated);
            }
            $blog->set('tags', PluginImportLeap::get_entry_tags($entry));
            $blog->commit();
            $artefactmapping[(string)$entry->id] = array($blog->get('id'));

            // Then, the blog posts
            foreach ($otherentries as $entryid) {
                $blogentry = $importer->get_entry_by_id($entryid);
                if (!$blogentry) {
                    // TODO: what to do here? Also - should this be checked here or earlier?
                    $importer->trace("WARNING: Blog $entry->id claims to have part $entryid which doesn't exist");
                    continue;
                }

                $artefactmapping[$entryid] = self::create_blogpost($blogentry, $importer, $blog->get('id'));
            }
            break;
        case self::STRATEGY_IMPORT_AS_ENTRY:
            $blogid = self::ensure_catchall_blog($importer);
            $artefactmapping[(string)$entry->id] = self::create_blogpost($entry, $importer, $blogid);
            break;
        default:
            throw new ImportException($importer, 'TODO: get_string: unknown strategy chosen for importing entry');
        }
        return $artefactmapping;
    }

    /**
     * Attaches files to blog posts
     *
     * We look at the leap relationships to add attachments. Currently this 
     * looks explicitly for the has_attachment relationship.
     *
     * If importing an entry resulted in importing a new file (caused by the 
     * entry having out-of-line content), we attach that file to the entry.
     */
    public static function setup_relationships(SimpleXMLElement $entry, PluginImport $importer, $strategy, array $otherentries) {
        switch ($strategy) {
        case self::STRATEGY_IMPORT_AS_BLOG:
            foreach ($otherentries as $entryid) {
                $blogpostentry = $importer->get_entry_by_id($entryid);
                // Get all attachments this blogpost things are attached to it
                // TODO: get all entries that think they're attached to the blogpost.
                // I think we can only look for files, Mahara doesn't understand 
                // attaching something that isn't a file to a blogpost
                foreach ($blogpostentry->link as $blogpostlink) {
                    $blogpost = null;
                    if ($importer->curie_equals($blogpostlink['rel'], PluginImportLeap::NS_LEAP, 'has_attachment') && isset($blogpostlink['href'])) {

                        if (!$blogpost) {
                            $artefactids = $importer->get_artefactids_imported_by_entryid((string)$blogpostentry->id);
                            $blogpost = new ArtefactTypeBlogPost($artefactids[0]);
                        }
                        $importer->trace("Attaching file $blogpostlink[href] to blog post $blogpostentry->id", PluginImportLeap::LOG_LEVEL_VERBOSE);
                        $artefactids = $importer->get_artefactids_imported_by_entryid((string)$blogpostlink['href']);
                        $blogpost->attach_file($artefactids[0]);
                    }
                    if ($blogpost) {
                        $blogpost->commit();
                    }
                }

                self::setup_outoflinecontent_relationship($blogpostentry, $importer);
            }
            break;
        case self::STRATEGY_IMPORT_AS_ENTRY:
175
            self::setup_outoflinecontent_relationship($entry, $importer);
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
            break;
        default:
            throw new ImportException($importer, 'TODO: get_string: unknown strategy chosen for importing entry');
        }
    }

    /**
     * Creates a catch-all blog if one doesn't exist already
     *
     * @param PluginImportLeap $importer The importer
     * @return int The artefact ID of the catch-all blog
     */
    private static function ensure_catchall_blog(PluginImportLeap $importer) {
        static $blogid = null;
        if (is_null($blogid)) {
            $time = time(); // TODO maybe the importer will get a time field to record time of import
            $blog = new ArtefactTypeBlog();
            $title = $importer->get('xml')->xpath('//a:feed/a:title');
Nigel McNie's avatar
Nigel McNie committed
194
195
            $blog->set('title', get_string('dataimportedfrom', 'artefact.blog', (string)$title[0]));
            $blog->set('description', get_string('entriesimportedfromleapexport', 'artefact.blog'));
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
            $blog->set('owner', $importer->get('usr'));
            $blog->set('ctime', $time);
            $blog->set('mtime', $time);
            $blog->commit();
            $blogid = $blog->get('id');
        }

        return $blogid;
    }

    /**
     * Creates a blogpost from the given entry
     *
     * @param SimpleXMLElement $entry    The entry to create the blogpost from
     * @param PluginImportLeap $importer The importer
     * @param int $blogid                The blog in which to put the post
     * @return array A list of artefact IDs created, to be used with the artefact mapping. 
     *               There will either be one (the blogpost ID), or two. If there is two, the 
     *               second one will be the ID of the file created to hold the out-of-line 
     *               content associated with the blogpost
     */
    private static function create_blogpost(SimpleXMLElement $entry, PluginImportLeap $importer, $blogid) {
        $createdartefacts = array();
        $blogpost = new ArtefactTypeBlogPost();
        $blogpost->set('title', (string)$entry->title);
        // If the entry has out of line content, we import that separately as a 
        // file and set the content to refer to it
        if (isset($entry->content['src']) && isset($entry->content['type'])) {
            $file = LeapImportFile::create_file($entry, $importer);
            $createdartefacts[] = $file->get('id');

227
            $content = '<a href="' . get_config('wwwroot') . 'artefact/file/download.php?file=' . $file->get('id') . '"'
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
                . ' title="' . hsc($file->get('title')) . '">';
            if (is_image_mime_type($file->get('filetype'))) {
                $content .= '<img src="' . get_config('wwwroot') 
                    . 'artefact/file/download.php?file=' . $file->get('id') . '&amp;maxwidth=500&amp;maxheight=500"'
                    . ' alt="' . hsc($file->get('title')) . '">';
            }
            $content .= '</a>';
            $blogpost->set('description', $content);
        }
        else {
            $blogpost->set('description', PluginImportLeap::get_entry_content($entry, $importer));
        }
        if ($published = strtotime((string)$entry->published)) {
            $blogpost->set('ctime', $published);
        }
        if ($updated = strtotime((string)$entry->updated)) {
            $blogpost->set('mtime', $updated);
        }

        $draftpost = count($entry->xpath('a:category[('
            . $importer->curie_xpath('@scheme', PluginImportLeap::NS_CATEGORIES, 'readiness#')
            . ') and @term="Unready"]')) == 1;
        $blogpost->set('published', $draftpost ? 0 : 1);

        $blogpost->set('owner', $importer->get('usr'));
        $blogpost->set('parent', $blogid);
        $blogpost->set('tags', PluginImportLeap::get_entry_tags($entry));
        $blogpost->commit();
        array_unshift($createdartefacts, $blogpost->get('id'));

        return $createdartefacts;
    }

    /**
     * Checks to see if a blogpost had out-of-line content, and if it did, 
     * attaches the generated file to it
     *
     * @param SimpleXMLElement $entry    The entry to check
     * @param PluginImportLeap $importer The importer
     */
    private static function setup_outoflinecontent_relationship(SimpleXMLElement $entry, PluginImportLeap $importer) {
        $artefactids = $importer->get_artefactids_imported_by_entryid((string)$entry->id);
        if (count($artefactids) == 2) {
            // In this case, a file was created as a result of 
            // importing a blog entry with out-of-line content. We 
            // attach the file to this post.
            $blogpost = new ArtefactTypeBlogPost($artefactids[0]);
            $blogpost->attach_file($artefactids[1]);
            $blogpost->commit();
        }
    }

}

?>