<?php

use dokuwiki\Extension\AdminPlugin;
use dokuwiki\File\PageResolver;

/**
 * Plugin CSVtoDWPages: Convert CSV file to DW Pages
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Ninja Dave <dokuwiki [at] reprah [dot] com>
 */

/**
 * All DokuWiki plugins to extend the admin function
 * need to inherit from this class
 */
class admin_plugin_csvtodwpages extends AdminPlugin  
{
    /**
     * Version: see lang.php
     */

    protected $params;
    protected $paramcount;

    private $nl = "\n";

    /**
     * access for managers
     */
    function forAdminOnly()
    {
        return false;
    }

    /**
     * return sort order for position in admin menu
     */
    function getMenuSort()
    {
        return 1;
    }

    /**
     * handle user request
     */
    function handle()
    {
        global $INPUT;
        global $params;
        global $paramcount;

        $fieldnames = array('csvdw_namespace','csvdw_delim','csvdw_pagename','csvdw_csvdata','csvdw_csvtemplate','csvdw_overwrite','csvdw_dummyrun' ,'csvdw_trim');

        if ($INPUT->has('csvdw_submit') && checkSecurityToken()) { 

            foreach ($fieldnames as $key) {
                if (!blank($INPUT->param($key))){
                    $paramcount++;
                    $params[$key] = $INPUT->param($key);
                }
            }
        }
    }

    /**
     * output appropriate html
     */
    function html()
    {
        global $params;
        global $paramcount;

        $fieldcount = 0;

        // update the label when the namespace is changed
        echo "<script language='javascript'>function csvtodw_nslabel(){document.getElementById('csvtodw_nslabel').innerHTML=document.getElementById('csvtodw_ns').value;};</script>";

        echo $this->locale_xhtml('intro') . $this->nl;
        echo '<form method="post" action="" class="csvtodwpages">' . $this->nl;
        echo '<input type="hidden" name="do" value="admin"/>' . $this->nl;
        echo '<input type="hidden" name="page" value="'.$this->getPluginName().'"/>' . $this->nl;
        formSecurityToken();

        echo '<fieldset class="csvtodwpages">' . $this->nl;

        echo '<table class="csvtodwpages"><tr><td>' . $this->nl;

        echo '<h4>'.$this->getLang('csvdw_namespace').'</h4>' . $this->nl;
        echo '<input type="text" name="csvdw_namespace" value="'.$this->_field('csvdw_namespace','').'" id="csvtodw_ns" onblur="csvtodw_nslabel()"/>' . $this->nl;
        $fieldcount++;

        echo '</td><td>' . $this->nl;

        echo '<h4>'.$this->getLang('csvdw_pagename').'</h4>' . $this->nl;
        echo '<input type="text" name="csvdw_pagename" value="'.$this->_field('csvdw_pagename','').'"/>' . $this->nl;
        $fieldcount++;
        
        echo '</td><td>' . $this->nl;

        echo '<h4>'.$this->getLang('csvdw_delim').'</h4>' . $this->nl;
        echo '<input type="text" name="csvdw_delim" maxlength="1" value="'.$this->_field('csvdw_delim',',').'"/>' . $this->nl;
        $fieldcount++;

        echo '</td></tr></table>' . $this->nl;

        echo '<h4>'.$this->getLang('csvdw_csvtemplate').'</h4>' . $this->nl;
        echo '<textarea name="csvdw_csvtemplate" class="edit">'.$this->_field('csvdw_csvtemplate').'</textarea><br/><br/>' . $this->nl;
        $fieldcount++;

        echo '<h4>'.$this->getLang('csvdw_csvdata').'</h4>' . $this->nl;
        echo '<textarea name="csvdw_csvdata" class="edit">'.$this->_field('csvdw_csvdata').'</textarea><br/><br/>' . $this->nl;
        $fieldcount++;

        echo '<table class="csvtodwpages"><tr><td>' . $this->nl;

        echo '<h4>'.sprintf($this->getLang('csvdw_overwrite'), $this->_field('csvdw_namespace','csvexploded')).'</h4>' . $this->nl;
        echo '<input type="radio" class="csvtodwpages" name="csvdw_overwrite[]" value="true" id="owt" '.$this->_field('csvdw_overwrite','true',true).'/> ' . $this->nl;
        echo '<label class="csvtodwpages" for="owt">'.$this->getLang('csvdw_yes').'</label> --- <label class="csvtodwpages" for="owf">'.$this->getLang('csvdw_no').'</label>' . $this->nl;
        echo '<input type="radio" class="csvtodwpages" name="csvdw_overwrite[]" value="false" id="owf" '.$this->_field('csvdw_overwrite','false',true).'/>' . $this->nl;
        $fieldcount++;

        echo '</td><td>' . $this->nl;

        echo '<h4>'.$this->getLang('csvdw_dummyrun').'</h4>' . $this->nl;
        echo '<input type="radio" class="csvtodwpages" name="csvdw_dummyrun[]" value="true" id="drt" '.$this->_field('csvdw_dummyrun','true',true).'/> ' . $this->nl;
        echo '<label class="csvtodwpages" for="drt">'.$this->getLang('csvdw_yes').'</label> --- <label class="csvtodwpages" for="drf">'.$this->getLang('csvdw_no').'</label>' . $this->nl;
        echo '<input type="radio" class="csvtodwpages" name="csvdw_dummyrun[]" value="false" id="drf" '.$this->_field('csvdw_dummyrun','false',true).'/>' . $this->nl;
        $fieldcount++;

        echo '</td><td>' . $this->nl;

        echo '<h4>'.$this->getLang('csvdw_trim').'</h4>' . $this->nl;
        echo '<input type="radio" name="csvdw_trim[]" value="true" id="trimt" '.$this->_field('csvdw_trim','true',true).'/> ' . $this->nl;
        echo '<label class="csvtodwpages" for="trimt">'.$this->getLang('csvdw_yes').'</label> --- <label class="csvtodwpages" for="trimf">'.$this->getLang('csvdw_no').'</label>' . $this->nl;
        echo '<input type="radio" name="csvdw_trim[]" value="false" id="trimf" '.$this->_field('csvdw_trim','false',true).'/>' . $this->nl;
        $fieldcount++;

        echo '</td></tr></table>' . $this->nl;

        // required fields warning
		echo (is_numeric($paramcount) && $paramcount !== $fieldcount) ? "<span class='csvtodwpageswarning'>".$this->getLang('csvdw_allfields')."</span><br/>" : '' . $this->nl;

        echo '<input type="submit" name="csvdw_submit" class="csvtodwpages" value="'.$this->getLang('csvdw_submitbtn').'"/>' . $this->nl;

        echo '<div class="csvtodwpages_ver">'.$this->getLang('csvdw_ver').'</div>';
        echo '</fieldset>';

        echo '</form>';

        // if all form values recieved, let's explode!
        if ($paramcount == $fieldcount) {
        	$this->_csvexploder();

		} elseif ($paramcount > $fieldcount) {
            // something weird going on
            echo '<br/><fieldset><span class="csvtodwpageswarning">Incorrect number of form parameters received. We\'re screwed!<br/>Needed '.$fieldcount.', got '.$paramcount.'</span></fieldset>' . $this->nl;
        }
	}


