def save(self, knowl, who, most_recent=None, minor=False): """who is the ID of the user, who wants to save the knowl""" if most_recent is None: most_recent = self.get_knowl(knowl.id, ['id'] + self._default_fields, allow_deleted=False) new_knowl = most_recent is None if new_knowl: authors = [] else: authors = most_recent.pop('authors', []) if not minor and who and who not in authors: authors = authors + [who] search_keywords = make_keywords(knowl.content, knowl.id, knowl.title) cat = extract_cat(knowl.id) # When renaming, source is set explicitly on the knowl if knowl.type == 0 and knowl.source is not None: typ, source, name = 0, knowl.source, knowl.source_name else: typ, source, name = extract_typ(knowl.id) links = extract_links(knowl.content) defines = extract_defines(knowl.content) # id, authors, cat, content, last_author, timestamp, title, status, type, links, defines, source, source_name values = (knowl.id, authors, cat, knowl.content, who, knowl.timestamp, knowl.title, knowl.status, typ, links, defines, source, name, search_keywords) with DelayCommit(self): inserter = SQL("INSERT INTO kwl_knowls (id, {0}, _keywords) VALUES ({1})") inserter = inserter.format(SQL(', ').join(map(Identifier, self._default_fields)), SQL(", ").join(Placeholder() * (len(self._default_fields) + 2))) self._execute(inserter, values) self.cached_titles[knowl.id] = knowl.title
def actually_rename(self, knowl, new_name=None): if new_name is None: new_name = knowl.source_name if new_name is None: raise ValueError("You must either call start_rename or provide the new name") with DelayCommit(self): new_cat = extract_cat(new_name) updator = SQL("UPDATE kwl_knowls SET (id, cat) = (%s, %s) WHERE id = %s") self._execute(updator, [new_name, new_cat, knowl.id]) # Remove source and source_name from all versions updator = SQL("UPDATE kwl_knowls SET (source, source_name) = (%s, %s) WHERE id = %s") self._execute(updator, [None, None, new_name]) # Only have to update keywords for most recent version and most recent reviewed version updator = SQL("UPDATE kwl_knowls SET _keywords = %s WHERE id = %s AND timestamp = %s") self._execute(updator, [make_keywords(knowl.content, new_name, knowl.title), new_name, knowl.timestamp]) if knowl.reviewed_timestamp and knowl.reviewed_timestamp != knowl.timestamp: self._execute(updator, [make_keywords(knowl.reviewed_content, new_name, knowl.reviewed_title), new_name, knowl.reviewed_timestamp]) referrers = self.ids_referencing(knowl.id, old=True) updator = SQL("UPDATE kwl_knowls SET (content, links) = (regexp_replace(content, %s, %s, %s), array_replace(links, %s, %s)) WHERE id = ANY(%s)") values = [r"""['"]\s*{0}\s*['"]""".format(knowl.id.replace('.', r'\.')), "'{0}'".format(new_name), 'g', knowl.id, new_name, referrers] # g means replace all self._execute(updator, values) if knowl.id in self.cached_titles: self.cached_titles[new_name] = self.cached_titles.pop(knowl.id) knowl.id = new_name
def start_rename(self, knowl, new_name, who): """ Create a copy of knowl in the database with the new name. Raises a ValueError if * the knowl is a comment or annotation * there is a renaming that already includes this knowl * the new name already exists The calling function should check that new_name is an acceptable knowl id. """ if knowl.type != 0: raise ValueError("Only normal knowls can be renamed.") if knowl.source is not None or knowl.source_name is not None: raise ValueError( "This knowl is already involved in a rename. Use undo_rename or actually_rename instead." ) if self.knowl_exists(new_name): raise ValueError("A knowl with id %s already exists." % new_name) updater = SQL( "UPDATE kwl_knowls SET (source, source_name) = (%s, %s) WHERE id = %s AND timestamp = %s" ) old_name = knowl.id with DelayCommit(self): self._execute(updater, [old_name, new_name, old_name, knowl.timestamp]) new_knowl = knowl.copy(ID=new_name, timestamp=datetime.utcnow(), source=knowl.id) new_knowl.save(who, most_recent=knowl, minor=True)