Klap-in / dokuwiki-plugin-bookcreator

Allow to select some pages and create a book (PDF, ODT or text)
https://www.dokuwiki.org/plugin:bookcreator
13 stars 18 forks source link

Support of further exportplugins #46

Closed Nos- closed 9 years ago

Nos- commented 9 years ago

Hi, I use a couple of export plugins but only a few are supported by this very helpful plugin. If e.g. the LatexIt-, Open-Document- and epub- plugin would be supported by this plugin many users could benefit from it. I would prefer a solution using "global documents" (like a book template which includes all wanted articles) but this is just an optional idea.

Klap-in commented 9 years ago

At the moment I'm busy, so will not on the short term look on this. I like to look on any contributions, so welcome. Note that the maximum pages that can be selected, are currently limited by the cookie size. Would be nice to find an alternative for the cookie storage, to improve this plugin even further.

lpaulsen93 commented 9 years ago

Hi Klap-in,

I could probably give you some assistance here. I assume roughly the following would need to be done:

In plugin bookcreator:

In plugin odt:

Is that right? Have you got further hints?

Greetings, Lars

Klap-in commented 9 years ago

Maybe also a helper plugin is useful for code reusage. Now possibly there will be code duplicated for the book stuff in dw2pdf and odt...but maybe generic code is difficult... because all the plugins can also live separately.

Klap-in commented 9 years ago

Indeed, basically that are the steps. Please build the code of the odt version of action.php as similar as possible. In that manner we can abstract some code later, probably. Or at least it simplifies maintainance.

lpaulsen93 commented 9 years ago

Maybe there could be a helper in the bookcreator plugin because the plugins dw2pdf and odt would interface to it. At least maybe for:

These would probably the same for every renderer interfacing to the bookcreator plugin. But the CSS helper could also be put in css.php maybe. It's using functions from there anyway.

iTStage commented 9 years ago

Hello LarsGit223, i follow your process from your first message, and an error message appears: "Failed to handle command: export_odtbook". Whence can come this error ?

lpaulsen93 commented 9 years ago

@iTStage: You mean you tried to do a ?do=export_odtbook request? Currently that comes because it is not implemented yet. Until now, we were just discussing what steps need to be taken to implement it. So right now it will not work. And you probably get that error because there in no one there handling a ?do=export_odtbook request.

This is future work.

iTStage commented 9 years ago

Yes i tried to make this request... I changed the odt Plug-in code by add ''collectExportPages ()'' and ''showPageWithErrorMsg () ''as in the plug-in dw2pdf and implement the same behaviour/interface in action.php. And in the Bookcreator, i create texts for new ODT export options in lang directory and in file syntax.php, i add option for ODT export in the form created in function showBookManager() if plugin ODT is installed. The book calls out the plug-in odt (export_odt in syntax.php) but when I change it by export_odtbook, this error message is displayed. Should we change other things in both plug-ins? Because it is a project that I set up for my course (internship project), which is to end on 12 June, that is why I am appealing to you.

Thank you for your reply and sorry for my English, I'm French.

Klap-in commented 9 years ago

Please publish your code, if you like to receive any feedback...

?do=export_<renderer name> is supported for creating export which a certain renderer (if installed of course). the odtbook is of course not a renderer. So therefere you get this message.

The action.php should check for the right do-action.

lpaulsen93 commented 9 years ago

Yes, for bookcreator support always two plugins need to be changed:

  1. The bookcreator plugin itself, to be able to choose a new format in the GUi and to issue requests according to the new format, in this case odt. As far as I understood, this is the part that you've already done.
  2. You need to change the plugin that has to handle the request and that has to do the actual exporting work. That's what is missing and therefore you get the error message. Because right now the ODT plugin supports only export_odt requests, but not export_odtbook or export_odtns.

You can compare the action.php files of the dw2pdf plugin and the ODT plugin. Look at the following lines:

I assume there is also more work to do because the ODT plugin now only exports single pages with an ODT document start, the ODT page content, and the ODT document end. For bookcreator support there needs to be the functionality to have a ODT document start, ODT page 1 content, ODT page 2 content, ... , ODT last page content, and then the ODT document end. Also, the ODT plugin is currently not able to create table of contents.

So this can cause some more work and I myself do not yet know what effort exactly this points mean/cause. The first steps might be easy, but then there are more changes required internally in the ODT plugin which also require knowledge of the ODT format itself I guess.

Klap-in commented 9 years ago

I agree that the building one ODT file with more articles is the challenging part of this odtbook feature. The rest (collecting, etc) is mostly straight forward (for me).

iTStage commented 9 years ago