    /**
     * take form values and explode the submitted csvdata into dokuwiki pages based on submitted csvtemplate
     */
	function _csvexploder()
    {
        global $conf;       // get dokuwiki conf array
        global $params;
        global $paramcount;
        global $ID;

        $resolver = new PageResolver($ID);


        $namespace      = strtolower($params['csvdw_namespace']); // which namespace to create pages within

        $pagename_column = $params['csvdw_pagename']; // which column(s) in the csv file used for the pagename

        $indexpage      = (empty($conf['start'])) ? 'start' : $conf['start']; // the dokuwiki index page name

        $csvdata        = $params['csvdw_csvdata'];         // the dokuwiki page in which you pasted the csv data
        $csvtemplate    = $params['csvdw_csvtemplate'];     // the dokuwiki page you created holding the template
        $csvdelim       = $params['csvdw_delim'][0];        // the csv delimiter character (single character)

        $overwrite_files = ($params['csvdw_overwrite'][0] == 'true') ? TRUE : FALSE;  // set this to TRUE to overwrite existing pages
        $dummyrun        = ($params['csvdw_dummyrun'][0]  == 'true') ? TRUE : FALSE;  // is this just a dummy run?
        $trimspaces      = ($params['csvdw_trim'][0]      == 'true') ? TRUE : FALSE;  // is this just a dummy run?

        $indexpagecontent = $this->getLang('csvdw_indexpagecontent');   // template for autogenerated index page

        // $dr = rtrim( $_SERVER['DOCUMENT_ROOT'], "/" ) .'/';

        // get field names from first row
        $csvfieldnames = str_getcsv(strtok($csvdata, PHP_EOL), $csvdelim);

        // if we have some csvfieldnames lets rock'n'roll
        if ($csvfieldnames !== FALSE) {

            if ($dummyrun) {
                echo $this->getLang('csvdw_dummyrunnotice') . $this->nl;
            }

            echo $this->getLang('csvdw_explodednotice') . $this->nl;

            if (array_count_values($csvfieldnames) >= 1) {

                while (($line = strtok(PHP_EOL)) !== FALSE) {

                    $line = str_getcsv($line, $csvdelim);

                    if (!empty(array_filter($line))) {

                        // get clean copy of the template
                        $thispage = $csvtemplate;

                        // set the page name for the index page text
                        $pagename = $this->_get_filename($pagename_column, $line);

                        // clean output filename to dokuwiki standards
                        $cleanpagename = cleanID($pagename);

                        $indexpagecontent .= "  * [[$cleanpagename|$pagename]]\r\n";

                        // replace the template [placeholder] names with content
                        foreach ($csvfieldnames as $key => $field) {
                            $thispage = str_replace('['.strtolower($field).']', $trimspaces ? trim($line[$key]) : $line[$key], $thispage);
                        }

                        // create wiki page
                        $filecreated = FALSE;

                        if ($overwrite_files !== TRUE && page_exists($resolver->resolveId($namespace.':'.$cleanpagename))) {
                            echo $this->getLang('csvdw_skipnoticep');   // msg($this->getLang('csvdw_skipnotice'));
                        } else {
                            if ($dummyrun) {
                                $filecreated = TRUE;
                            } else {
                                // we are assuming that if the file exists after saveWikiText() then it was created
                                // Unfortunately saveWikiText() doesn't provide a return value to indicate if it succeeded or failed.
                                // This leaves it possible that a page existed previously but we were unable to overwrite it.
                                // The DW notice system will put a notice in the exploded file list to indicate the failure though.
                                // see io_writeWikiPage() and _io_writeWikiPage_action() in .\dokuwiki\inc\io.php
                                saveWikiText($resolver->resolveId($namespace.':'.$cleanpagename), $thispage, $this->getLang('csvdw_summary'));
                                $filecreated = page_exists($resolver->resolveId($namespace.':'.$cleanpagename));  
                            }
                            
                            if ($filecreated == FALSE) {
                                echo $this->getLang('csvdw_errornotice');
                            } else {
                                echo $this->getLang('csvdw_creatednoticep');
                            }
                        }

                        echo wikiFN($resolver->resolveId($namespace.':'.$cleanpagename))."<br/>" . $this->nl;
                    }

                }

                // show an example template page if this is a dummy run
                // (uses the data from the last processed csv row)
                if ($dummyrun) {
                    echo $this->getLang('csvdw_examplepagenotice') . $this->nl;
                    echo nl2br($thispage) . $this->nl;
                }
                
                echo "<br/><br/><hr/>" . $this->nl;

                // create index page
                $filecreated = FALSE;

                if ($overwrite_files !== TRUE && page_exists($resolver->resolveId($namespace.':'.$indexpage))) {
                    echo $this->getLang('csvdw_skipnoticei');   // msg($this->getLang('csvdw_skipnoticei'));

                } else {
                    if ($dummyrun) {
                        $filecreated = TRUE;
                    } else {
                        saveWikiText($resolver->resolveId($namespace.':'.$indexpage), $indexpagecontent, $this->getLang('csvdw_summary'));
                        $filecreated = page_exists($resolver->resolveId($namespace.':'.$indexpage));
                    }
                    if ($filecreated == FALSE) {
                        echo $this->getLang('csvdw_errornotice');
                    } else {
                        echo $this->getLang('csvdw_creatednoticei');
                    }
                }
                
                // echo wikiFN(resolve_id($namespace, $indexpage))."<br/>" . $this->nl;
                echo wikiFN($resolver->resolveId($namespace.':'.$indexpage))."<br/>" . $this->nl;
            }

            echo "<br/>" . $this->nl;

            // null is used as the first param to wl() as it's the only way to get the URL
            // to work on both our dev server (excludes the doku.php in url) and the live
            // server (includes doku.php in url)
            echo 'Go to <a href="' . wl(null, '', false) . $resolver->resolveId($namespace.':'.$indexpage) . '">' . $namespace . ':' . $indexpage . '</a><br/>' . $this->nl;
        }

        strtok('',''); // release strtok memory
	}

