diff --git a/NEWS.mdtext b/NEWS.mdtext index b54bf3c..3d826ed 100644 --- a/NEWS.mdtext +++ b/NEWS.mdtext @@ -3,6 +3,9 @@ The development of this version of Indefero has partially been sponsored by the friendly folks from Scilab ! +ATTENTION: You need Pluf [4121ca4](http://projects.ceondo.com/p/pluf/source/commit/4121ca4) +or newer to properly run this version of Indefero! + ## Changes - Indefero's post-commit web hook now by default issues HTTP PUT instead of diff --git a/src/IDF/Form/WikiCreate.php b/src/IDF/Form/WikiCreate.php index df1f966..9c06c75 100644 --- a/src/IDF/Form/WikiCreate.php +++ b/src/IDF/Form/WikiCreate.php @@ -107,9 +107,9 @@ Add your content here. Format your content with: if (preg_match('/[^a-zA-Z0-9\-]/', $title)) { throw new Pluf_Form_Invalid(__('The title contains invalid characters.')); } - $sql = new Pluf_SQL('project=%s AND title=%s', + $sql = new Pluf_SQL('project=%s AND title=%s', array($this->project->id, $title)); - $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen())); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); if ($pages->count() > 0) { throw new Pluf_Form_Invalid(__('A page with this title already exists.')); } @@ -137,7 +137,7 @@ Add your content here. Format your content with: $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); if (strpos($this->cleaned_data['label'.$i], ':') !== false) { list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); - list($class, $name) = array(mb_strtolower(trim($class)), + list($class, $name) = array(mb_strtolower(trim($class)), trim($name)); } else { $class = 'other'; @@ -181,9 +181,9 @@ Add your content here. Format your content with: $tags[] = IDF_Tag::add($name, $this->project, $class); } } - } + } // Create the page - $page = new IDF_WikiPage(); + $page = new IDF_Wiki_Page(); $page->project = $this->project; $page->submitter = $this->user; $page->summary = trim($this->cleaned_data['summary']); @@ -193,7 +193,7 @@ Add your content here. Format your content with: $page->setAssoc($tag); } // add the first revision - $rev = new IDF_WikiRevision(); + $rev = new IDF_Wiki_PageRevision(); $rev->wikipage = $page; $rev->content = $this->cleaned_data['content']; $rev->submitter = $this->user; diff --git a/src/IDF/Form/WikiUpdate.php b/src/IDF/Form/WikiUpdate.php index 1b551c8..dae75f0 100644 --- a/src/IDF/Form/WikiUpdate.php +++ b/src/IDF/Form/WikiUpdate.php @@ -33,7 +33,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form public $project = null; public $page = null; public $show_full = false; - + public function initFields($extra=array()) { @@ -118,9 +118,9 @@ class IDF_Form_WikiUpdate extends Pluf_Form if (preg_match('/[^a-zA-Z0-9\-]/', $title)) { throw new Pluf_Form_Invalid(__('The title contains invalid characters.')); } - $sql = new Pluf_SQL('project=%s AND title=%s', + $sql = new Pluf_SQL('project=%s AND title=%s', array($this->project->id, $title)); - $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen())); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); if ($pages->count() > 0 and $pages[0]->id != $this->page->id) { throw new Pluf_Form_Invalid(__('A page with this title already exists.')); } @@ -148,7 +148,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); if (strpos($this->cleaned_data['label'.$i], ':') !== false) { list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); - list($class, $name) = array(mb_strtolower(trim($class)), + list($class, $name) = array(mb_strtolower(trim($class)), trim($name)); } else { $class = 'other'; @@ -229,7 +229,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form } $this->page->update(); // add the new revision - $rev = new IDF_WikiRevision(); + $rev = new IDF_Wiki_PageRevision(); $rev->wikipage = $this->page; $rev->content = $this->cleaned_data['content']; $rev->submitter = $this->user; diff --git a/src/IDF/Migrations/19WikiPageAssocs.php b/src/IDF/Migrations/19WikiPageAssocs.php new file mode 100644 index 0000000..8371f17 --- /dev/null +++ b/src/IDF/Migrations/19WikiPageAssocs.php @@ -0,0 +1,74 @@ +pfx.'idf_tag_idf_wiki_page_assoc', $intro->listTables())) { + echo '19 skipping up migration - relation table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wiki_page_assoc'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wiki_page_pluf_user_assoc'); + + if ($engine === 'PostgreSQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL'); + } +} + +function IDF_Migrations_19WikiPageAssocs_down($params=null) +{ + $engine = Pluf::f('db_engine'); + if (!in_array($engine, array('MySQL', 'PostgreSQL'))) { + throw new Exception('unsupported engine '.$engine); + } + + $db = Pluf::db(); + $intro = new Pluf_DB_Introspect($db); + if (in_array($db->pfx.'idf_tag_idf_wikipage_assoc', $intro->listTables())) { + echo '19 skipping down migration - relation table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wikipage_assoc'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wikipage_pluf_user_assoc'); + + if ($engine === 'PostgreSQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL'); + } +} diff --git a/src/IDF/Migrations/20AddWikiResources.php b/src/IDF/Migrations/20AddWikiResources.php new file mode 100644 index 0000000..20d82eb --- /dev/null +++ b/src/IDF/Migrations/20AddWikiResources.php @@ -0,0 +1,51 @@ +model = new IDF_Wiki_Resource(); + $schema->createTables(); + + $schema->model = new IDF_Wiki_ResourceRevision(); + $schema->createTables(); +} + +function IDF_Migrations_20AddWikiResources_down($params=null) +{ + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + + $schema->model = new IDF_Wiki_ResourceRevision(); + $schema->dropTables(); + + $schema->model = new IDF_Wiki_Resource(); + $schema->dropTables(); +} diff --git a/src/IDF/Migrations/21WikiPageRevisionName.php b/src/IDF/Migrations/21WikiPageRevisionName.php new file mode 100644 index 0000000..aca13d1 --- /dev/null +++ b/src/IDF/Migrations/21WikiPageRevisionName.php @@ -0,0 +1,56 @@ +pfx.'idf_wikipagerevs', $intro->listTables())) { + echo '21 skipping up migration - table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikirevisions RENAME TO '.$db->pfx.'idf_wikipagerevs'); +} + +function IDF_Migrations_21WikiPageRevisionName_down($params=null) +{ + $engine = Pluf::f('db_engine'); + if (!in_array($engine, array('MySQL', 'PostgreSQL'))) { + throw new Exception('unsupported engine '.$engine); + } + + $db = Pluf::db(); + $intro = new Pluf_DB_Introspect($db); + if (in_array($db->pfx.'idf_wikirevisions', $intro->listTables())) { + echo '21 skipping down migration - table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipagerevs RENAME TO '.$db->pfx.'idf_wikirevisions'); +} diff --git a/src/IDF/Migrations/7Wiki.php b/src/IDF/Migrations/7Wiki.php index 17e487a..5330d63 100644 --- a/src/IDF/Migrations/7Wiki.php +++ b/src/IDF/Migrations/7Wiki.php @@ -22,14 +22,14 @@ # ***** END LICENSE BLOCK ***** */ /** - * Add the download of files. + * Add wiki functionality. */ function IDF_Migrations_7Wiki_up($params=null) { $models = array( - 'IDF_WikiPage', - 'IDF_WikiRevision', + 'IDF_Wiki_Page', + 'IDF_Wiki_PageRevision', ); $db = Pluf::db(); $schema = new Pluf_DB_Schema($db); @@ -42,8 +42,8 @@ function IDF_Migrations_7Wiki_up($params=null) function IDF_Migrations_7Wiki_down($params=null) { $models = array( - 'IDF_WikiRevision', - 'IDF_WikiPage', + 'IDF_Wiki_PageRevision', + 'IDF_Wiki_Page', ); $db = Pluf::db(); $schema = new Pluf_DB_Schema($db); diff --git a/src/IDF/Migrations/Backup.php b/src/IDF/Migrations/Backup.php index 32fcb9e..60f6f78 100644 --- a/src/IDF/Migrations/Backup.php +++ b/src/IDF/Migrations/Backup.php @@ -43,8 +43,10 @@ function IDF_Migrations_Backup_run($folder, $name=null) 'IDF_IssueFile', 'IDF_Commit', 'IDF_Timeline', - 'IDF_WikiPage', - 'IDF_WikiRevision', + 'IDF_Wiki_Page', + 'IDF_Wiki_PageRevision', + 'IDF_Wiki_Resource', + 'IDF_Wiki_ResourceRevision', 'IDF_Review', 'IDF_Review_Patch', 'IDF_Review_Comment', @@ -90,8 +92,10 @@ function IDF_Migrations_Backup_restore($folder, $name) 'IDF_IssueFile', 'IDF_Commit', 'IDF_Timeline', - 'IDF_WikiPage', - 'IDF_WikiRevision', + 'IDF_Wiki_Resource', + 'IDF_Wiki_ResourceRevision', + 'IDF_Wiki_Page', + 'IDF_Wiki_PageRevision', 'IDF_Review', 'IDF_Review_Patch', 'IDF_Review_Comment', diff --git a/src/IDF/Migrations/Install.php b/src/IDF/Migrations/Install.php index aea5f00..cefdb30 100644 --- a/src/IDF/Migrations/Install.php +++ b/src/IDF/Migrations/Install.php @@ -40,8 +40,10 @@ function IDF_Migrations_Install_setup($params=null) 'IDF_IssueFile', 'IDF_Commit', 'IDF_Timeline', - 'IDF_WikiPage', - 'IDF_WikiRevision', + 'IDF_Wiki_Resource', + 'IDF_Wiki_ResourceRevision', + 'IDF_Wiki_Page', + 'IDF_Wiki_PageRevision', 'IDF_Review', 'IDF_Review_Patch', 'IDF_Review_Comment', @@ -97,8 +99,10 @@ function IDF_Migrations_Install_teardown($params=null) 'IDF_Review_Comment', 'IDF_Review_Patch', 'IDF_Review', - 'IDF_WikiRevision', - 'IDF_WikiPage', + 'IDF_Wiki_PageRevision', + 'IDF_Wiki_Page', + 'IDF_Wiki_ResourceRevision', + 'IDF_Wiki_Resource', 'IDF_Timeline', 'IDF_IssueFile', 'IDF_Search_Occ', diff --git a/src/IDF/Project.php b/src/IDF/Project.php index ddea3c5..a10d58b 100644 --- a/src/IDF/Project.php +++ b/src/IDF/Project.php @@ -427,13 +427,13 @@ GROUP BY uid"; $dep_ids = IDF_Views_Wiki::getDeprecatedPagesIds($this); $extra = ''; if (count($dep_ids)) { - $extra = ' AND idf_wikipage_id NOT IN ('.implode(', ', $dep_ids).') '; + $extra = ' AND idf_wiki_page_id NOT IN ('.implode(', ', $dep_ids).') '; } - $what_t = Pluf::factory('IDF_WikiPage')->getSqlTable(); - $asso_t = $this->_con->pfx.'idf_tag_idf_wikipage_assoc'; + $what_t = Pluf::factory('IDF_Wiki_Page')->getSqlTable(); + $asso_t = $this->_con->pfx.'idf_tag_idf_wiki_page_assoc'; $sql = 'SELECT '.$tag_t.'.id AS id, COUNT(*) AS nb_use FROM '.$tag_t.' '."\n". 'LEFT JOIN '.$asso_t.' ON idf_tag_id='.$tag_t.'.id '."\n". - 'LEFT JOIN '.$what_t.' ON idf_wikipage_id='.$what_t.'.id '."\n". + 'LEFT JOIN '.$what_t.' ON idf_wiki_page_id='.$what_t.'.id '."\n". 'WHERE idf_tag_id IS NOT NULL '.$extra.' AND '.$what_t.'.project='.$this->id.' GROUP BY '.$tag_t.'.id, '.$tag_t.'.class, '.$tag_t.'.name ORDER BY '.$tag_t.'.class ASC, '.$tag_t.'.name ASC'; } elseif ($what == 'downloads') { $dep_ids = IDF_Views_Download::getDeprecatedFilesIds($this); @@ -622,10 +622,10 @@ GROUP BY uid"; $stats = array(); $stats['total'] = 0; $what = array('downloads' => 'IDF_Upload', - 'reviews' => 'IDF_Review', - 'issues' => 'IDF_Issue', - 'docpages' => 'IDF_WikiPage', - 'commits' => 'IDF_Commit', + 'reviews' => 'IDF_Review', + 'issues' => 'IDF_Issue', + 'docpages' => 'IDF_Wiki_Page', + 'commits' => 'IDF_Commit', ); foreach ($what as $key=>$m) { $i = Pluf::factory($m)->getCount(array('filter' => 'project='.(int)$this->id)); @@ -755,7 +755,8 @@ GROUP BY uid"; Pluf_Signal::send('IDF_Project::preDelete', 'IDF_Project', $params); $what = array('IDF_Upload', 'IDF_Review', 'IDF_Issue', - 'IDF_WikiPage', 'IDF_Commit', 'IDF_Tag', + 'IDF_Wiki_Page', 'IDF_Wiki_Resource', + 'IDF_Commit', 'IDF_Tag', ); foreach ($what as $m) { foreach (Pluf::factory($m)->getList(array('filter' => 'project='.(int)$this->id)) as $item) { diff --git a/src/IDF/Template/Markdown.php b/src/IDF/Template/Markdown.php index 7ce47b1..895d511 100644 --- a/src/IDF/Template/Markdown.php +++ b/src/IDF/Template/Markdown.php @@ -69,7 +69,7 @@ class IDF_Template_Markdown extends Pluf_Template_Tag { $sql = new Pluf_SQL('project=%s AND title=%s', array($this->project->id, $m[2])); - $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen())); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); if ($pages->count() != 1 and $this->request->rights['hasWikiAccess'] and !$this->request->user->isAnonymous()) { return ' '.$m[1].''; diff --git a/src/IDF/Views/Project.php b/src/IDF/Views/Project.php index 1ea7718..e4a0dc8 100644 --- a/src/IDF/Views/Project.php +++ b/src/IDF/Views/Project.php @@ -68,7 +68,7 @@ class IDF_Views_Project $pages = array(); if ($request->rights['hasWikiAccess']) { $tags = IDF_Views_Wiki::getWikiTags($prj); - $pages = $tags[0]->get_idf_wikipage_list(); + $pages = $tags[0]->get_idf_wiki_page_list(); } return Pluf_Shortcuts_RenderToResponse('idf/project/home.html', array( @@ -131,8 +131,10 @@ class IDF_Views_Project } if (true === IDF_Precondition::accessWiki($request) && ($model_filter == 'all' || $model_filter == 'documents')) { - $classes[] = '\'IDF_WikiPage\''; - $classes[] = '\'IDF_WikiRevision\''; + $classes[] = '\'IDF_Wiki_Page\''; + $classes[] = '\'IDF_Wiki_PageRevision\''; + $classes[] = '\'IDF_Wiki_Resource\''; + $classes[] = '\'IDF_Wiki_ResourceRevision\''; } if (true === IDF_Precondition::accessReview($request) && ($model_filter == 'all' || $model_filter == 'reviews')) { diff --git a/src/IDF/Views/Wiki.php b/src/IDF/Views/Wiki.php index 6880f4c..2a837a7 100644 --- a/src/IDF/Views/Wiki.php +++ b/src/IDF/Views/Wiki.php @@ -40,7 +40,7 @@ class IDF_Views_Wiki $prj = $request->project; $title = sprintf(__('%s Documentation'), (string) $prj); // Paginator to paginate the pages - $pag = new Pluf_Paginator(new IDF_WikiPage()); + $pag = new Pluf_Paginator(new IDF_Wiki_Page()); $pag->class = 'recent-issues'; $pag->item_extra_props = array('project_m' => $prj, 'shortname' => $prj->shortname, @@ -82,13 +82,13 @@ class IDF_Views_Wiki { $prj = $request->project; if (!isset($request->REQUEST['q']) or trim($request->REQUEST['q']) == '') { - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', array($prj->shortname)); return new Pluf_HTTP_Response_Redirect($url); } $q = $request->REQUEST['q']; $title = sprintf(__('Documentation Search - %s'), $q); - $pages = new Pluf_Search_ResultSet(IDF_Search::mySearch($q, $prj, 'IDF_WikiPage')); + $pages = new Pluf_Search_ResultSet(IDF_Search::mySearch($q, $prj, 'IDF_Wiki_Page')); if (count($pages) > 100) { $pages->results = array_slice($pages->results, 0, 100); } @@ -133,7 +133,7 @@ class IDF_Views_Wiki // Paginator to paginate the pages $ptags = self::getWikiTags($prj); $dtag = array_pop($ptags); // The last tag is the deprecated tag. - $pag = new Pluf_Paginator(new IDF_WikiPage()); + $pag = new Pluf_Paginator(new IDF_Wiki_Page()); $pag->model_view = 'join_tags'; $pag->class = 'recent-issues'; $pag->item_extra_props = array('project_m' => $prj, @@ -179,10 +179,10 @@ class IDF_Views_Wiki )); if ($form->isValid() and !isset($request->POST['preview'])) { $page = $form->save(); - $urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + $urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', array($prj->shortname, $page->title)); $request->user->setMessage(sprintf(__('The page %s has been created.'), $urlpage, Pluf_esc($page->title))); - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', array($prj->shortname)); return new Pluf_HTTP_Response_Redirect($url); } elseif (isset($request->POST['preview'])) { @@ -214,9 +214,9 @@ class IDF_Views_Wiki { $prj = $request->project; // Find the page - $sql = new Pluf_SQL('project=%s AND title=%s', + $sql = new Pluf_SQL('project=%s AND title=%s', array($prj->id, $match[2])); - $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen())); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); if ($pages->count() != 1) { return new Pluf_HTTP_Response_NotFound($request); } @@ -224,7 +224,7 @@ class IDF_Views_Wiki $oldrev = false; // We grab the old revision if requested. if (isset($request->GET['rev']) and preg_match('/^[0-9]+$/', $request->GET['rev'])) { - $oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_WikiRevision', + $oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision', $request->GET['rev']); if ($oldrev->wikipage != $page->id or $oldrev->is_head == true) { return new Pluf_HTTP_Response_NotFound($request); @@ -260,7 +260,7 @@ class IDF_Views_Wiki public function deleteRev($request, $match) { $prj = $request->project; - $oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_WikiRevision', $match[2]); + $oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision', $match[2]); $page = $oldrev->get_wikipage(); $prj->inOr404($page); if ($oldrev->is_head == true) { @@ -269,7 +269,7 @@ class IDF_Views_Wiki if ($request->method == 'POST') { $oldrev->delete(); $request->user->setMessage(__('The old revision has been deleted.')); - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', array($prj->shortname, $page->title)); return new Pluf_HTTP_Response_Redirect($url); } @@ -300,9 +300,9 @@ class IDF_Views_Wiki { $prj = $request->project; // Find the page - $sql = new Pluf_SQL('project=%s AND title=%s', + $sql = new Pluf_SQL('project=%s AND title=%s', array($prj->id, $match[2])); - $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen())); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); if ($pages->count() != 1) { return new Pluf_HTTP_Response_NotFound($request); } @@ -317,17 +317,17 @@ class IDF_Views_Wiki $form = new IDF_Form_WikiUpdate($request->POST, $params); if ($form->isValid() and !isset($request->POST['preview'])) { $page = $form->save(); - $urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + $urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', array($prj->shortname, $page->title)); $request->user->setMessage(sprintf(__('The page %s has been updated.'), $urlpage, Pluf_esc($page->title))); - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', array($prj->shortname)); return new Pluf_HTTP_Response_Redirect($url); } elseif (isset($request->POST['preview'])) { $preview = $request->POST['content']; } } else { - + $form = new IDF_Form_WikiUpdate(null, $params); } return Pluf_Shortcuts_RenderToResponse('idf/wiki/update.html', @@ -350,7 +350,7 @@ class IDF_Views_Wiki public function delete($request, $match) { $prj = $request->project; - $page = Pluf_Shortcuts_GetObjectOr404('IDF_WikiPage', $match[2]); + $page = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_Page', $match[2]); $prj->inOr404($page); $params = array('page' => $page); if ($request->method == 'POST') { @@ -358,7 +358,7 @@ class IDF_Views_Wiki if ($form->isValid()) { $form->save(); $request->user->setMessage(__('The documentation page has been deleted.')); - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::index', array($prj->shortname)); return new Pluf_HTTP_Response_Redirect($url); } @@ -411,7 +411,7 @@ class IDF_Views_Wiki $sql = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($project->id, $dtag->id)); $ids = array(); - foreach (Pluf::factory('IDF_WikiPage')->getList(array('filter' => $sql->gen(), 'view' => 'join_tags')) + foreach (Pluf::factory('IDF_Wiki_Page')->getList(array('filter' => $sql->gen(), 'view' => 'join_tags')) as $file) { $ids[] = (int) $file->id; } @@ -425,7 +425,7 @@ class IDF_Views_Wiki { $conf = new IDF_Conf(); $conf->setProject($project); - $st = preg_split("/\015\012|\015|\012/", + $st = preg_split("/\015\012|\015|\012/", $conf->getVal('labels_wiki_predefined', IDF_Form_WikiConf::init_predefined), -1, PREG_SPLIT_NO_EMPTY); $auto = ''; foreach ($st as $s) { diff --git a/src/IDF/Wiki/Page.php b/src/IDF/Wiki/Page.php new file mode 100644 index 0000000..00965fd --- /dev/null +++ b/src/IDF/Wiki/Page.php @@ -0,0 +1,224 @@ +_a['table'] = 'idf_wikipages'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'wikipages', + ), + 'title' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('title'), + 'help_text' => __('The title of the page must only contain letters, digits or the dash character. For example: My-new-Wiki-Page.'), + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the page content.'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_wikipages', + ), + 'interested' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'model' => 'Pluf_User', + 'blank' => true, + 'verbose' => __('interested users'), + 'help_text' => 'Interested users will get an email notification when the wiki page is changed.', + ), + 'tags' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'IDF_Tag', + 'verbose' => __('labels'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + $table = $this->_con->pfx.'idf_tag_idf_wiki_page_assoc'; + $this->_a['views'] = array( + 'join_tags' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_wiki_page_id=id', + ), + ); + } + + function __toString() + { + return $this->title.' - '.$this->summary; + } + + function _toIndex() + { + $rev = $this->get_current_revision()->_toIndex(); + $str = str_repeat($this->title.' '.$this->summary.' ', 4).' '.$rev; + return Pluf_Text::cleanString(html_entity_decode($str, ENT_QUOTES, 'UTF-8')); + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + } + + function get_current_revision() + { + $true = Pluf_DB_BooleanToDb(true, $this->getDbConnection()); + $rev = $this->get_revisions_list(array('filter' => 'is_head='.$true, + 'nb' => 1)); + return ($rev->count() == 1) ? $rev[0] : null; + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function postSave($create=false) + { + // Note: No indexing is performed here. The indexing is + // triggered in the postSave step of the revision to ensure + // that the page as a given revision in the database when + // doing the indexing. + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter()); + } + } + + /** + * Returns an HTML fragment used to display this wikipage in the + * timeline. + * + * The request object is given to be able to check the rights and + * as such create links to other items etc. You can consider that + * if displayed, you can create a link to it. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + array($request->project->shortname, + $this->title)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($this->title), Pluf_esc($this->summary)).''; + $out .= "\n".' +
'.sprintf(__('Creation of page %s, by %s'), $url, Pluf_esc($this->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + array($request->project->shortname, + $this->title)); + $title = sprintf(__('%s: Documentation page %s added - %s'), + $request->project->name, + $this->title, $this->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'page' => $this, + 'rev' => $this->get_current_revision(), + 'create' => true, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment.xml'); + return $tmpl->render($context); + } +} \ No newline at end of file diff --git a/src/IDF/Wiki/PageRevision.php b/src/IDF/Wiki/PageRevision.php new file mode 100644 index 0000000..dd40a2b --- /dev/null +++ b/src/IDF/Wiki/PageRevision.php @@ -0,0 +1,294 @@ +_a['table'] = 'idf_wikipagerevs'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'wikipage' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Wiki_Page', + 'blank' => false, + 'verbose' => __('page'), + 'relate_name' => 'revisions', + ), + 'is_head' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'blank' => false, + 'default' => false, + 'help_text' => 'If this revision is the latest, we mark it as being the head revision.', + 'index' => true, + + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the changes.'), + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Compressed', + 'blank' => false, + 'verbose' => __('content'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + ), + 'changes' => + array( + 'type' => 'Pluf_DB_Field_Serialized', + 'blank' => true, + 'verbose' => __('changes'), + 'help_text' => 'Serialized array of the changes in the page.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + ); + $this->_a['idx'] = array( + 'creation_dtime_idx' => + array( + 'col' => 'creation_dtime', + 'type' => 'normal', + ), + ); + } + + function changedRevision() + { + return (is_array($this->changes) and count($this->changes) > 0); + } + + function _toIndex() + { + return $this->content; + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + $this->is_head = true; + } + } + + function postSave($create=false) + { + if ($create) { + // Check if more than one revision for this page. We do + // not want to insert the first revision in the timeline + // as the page itself is inserted. We do not insert on + // update as update is performed to change the is_head + // flag. + $sql = new Pluf_SQL('wikipage=%s', array($this->wikipage)); + $rev = Pluf::factory('IDF_Wiki_PageRevision')->getList(array('filter'=>$sql->gen())); + if ($rev->count() > 1) { + IDF_Timeline::insert($this, $this->get_wikipage()->get_project(), + $this->get_submitter()); + foreach ($rev as $r) { + if ($r->id != $this->id and $r->is_head) { + $r->is_head = false; + $r->update(); + } + } + } + $page = $this->get_wikipage(); + $page->update(); // Will update the modification timestamp. + IDF_Search::index($page); + } + } + + public function timelineFragment($request) + { + $page = $this->get_wikipage(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + array($request->project->shortname, + $page->title)); + $out = "\n".''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($page->title), Pluf_esc($this->summary)); + if ($this->changedRevision()) { + $out .= '
'; + $changes = $this->changes; + foreach ($changes as $w => $v) { + $out .= ''; + switch ($w) { + case 'lb': + $out .= __('Labels:'); break; + } + $out .= ' '; + if ($w == 'lb') { + $out .= Pluf_esc(implode(', ', $v)); + } else { + $out .= Pluf_esc($v); + } + $out .= ' '; + } + $out .= '
'; + } + $out .= ''; + $out .= "\n".' +
'.sprintf(__('Change of %s, by %s'), $url, Pluf_esc($page->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $page = $this->get_wikipage(); + if (!$this->is_head) { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + array($request->project->shortname, + $page->title), + array('rev' => $this->id)); + } else { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', + array($request->project->shortname, + $page->title)); + } + $title = sprintf(__('%s: Documentation page %s updated - %s'), + $request->project->name, + $page->title, $page->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'page' => $page, + 'rev' => $this, + 'create' => false, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment.xml'); + return $tmpl->render($context); + } + + + + /** + * Notification of change of a Wiki Page. + * + * The content of a WikiPage is in the IDF_WikiRevision object, + * this is why we send the notificatin from there. This means that + * when the create flag is set, this is for the creation of a + * wikipage and not, for the addition of a new revision. + * + * Usage: + *
+     * $this->notify($conf); // Notify the creation of a wiki page
+     * $this->notify($conf, false); // Notify the update of the page
+     * 
+ * + * @param IDF_Conf Current configuration + * @param bool Creation (true) + */ + public function notify($conf, $create=true) + { + $wikipage = $this->get_wikipage(); + $project = $wikipage->get_project(); + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $messageId = '<'.md5('wiki'.$wikipage->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + $recipients = $project->getNotificationRecipientsForTab('wiki'); + + foreach ($recipients as $address => $language) { + + if ($this->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'page' => $wikipage, + 'rev' => $this, + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + $tplfile = 'idf/wiki/wiki-created-email.txt'; + $subject = __('New Documentation Page %s - %s (%s)'); + $headers = array('Message-ID' => $messageId); + if (!$create) { + $tplfile = 'idf/wiki/wiki-updated-email.txt'; + $subject = __('Documentation Page Changed %s - %s (%s)'); + $headers = array('References' => $messageId); + } + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, + $address, + sprintf($subject, + $wikipage->title, + $wikipage->summary, + $project->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } +} diff --git a/src/IDF/Wiki/Resource.php b/src/IDF/Wiki/Resource.php new file mode 100644 index 0000000..1504682 --- /dev/null +++ b/src/IDF/Wiki/Resource.php @@ -0,0 +1,204 @@ +_a['table'] = 'idf_wikiresources'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'wikipages', + ), + 'title' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('title'), + 'help_text' => __('The title of the resource must only contain letters, digits, dots or the dash character. For example: my-resource.png.'), + ), + 'mime_type' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 100, + 'verbose' => __('MIME media type'), + 'help_text' => __('The MIME media type of the resource.'), + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the resource.'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_wikipages', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + } + + function __toString() + { + return $this->title.' - '.$this->summary; + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + } + + function get_current_revision() + { + $true = Pluf_DB_BooleanToDb(true, $this->getDbConnection()); + $rev = $this->get_revisions_list(array('filter' => 'is_head='.$true, + 'nb' => 1)); + return ($rev->count() == 1) ? $rev[0] : null; + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function postSave($create=false) + { + // Note: No indexing is performed here. The indexing is + // triggered in the postSave step of the revision to ensure + // that the page as a given revision in the database when + // doing the indexing. + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter()); + } + } + + /** + * Returns an HTML fragment used to display this resource in the + * timeline. + * + * The request object is given to be able to check the rights and + * as such create links to other items etc. You can consider that + * if displayed, you can create a link to it. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($request->project->shortname, + $this->title)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($this->title), Pluf_esc($this->summary)).''; + $out .= "\n".' +
'.sprintf(__('Creation of page %s, by %s'), $url, Pluf_esc($this->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($request->project->shortname, + $this->title)); + $title = sprintf(__('%s: Documentation page %s added - %s'), + $request->project->name, + $this->title, $this->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'page' => $this, + 'rev' => $this->get_current_revision(), + 'create' => true, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment.xml'); + return $tmpl->render($context); + } +} \ No newline at end of file diff --git a/src/IDF/Wiki/ResourceRevision.php b/src/IDF/Wiki/ResourceRevision.php new file mode 100644 index 0000000..e29b0c2 --- /dev/null +++ b/src/IDF/Wiki/ResourceRevision.php @@ -0,0 +1,186 @@ +_a['table'] = 'idf_wikiresourcerevs'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'wikiresource' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Wiki_Resource', + 'blank' => false, + 'verbose' => __('resource'), + 'relate_name' => 'revisions', + ), + 'is_head' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'blank' => false, + 'default' => false, + 'help_text' => 'If this revision is the latest, we mark it as being the head revision.', + 'index' => true, + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the changes.'), + ), + 'filesize' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'default' => 0, + 'verbose' => __('file size in bytes'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_downloads', + ), + 'pageusage' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'model' => 'IDF_Wiki_PageRevision', + 'blank' => true, + 'verbose' => __('page usage'), + 'help_text' => 'Records on which pages this resource revision is used.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + ); + } + + function __toString() + { + return sprintf(__('id %d: %s'), $this->id, $this->summary); + } + + function _toIndex() + { + return ''; + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } + + function postSave($create=false) + { + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter(), $this->creation_dtime); + } + } + + function getAbsoluteUrl($project) + { + return Pluf::f('url_upload').'/'.$project->shortname.'/files/'.$this->file; + } + + function getFullPath() + { + return(Pluf::f('upload_path').'/'.$this->get_project()->shortname.'/files/'.$this->file); + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->file); + } + + /** + * Returns the timeline fragment for the file. + * + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view', + array($request->project->shortname, + $this->id)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('Download %2$d, %3$s'), $url, $this->id, Pluf_esc($this->summary)).''; + $out .= ''; + $out .= "\n".' +
'.sprintf(__('Addition of download %d, by %s'), $url, $this->id, $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Download::view', + array($request->project->shortname, + $this->id)); + $title = sprintf(__('%s: Download %d added - %s'), + $request->project->name, + $this->id, $this->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'file' => $this, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/downloads/feedfragment.xml'); + return $tmpl->render($context); + } +} diff --git a/src/IDF/WikiPage.php b/src/IDF/WikiPage.php deleted file mode 100644 index 23340f0..0000000 --- a/src/IDF/WikiPage.php +++ /dev/null @@ -1,224 +0,0 @@ -_a['table'] = 'idf_wikipages'; - $this->_a['model'] = __CLASS__; - $this->_a['cols'] = array( - // It is mandatory to have an "id" column. - 'id' => - array( - 'type' => 'Pluf_DB_Field_Sequence', - 'blank' => true, - ), - 'project' => - array( - 'type' => 'Pluf_DB_Field_Foreignkey', - 'model' => 'IDF_Project', - 'blank' => false, - 'verbose' => __('project'), - 'relate_name' => 'wikipages', - ), - 'title' => - array( - 'type' => 'Pluf_DB_Field_Varchar', - 'blank' => false, - 'size' => 250, - 'verbose' => __('title'), - 'help_text' => __('The title of the page must only contain letters, digits or the dash character. For example: My-new-Wiki-Page.'), - ), - 'summary' => - array( - 'type' => 'Pluf_DB_Field_Varchar', - 'blank' => false, - 'size' => 250, - 'verbose' => __('summary'), - 'help_text' => __('A one line description of the page content.'), - ), - 'submitter' => - array( - 'type' => 'Pluf_DB_Field_Foreignkey', - 'model' => 'Pluf_User', - 'blank' => false, - 'verbose' => __('submitter'), - 'relate_name' => 'submitted_wikipages', - ), - 'interested' => - array( - 'type' => 'Pluf_DB_Field_Manytomany', - 'model' => 'Pluf_User', - 'blank' => true, - 'verbose' => __('interested users'), - 'help_text' => 'Interested users will get an email notification when the wiki page is changed.', - ), - 'tags' => - array( - 'type' => 'Pluf_DB_Field_Manytomany', - 'blank' => true, - 'model' => 'IDF_Tag', - 'verbose' => __('labels'), - ), - 'creation_dtime' => - array( - 'type' => 'Pluf_DB_Field_Datetime', - 'blank' => true, - 'verbose' => __('creation date'), - ), - 'modif_dtime' => - array( - 'type' => 'Pluf_DB_Field_Datetime', - 'blank' => true, - 'verbose' => __('modification date'), - ), - ); - $this->_a['idx'] = array( - 'modif_dtime_idx' => - array( - 'col' => 'modif_dtime', - 'type' => 'normal', - ), - ); - $table = $this->_con->pfx.'idf_tag_idf_wikipage_assoc'; - $this->_a['views'] = array( - 'join_tags' => - array( - 'join' => 'LEFT JOIN '.$table - .' ON idf_wikipage_id=id', - ), - ); - } - - function __toString() - { - return $this->title.' - '.$this->summary; - } - - function _toIndex() - { - $rev = $this->get_current_revision()->_toIndex(); - $str = str_repeat($this->title.' '.$this->summary.' ', 4).' '.$rev; - return Pluf_Text::cleanString(html_entity_decode($str, ENT_QUOTES, 'UTF-8')); - } - - /** - * We drop the information from the timeline. - */ - function preDelete() - { - IDF_Timeline::remove($this); - IDF_Search::remove($this); - } - - function get_current_revision() - { - $true = Pluf_DB_BooleanToDb(true, $this->getDbConnection()); - $rev = $this->get_revisions_list(array('filter' => 'is_head='.$true, - 'nb' => 1)); - return ($rev->count() == 1) ? $rev[0] : null; - } - - function preSave($create=false) - { - if ($this->id == '') { - $this->creation_dtime = gmdate('Y-m-d H:i:s'); - } - $this->modif_dtime = gmdate('Y-m-d H:i:s'); - } - - function postSave($create=false) - { - // Note: No indexing is performed here. The indexing is - // triggered in the postSave step of the revision to ensure - // that the page as a given revision in the database when - // doing the indexing. - if ($create) { - IDF_Timeline::insert($this, $this->get_project(), - $this->get_submitter()); - } - } - - /** - * Returns an HTML fragment used to display this wikipage in the - * timeline. - * - * The request object is given to be able to check the rights and - * as such create links to other items etc. You can consider that - * if displayed, you can create a link to it. - * - * @param Pluf_HTTP_Request - * @return Pluf_Template_SafeString - */ - public function timelineFragment($request) - { - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', - array($request->project->shortname, - $this->title)); - $out = ''. - Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). - ''; - $stag = new IDF_Template_ShowUser(); - $user = $stag->start($this->get_submitter(), $request, '', false); - $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($this->title), Pluf_esc($this->summary)).''; - $out .= "\n".' -
'.sprintf(__('Creation of page %s, by %s'), $url, Pluf_esc($this->title), $user).'
'; - return Pluf_Template::markSafe($out); - } - - public function feedFragment($request) - { - $url = Pluf::f('url_base') - .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', - array($request->project->shortname, - $this->title)); - $title = sprintf(__('%s: Documentation page %s added - %s'), - $request->project->name, - $this->title, $this->summary); - $date = Pluf_Date::gmDateToGmString($this->creation_dtime); - $context = new Pluf_Template_Context_Request( - $request, - array('url' => $url, - 'title' => $title, - 'page' => $this, - 'rev' => $this->get_current_revision(), - 'create' => true, - 'date' => $date) - ); - $tmpl = new Pluf_Template('idf/wiki/feedfragment.xml'); - return $tmpl->render($context); - } -} \ No newline at end of file diff --git a/src/IDF/WikiRevision.php b/src/IDF/WikiRevision.php deleted file mode 100644 index a05bd01..0000000 --- a/src/IDF/WikiRevision.php +++ /dev/null @@ -1,294 +0,0 @@ -_a['table'] = 'idf_wikirevisions'; - $this->_a['model'] = __CLASS__; - $this->_a['cols'] = array( - // It is mandatory to have an "id" column. - 'id' => - array( - 'type' => 'Pluf_DB_Field_Sequence', - 'blank' => true, - ), - 'wikipage' => - array( - 'type' => 'Pluf_DB_Field_Foreignkey', - 'model' => 'IDF_WikiPage', - 'blank' => false, - 'verbose' => __('page'), - 'relate_name' => 'revisions', - ), - 'is_head' => - array( - 'type' => 'Pluf_DB_Field_Boolean', - 'blank' => false, - 'default' => false, - 'help_text' => 'If this revision is the latest, we mark it as being the head revision.', - 'index' => true, - - ), - 'summary' => - array( - 'type' => 'Pluf_DB_Field_Varchar', - 'blank' => false, - 'size' => 250, - 'verbose' => __('summary'), - 'help_text' => __('A one line description of the changes.'), - ), - 'content' => - array( - 'type' => 'Pluf_DB_Field_Compressed', - 'blank' => false, - 'verbose' => __('content'), - ), - 'submitter' => - array( - 'type' => 'Pluf_DB_Field_Foreignkey', - 'model' => 'Pluf_User', - 'blank' => false, - 'verbose' => __('submitter'), - ), - 'changes' => - array( - 'type' => 'Pluf_DB_Field_Serialized', - 'blank' => true, - 'verbose' => __('changes'), - 'help_text' => 'Serialized array of the changes in the issue.', - ), - 'creation_dtime' => - array( - 'type' => 'Pluf_DB_Field_Datetime', - 'blank' => true, - 'verbose' => __('creation date'), - ), - ); - $this->_a['idx'] = array( - 'creation_dtime_idx' => - array( - 'col' => 'creation_dtime', - 'type' => 'normal', - ), - ); - } - - function changedRevision() - { - return (is_array($this->changes) and count($this->changes) > 0); - } - - function _toIndex() - { - return $this->content; - } - - /** - * We drop the information from the timeline. - */ - function preDelete() - { - IDF_Timeline::remove($this); - } - - function preSave($create=false) - { - if ($this->id == '') { - $this->creation_dtime = gmdate('Y-m-d H:i:s'); - $this->is_head = true; - } - } - - function postSave($create=false) - { - if ($create) { - // Check if more than one revision for this page. We do - // not want to insert the first revision in the timeline - // as the page itself is inserted. We do not insert on - // update as update is performed to change the is_head - // flag. - $sql = new Pluf_SQL('wikipage=%s', array($this->wikipage)); - $rev = Pluf::factory('IDF_WikiRevision')->getList(array('filter'=>$sql->gen())); - if ($rev->count() > 1) { - IDF_Timeline::insert($this, $this->get_wikipage()->get_project(), - $this->get_submitter()); - foreach ($rev as $r) { - if ($r->id != $this->id and $r->is_head) { - $r->is_head = false; - $r->update(); - } - } - } - $page = $this->get_wikipage(); - $page->update(); // Will update the modification timestamp. - IDF_Search::index($page); - } - } - - public function timelineFragment($request) - { - $page = $this->get_wikipage(); - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', - array($request->project->shortname, - $page->title)); - $out = "\n".''. - Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). - ''; - $stag = new IDF_Template_ShowUser(); - $user = $stag->start($this->get_submitter(), $request, '', false); - $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($page->title), Pluf_esc($this->summary)); - if ($this->changedRevision()) { - $out .= '
'; - $changes = $this->changes; - foreach ($changes as $w => $v) { - $out .= ''; - switch ($w) { - case 'lb': - $out .= __('Labels:'); break; - } - $out .= ' '; - if ($w == 'lb') { - $out .= Pluf_esc(implode(', ', $v)); - } else { - $out .= Pluf_esc($v); - } - $out .= ' '; - } - $out .= '
'; - } - $out .= ''; - $out .= "\n".' -
'.sprintf(__('Change of %s, by %s'), $url, Pluf_esc($page->title), $user).'
'; - return Pluf_Template::markSafe($out); - } - - public function feedFragment($request) - { - $page = $this->get_wikipage(); - if (!$this->is_head) { - $url = Pluf::f('url_base') - .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', - array($request->project->shortname, - $page->title), - array('rev' => $this->id)); - } else { - $url = Pluf::f('url_base') - .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::view', - array($request->project->shortname, - $page->title)); - } - $title = sprintf(__('%s: Documentation page %s updated - %s'), - $request->project->name, - $page->title, $page->summary); - $date = Pluf_Date::gmDateToGmString($this->creation_dtime); - $context = new Pluf_Template_Context_Request( - $request, - array('url' => $url, - 'title' => $title, - 'page' => $page, - 'rev' => $this, - 'create' => false, - 'date' => $date) - ); - $tmpl = new Pluf_Template('idf/wiki/feedfragment.xml'); - return $tmpl->render($context); - } - - - - /** - * Notification of change of a WikiPage. - * - * The content of a WikiPage is in the IDF_WikiRevision object, - * this is why we send the notificatin from there. This means that - * when the create flag is set, this is for the creation of a - * wikipage and not, for the addition of a new revision. - * - * Usage: - *
-     * $this->notify($conf); // Notify the creation of a wiki page
-     * $this->notify($conf, false); // Notify the update of the page
-     * 
- * - * @param IDF_Conf Current configuration - * @param bool Creation (true) - */ - public function notify($conf, $create=true) - { - $wikipage = $this->get_wikipage(); - $project = $wikipage->get_project(); - $current_locale = Pluf_Translation::getLocale(); - - $from_email = Pluf::f('from_email'); - $messageId = '<'.md5('wiki'.$wikipage->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; - $recipients = $project->getNotificationRecipientsForTab('wiki'); - - foreach ($recipients as $address => $language) { - - if ($this->get_submitter()->email === $address) { - continue; - } - - Pluf_Translation::loadSetLocale($language); - - $context = new Pluf_Template_Context(array( - 'page' => $wikipage, - 'rev' => $this, - 'project' => $project, - 'url_base' => Pluf::f('url_base'), - )); - - $tplfile = 'idf/wiki/wiki-created-email.txt'; - $subject = __('New Documentation Page %s - %s (%s)'); - $headers = array('Message-ID' => $messageId); - if (!$create) { - $tplfile = 'idf/wiki/wiki-updated-email.txt'; - $subject = __('Documentation Page Changed %s - %s (%s)'); - $headers = array('References' => $messageId); - } - - $tmpl = new Pluf_Template($tplfile); - $text_email = $tmpl->render($context); - - $email = new Pluf_Mail($from_email, - $address, - sprintf($subject, - $wikipage->title, - $wikipage->summary, - $project->shortname)); - $email->addTextMessage($text_email); - $email->addHeaders($headers); - $email->sendMail(); - } - - Pluf_Translation::loadSetLocale($current_locale); - } -} diff --git a/src/IDF/relations.php b/src/IDF/relations.php index 38f0ea1..797a90c 100644 --- a/src/IDF/relations.php +++ b/src/IDF/relations.php @@ -30,9 +30,12 @@ $m['IDF_IssueFile'] = array('relate_to' => array('IDF_IssueComment', 'Pluf_User' $m['IDF_Upload'] = array('relate_to' => array('IDF_Project', 'Pluf_User'), 'relate_to_many' => array('IDF_Tag')); $m['IDF_Search_Occ'] = array('relate_to' => array('IDF_Project'),); -$m['IDF_WikiPage'] = array('relate_to' => array('IDF_Project', 'Pluf_User'), - 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); -$m['IDF_WikiRevision'] = array('relate_to' => array('IDF_WikiPage', 'Pluf_User')); +$m['IDF_Wiki_Page'] = array('relate_to' => array('IDF_Project', 'Pluf_User'), + 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); +$m['IDF_Wiki_PageRevision'] = array('relate_to' => array('IDF_Wiki_Page', 'Pluf_User')); +$m['IDF_Wiki_Resource'] = array('relate_to' => array('IDF_Project', 'Pluf_User')); +$m['IDF_Wiki_ResourceRevision'] = array('relate_to' => array('IDF_Wiki_Resource', 'Pluf_User'), + 'relate_to_many' => array('IDF_PageRevision', 'Pluf_User')); $m['IDF_Review'] = array('relate_to' => array('IDF_Project', 'Pluf_User', 'IDF_Tag'), 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); $m['IDF_Review_Patch'] = array('relate_to' => array('IDF_Review', 'Pluf_User'));