08ccb7fa69af86a9d6c2ef22f87069cf05f47812
[redakcja.git] / apps / catalogue / management / commands / make_master.py
1 # -*- coding: utf-8 -*-
2
3 from django.core.management.base import BaseCommand
4 from django.core.management.color import color_style
5 from django.utils.encoding import smart_text
6 from catalogue.management.prompt import confirm
7 from catalogue.models import Book
8 from optparse import make_option
9 from datetime import date
10 import re
11 from slughifi import slughifi
12 from lxml import etree
13 from librarian import WLURI
14
15
16 dc_fixed = {
17     'description': u'Publikacja zrealizowana w ramach projektu Cyfrowa Przyszłość (http://edukacjamedialna.edu.pl).',
18     'rights': u'Creative Commons Uznanie autorstwa - Na tych samych warunkach 3.0',
19     'rights_license': u'http://creativecommons.org/licenses/by-sa/3.0/',
20     }
21
22 dc_namespaces = { "dc": "http://purl.org/dc/elements/1.1/" }
23
24 class Command(BaseCommand):
25     option_list = BaseCommand.option_list + (
26         make_option('-s', '--slug', dest='slug', help="Slug for master module (if empty will be generated from title)"),
27         make_option('-F', '--file', dest='slugs_file', help="file with child module titles per line"),
28         make_option('-t', '--title', dest='title', default='', help="title of master module"),
29         make_option('-l', '--level', dest='audience', default='', help='Audience level'),
30     )
31     help = 'Create a master module skeleton'
32
33     def looks_like_synthetic(self, title):
34         if re.match(r"^(gim|lic)_\d[.]? ", title):
35             return True
36         return False
37
38     def adopt(self, child, master, typ_, audience_, commit_args):
39         fc = child[0]
40         txt = fc.materialize()
41         changed = False
42         try:
43             t = etree.fromstring(txt)
44         except etree.XMLSyntaxError, e:
45             print "cannot read xml in part: %s" % child.slug
46             print unicode(e)
47             return
48         wluri = WLURI(t.xpath("//dc:identifier.url", namespaces=dc_namespaces)[0].text)
49         typ = t.xpath("//dc:type", namespaces=dc_namespaces)
50         if not typ:
51             print "no type in DC, inserting under format" 
52             fmt = t.xpath("//dc:format", namespaces=dc_namespaces)
53             container = fmt.getparent()
54             typ = etree.SubElement(container, etree.QName('dc', 'type'))
55             container.insert(typ, container.index(fmt)+1)
56             changed = True
57         else:
58             typ = typ[0]
59         if typ.text != typ_:
60             print "type is '%s', setting to '%s'" % (typ.text, typ_)
61             changed = True
62             typ.text = typ_
63         #audience = t.xpath("//dc:audience", namespaces=dc_namespaces)[0]
64         #if audience.text != audience_:
65         #    print "audience is '%s', setting to '%s'" % (audience.text, audience_)
66         #    changed = True
67         #    audience.text = audience_
68         if changed:
69             print "will commit."
70             fc.commit(etree.tostring(t, encoding=unicode), **commit_args)
71         return wluri
72
73
74     def gen_xml(self, options, synthetic_modules=[], course_modules=[], project_modules=[]):
75         holder = {}
76         holder['xml'] = u""
77         slug = options['slug']
78         if not slug:
79             slug = slughifi(options['title'])
80
81         def p(t):
82             holder['xml'] += u"%s\n" % t
83
84         def dc(k, v):
85             v = smart_text(v)
86             p(u'<dc:%s xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">%s</dc:%s>' % (k, v, k))
87
88         def t(tag, ct):
89             p(u'<%s>%s</%s>' % (tag, ct, tag))
90
91         def slug_url(slug):
92             return u"http://edukacjamedialna/%s/" % slug
93
94         p("<utwor>")
95         p(u'<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">')
96         p(u'<rdf:Description rdf:about="http://redakcja.edukacjamedialna.edu.pl/documents/">')
97
98         dc(u'title', options['title'])
99         for s in synthetic_modules:
100             dc(u'relation.hasPart', unicode(s))
101         for s in course_modules:
102             dc(u'relation.hasPart', unicode(s))
103         for s in project_modules:
104             dc(u'relation.hasPart', unicode(s))
105         dc(u'publisher', u'Fundacja Nowoczesna Polska')
106         #        dc(u'subject.competence', meta.get(u'Wybrana kompetencja z Katalogu', u''))
107         #        dc(u'subject.curriculum', meta.get(u'Odniesienie do podstawy programowej', u''))
108         ## for keyword in meta.get(u'Słowa kluczowe', u'').split(u','):
109         ##     keyword = keyword.strip()
110         ##     dc(u'subject', keyword)
111         dc(u'description', dc_fixed['description'])
112         dc(u'identifier.url', u'http://edukacjamedialna.edu.pl/%s' % slug)
113         dc(u'rights', dc_fixed['rights'])
114         dc(u'rights.license', dc_fixed['rights_license'])
115         dc(u'format', u'xml')
116         dc(u'type', u'section')
117         dc(u'date', date.strftime(date.today(), "%Y-%m-%d"))
118         dc(u'language', u'pol')
119         p(u'</rdf:Description>')
120         p(u'</rdf:RDF>')
121         p(u'</utwor>')
122
123         return holder['xml']
124
125     def handle(self, *args, **options):
126         commit_args = {
127             "author_name": 'Platforma',
128             "description": 'Automatycznie zaimportowane z EtherPad',
129             "publishable": False,
130         }
131
132         slug = options['slug']
133         if not slug:
134             slug = slughifi(options['title'])
135         existing = Book.objects.filter(slug=slug)
136
137         master = None
138         if existing:
139             overwrite = confirm("%s exists. Overwrite?" % slug, True)
140             if not overwrite:
141                 return
142             master = existing[0]
143         else:
144             master = Book()
145         master.slug = slug
146         master.title = options['title']
147         master.save()
148
149         if len(master) == 0:
150             master.add(slug, options['title'])
151
152         synthetic_modules = []
153         course_modules = []
154         if 'slugs_file' in options:
155             f = open(options['slugs_file'], 'r')
156             try:
157                 titles = [l.strip() for l in f.readlines()]
158
159                 for t in titles:
160                     if not t: continue
161                     try:
162                         b = Book.objects.get(title=t)
163                     except Book.DoesNotExist:
164                         print "Book for title %s does not exist" % t
165                         continue
166                     if self.looks_like_synthetic(t):
167                         wlurl = self.adopt(b, master, 'synthetic', options['audience'], commit_args)
168                         synthetic_modules.append(wlurl)
169                     else:
170                         wlurl = self.adopt(b, master, 'course', options['audience'], commit_args)
171                         course_modules.append(wlurl)
172             except Exception, e:
173                 print "Error getting slug list (file %s): %s" % (options['slugs_file'], e)
174
175         print "synthetic: %s" % [unicode(z) for z in synthetic_modules]
176         print "course: %s" % [unicode(z) for z in course_modules]
177
178         xml = self.gen_xml(options, synthetic_modules, course_modules)
179         c = master[0]
180         print xml
181         if confirm("Commit?", True):
182             c.commit(xml, **commit_args)
183