    /**
     * Helper to build a unique pagename from specified csv column data
     * 
     * Will combine multiple column data together if comma separated list
     * is supplied. Each field will be separated with underscores _
     * 
     * @param $pagecols string Single int value or comma separated list eg. 0,3
     * @param $line     array  An array containing the csv values for the current row
     * @return string   A page name combining all row values separated with _ eg. youngstown_oh
     */
    protected function _get_filename($pagecols='', &$line)
    {
        $pagename = '';
        $pagecols = explode(',', $pagecols);

        // combine column data into filename
        foreach ($pagecols as $col) {
            $pagename .= trim($line[$col]).'_';
        }
        
        return rtrim($pagename, "_");
    }

    /**
     * Helper to repopulate form field values from POST data
     * 
     * @param  $field   = fieldname
     * @param  $default = default value to return if no value present
     * @param  $isradio = flag indicating if field is a radiobutton - return 'checked' instead of value
     * @return string : form field value or default
     * @return array  : first element of array if incoming field was an array (multivalue field)
     */
	protected function _field($field, $default='', $isradio=false)
    {
        global $params;
        global $paramcount;

        $val = '';
        if (!blank($params[$field])) {
            $val = is_array($params[$field]) ? $params[$field][0] : $params[$field];
        }

        if ($isradio) {
            if ($val==$default) {
                return 'checked';
            }
            return '';
        }

        return !blank($val) ? $val : $default;
    }

}