Thank you for your answers, I began to understand my problem. I give you the code I changed / added in ODT:

    function handle_cache_prepare(Doku_Event $event, $param) {
        global $ACT;
        global $REV;
        global $ID;
        if(($ACT != 'export_odtbook') && ($ACT != 'export_odt')) return false;

        // check user's rights
        if(auth_quickaclcheck($ID) < AUTH_READ) return false;

        if($data = $this->collectExportPages($event)) {
            list($title, $this->list) = $data;
        } else {
            return false;
        }
        $event->preventDefault();

        $cache =& $event->data;
        // only the ODT rendering mode needs caching tweaks
        if ($cache->mode != "odt") return;

        foreach($this->list as $pageid) {
            $odt_meta = p_get_metadata($ID, 'relation odt');
        }
    }

and here:

   function collectExportPages(Doku_Event $event) {
        global $ACT;
        global $ID;
        global $INPUT;
        global $conf;

        $list = array();

        if($ACT == 'export_odtbook') {
            if(isset($_COOKIE['list-pagelist']) && !empty($_COOKIE['list-pagelist'])) {
                //is in Bookmanager of bookcreator plugin a title given?
                if(!$title = $INPUT->str('pdfbook_title')) {
                    $this->showPageWithErrorMsg($event, 'needtitle');
                    return false;
                } else {
                    $list = explode("|", $_COOKIE['list-pagelist']);
                }

            } else {
               //show empty bookcreator message
               $this->showPageWithErrorMsg($event, 'empty');
               return false;
           }

           $list = array_map('cleanID', $list);
           return array($title, $list);
       }
  }
Klap-in commented 9 years ago

When reading your code I don't see sofar some suspicious with respect to not recognizing your do-action.

Note: $odt_meta = p_get_metadata($ID, 'relation odt'); I think you want $pageid from the list, and not $ID, that is global pageid

iTStage commented 9 years ago

Yes, thank you for the little note, I still have not managed to find out why it does not recognize the action...

iTStage commented 9 years ago

Is it possible to add functions / code to export to ODT in book Plug-in, so that pressing the button export, we export ODT the list ?

lpaulsen93 commented 9 years ago

As we wrote, it should be possible. How do you want to proceed? I thought you are working on this now? Sorry, I'm not sure if I understood your question.

iTStage commented 9 years ago

I would add the functions of ODT plugin in bookcreator Plugin . Unless I am mistaken, the plug-in bookcreator selects pages and then create an outlet to the plug-in made wish? Where in the plug-in dw2pdf, we recover the data of the selected pages?

iTStage commented 9 years ago

Return to the beginning, that needs to change , add, modify both Plug-ins ?

Klap-in commented 9 years ago

General note: please share your work directly in (fork of) the repository. That way we can provide in early stage feedback.

The bookcreator creates a cookie list-pagelist. This cookie is accessible via the global variable $_COOKIE['list-pagelist']. This is performed in the collectExportPages() function in action.php of dw2pdf.

iTStage commented 9 years ago

So we can replicate this function in action.php of ODT ?

iTStage commented 9 years ago

Just information, do you use a PHP debugger ? Which?

Klap-in commented 9 years ago

I work with the Editor IntelliJ IDEA (https://www.dokuwiki.org/devel:intellij_idea) Further you can find any failure by de web server in the log file of apache. (or what do you mean exactly by 'debugger'?)

iTStage commented 9 years ago

I was looking for a software that allowed to test PHP code. To see if there are errors, and / or run the code in "step by step" to observe variables, whether we enter well in all functions etc.

Klap-in commented 9 years ago

A step-by-step tool is not know for me. IntelliJ places notices in the code which are very helpful, and prevent many inconsistencies. further you can write manually stuff to log or to screen when debugging and checking.

for interface/function testing you can use unit tests as well https://www.dokuwiki.org/devel:unittesting Some minor tools in dokuwiki for debug purposes are: https://www.dokuwiki.org/devel:debugging

lpaulsen93 commented 9 years ago

There seem to be debuggers, check http://php.net/manual/en/debugger-about.php. But I never used a php debugger.

Also, it is possibly not as easy as debugging a standalone program because you need to debug the webserver also/or with a webserver running. But as I said, I got no experience with that and so I can't give you more help on debugging php.

iTStage commented 9 years ago

It does not matter, your helpers are enough for me to move quietly, but according to you, with the code I provided you are, can come to where the error "Failed to handle command: export_odtbook"? Otherwise, there is another way to export multiple pages in ODT without the include Plug-in? I would get the same toolbar as the book (select pages with a click, and export).

Anyway, thank you for your help

Klap-in commented 9 years ago

This default catch of export_<..> is performed at: http://xref.dokuwiki.org/reference/dokuwiki/inc/actions.php.source.html#l159

Handling of default exports with http://xref.dokuwiki.org/reference/dokuwiki/inc/actions.php.source.html#l600

When not recognized: http://xref.dokuwiki.org/reference/dokuwiki/inc/template.php.source.html#l90

But registered action with e.g. in dw2pdf: $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'convert', array()); should already get the export action before the default action is reached. But I don't know what you have written in that piece of your code, so I cannot give feedback on it.

Klap-in commented 9 years ago

For fast result the include plugin is probably the best already working solution.

Other options require knowledge of ODT, for the combining the different articles...

iTStage commented 9 years ago

In the book creator plug-in, in function exportOnScreen(&$renderer) () ,What is the variable $lf_subst and how work $renderer->doc .= str_replace(DOKU_LF, $lf_subst, p_cached_output(wikiFN($page), $render_mode)); ?

iTStage commented 9 years ago
 function render($mode, Doku_Renderer $renderer, $data) {
        global $ID;

        list($type, $num, $order) = $data;

        if($type == "book") {
            $renderer->info['cache'] = false;
            if(($mode == 'text') && (isset($_GET['do']) && ($_GET['do'] == 'export_text'))) {
                $mode = 'xhtml';
            }

            if($mode == 'xhtml') {
                /** @var $renderer Doku_Renderer_xhtml */

                // verification that if the user can save / delete the selections
                $usercansave = (auth_quickaclcheck($this->getConf('save_namespace').':*') >= AUTH_CREATE);

                if($usercansave) {
                    //save or delete selection
                    if(isset($_POST['task']) && ($_POST['task'] == "save") && checkSecurityToken()) {
                        $this->saveSelection();
                    } elseif(isset($_POST['task']) && ($_POST['task'] == "delete") && checkSecurityToken()) {
                        $this->deleteSelection();
                    }
                }

                if(isset($_GET['do']) && ($_GET['do'] == 'export_html' || $_GET['do'] == 'export_text')) {
                    //export as xhtml or text
                    $this->exportOnScreen($renderer);

                } else {
                    $renderer->info['cache'] = false;

                    //search for the current selection in cookie
                    $foundlist = false;
                    if(isset($_COOKIE['bookcreator'])) {
                        $currentselection = $_COOKIE['bookcreator'];

                        //empty?
                        if(($currentselection == "") || (count($currentselection) == 0)) {
                            $renderer->doc .= $this->getLang('empty');
                        } else {
                            $foundlist = true;
                        }
                    }

                    //show the bookmanager when there are pages selected, otherwise a message.
                    if($foundlist) {
                        $this->showBookManager($renderer, $usercansave);
                    } else {
                        //no selection available
                        $renderer->doc .= $this->getLang('nocookies');
                    }

                    // Displays the list of saved selections
                    $this->renderSelectionslist($renderer, $bookmanager = true, $ID, $order);
                    $renderer->doc .= "<br />";
                }
            } else {
            // type == archive

            if($mode == 'odt') {
            if(isset($_GET['do']) && ($_GET['do'] == 'export_odt')) {
                    $this->exportOnScreen($renderer);
            }
        }
    }
}
}

I insert a new condition in this fonction, and in exportOnScreen($renderer)

private function exportOnScreen(Doku_Renderer $renderer) {
        $list = array();
        if(isset($_COOKIE['list-pagelist'])) {
            $renderer->doc = 'odt';
            $list          = explode("|", $_COOKIE['list-pagelist']);
        }

        $render_mode = 'odt';
        $lf_subst    = '';
        if($_GET['do'] == 'export_text) {
            $render_mode = 'text';
            $lf_subst    = '';
        }

        foreach($list as $page) {
            $renderer->doc .= str_replace(DOKU_LF, $lf_subst, p_cached_output(wikiFN($page), $render_mode)); //p_wiki_xhtml($page,$REV,false);
        }
    }

when exporting, I get a file with the different pages but the content is encrypted (symbol)

iTStage commented 9 years ago

Did you look at my code?

Klap-in commented 9 years ago

Yes, and sofar I have no idea why it converted to symbols.

I started a fork as well, with sofar only code for collecting pages. An a bit thinking about work todo on the renderer. See https://github.com/LarsGit223/dokuwiki-plugin-odt/pull/43

Input/feedback is welcome.

Klap-in commented 9 years ago

Hmm, maybe the symbols you get are the result of concatenating two zip-files together... the result of the ODT renderer is a zip, not an real string. So these should not be concatenated with $renderer->doc .= ....

iTStage commented 9 years ago

Yes I saw or was the problem, I will look at your code, I think a good start this time, I did a little test, but it exports a damaged file. To talk, I go here https://github.com/LarsGit223/dokuwiki-plugin-odt/pull/43 ?

Klap-in commented 9 years ago

My code will not export anything, if it does, it will not make sense. It is work in progress.

In my code firstly the renderer has to become multi-wikipage capable. e.g. pointers and bookmarks should get a prefix for the wikipage that contained them.

Klap-in commented 9 years ago

A first working example of odt book creation is available at https://github.com/LarsGit223/dokuwiki-plugin-odt/pull/45

Klap-in commented 9 years ago

ODT book export is added. See master branch of ODT plugin.

lpaulsen93 commented 9 years ago

ODT bookcreator support has been officially released today in ODT plugin release 2015-10-03. @Klap-in: thanks a lot again for your contribution!

Klap-in commented 9 years ago

ODT export is successful done! If other export formats are desired, please open a specific feature request.