Extension:UploadCSV/UploadCSV.php

From MediaWiki.org
Jump to: navigation, search
<?php
# Extension:UploadCSV{{php}}{{Category:Extensions|UploadCSV}}
# - See http://www.mediawiki.org/wiki/Extension:UploadCSV for installation and usage details
# - Author: Gunter Schmidt (http://www.mediawiki.org/wiki/User:GunterS)

if ( !defined( 'MEDIAWIKI' ) ) {
?>
<p>This is an MediaWiki-extension. To enable it, put </p>
<pre>require_once("$IP/extensions/UploadCSV/UploadCSV.php");</pre>
<p>near the bottom of your LocalSettings.php</p>
<?php
        exit(1);
}
 
$Ext_Version = '0.2.3'; // Mar. 27, 2007
$wgExtensionFunctions[] = "wfUploadCSVStart";
$wgExtensionCredits['specialpage'][] = array(
        'name' => 'Special:UploadCSV',
        'description' => 'Mass creation of articles from a csv-file.',
        'url' => 'http://www.mediawiki.org/wiki/Extension:UploadCSV',
        'author' => 'Gunter Schmidt',
        'version' => $Ext_Version
);
 
/* ToDo
- smart edit of existing articles, only replace template
- multiple templates on a page (maybe template given on the dataline, will need a template key)
- translation
- documentation
*/
 
require_once "$IP/includes/SpecialPage.php";
# Internationalisation file
require_once( dirname( __FILE__ ) . '/UploadCSV.i18n.php' );
 
function wfUploadCSVStart() {
        global $wgMessageCache, $ExtensionTitles;
 
        // Load messages, so we have a title in Special:SpecialPages
        UploadCSVPage::loadTitles();
 
        SpecialPage::addPage(new UploadCSVPage());
}
 
class UploadCSVPage extends SpecialPage {
                public $Specialpage_Name='UploadCSV', $MsgPrefix; //keep this within the class or it will mess with other extensions!
                public $curRow;
 
        function UploadCSVPage() {
                SpecialPage::SpecialPage($this->Specialpage_Name);
                                $this->MsgPrefix = strtolower($this->Specialpage_Name) . '_';
        }
 
        function execute( $par ) {
                global $wgRequest, $wgOut, $wgUser, $csvInfo, $wgUploadDirectory;
                $MsgPrefix = $this->MsgPrefix;
 
                //Debug info
                $hidden = "text"; // hidden or text
 
                self::loadMessages();
                $this->setHeaders();
 
                #$wgOut->setPagetitle("Gunters Extension"); // only necessary if you do want a different title than in the Special:Specialpages list
         $wgOut->addHTML( wfMsg( $MsgPrefix . 'intro' ) );
 
                // Set form variables
                $template = $wgRequest->getText('wpTemplate');
                if (empty($template)) $template = "SAP-Jobstep"; #else $template = "ok";

                # Put all templates into a select list
         $templates = '';
                $db =& wfGetDB(DB_SLAVE);
                $pagetable = $db->tableName('page');
                $ns = NS_TEMPLATE;
                $result = $db->query("SELECT page_id FROM $pagetable WHERE page_namespace=$ns ORDER BY page_title");
                while ($row = mysql_fetch_array($result)) {
                        $t = Title::newFromID($row[0])->getPrefixedText();
                        $selected = $t == $template ? ' selected' : '';
                        $templates .= "<option value='$t'$selected>$t</option>\n";
                        }
 
                $UploadFile = $wgRequest->getText('wpUploadFile');
 
                $curInfo = $wgRequest->getText('wpcurInfo');
 
                $curAction = $wgRequest->getText('wpcurAction');
                if (empty($curAction)) $curAction = 'start';
                $this->curRow = $wgRequest->getText('wpcurRow');
                if (empty($this->curRow)) $this->curRow = 1;
                $endRow = $wgRequest->getText('wpendRow');
                if (empty($endRow) || !is_numeric($endRow)) $endRow = 0;
 
                # Allow separator character to be specified in form and allow escaping in content, eg \;
         $separator = $wgRequest->getText('wpSeparator');
                if (empty($separator)) $separator = ';';
                $esc = $separator == '|' ? '\\' : '';
                $sepPattern = "/(?<!\\\\)$esc$separator/";
 
                # If file has only just been uploaded, move it to a permenant location
         # - the files are currently not deleted
         if ($curAction != 'start') $curUploadFile = $wgRequest->getText('wpcurUploadFile');
                elseif ($tmp = $wgRequest->getFileTempname('wpUploadFile')) {
                        if (is_uploaded_file($tmp)) {
                            $curUploadFile = "$wgUploadDirectory/".basename($tmp);
                            if (move_uploaded_file($tmp,$curUploadFile) === false) $errormsg = 'Failed to move tmp file!';
                            }
                        else $errormsg = 'Invalid upload file!';
                        }
                else $curUploadFile = '';
                $UploadFile = $curUploadFile;
 
                // build form
                $wgOut->addHTML("<form name=\"userForm\" action=\"$this->action\" method=\"post\" enctype=\"multipart/form-data\"><br />" .
                        "<table style=\"text-align: left;\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">
                        <tbody>
 
                        <tr>  
                                <td align='right'><b>" . wfMsg( 'nstab-template' ) . ":</b></td>
                                <td><select name='wpTemplate'>$templates</select>
                                <b>" . wfMsg( $MsgPrefix . 'separator' ) . ":</b> " .
                                wfElement( 'input', array(
                                'type'  => 'text',
                                'name'  => 'wpSeparator',
                                                        'size'  => '1',
                                'value' => $separator
                                )) .
                                "</td>
                        </tr>
 
                        <tr>  
                                <td align='right'><b>" . wfMsg( 'sourcefilename' ) . ":</b></td>  
                                <td>" .
                                wfElement( 'input', array(
                                'type'  => 'file',
                                'name'  => 'wpUploadFile',
                                                        'size'  => '70',
                                                        'maxlength' => '150',
                                'value' => $UploadFile,
                                'onchange' => "this.form.wpcurUploadFile.value = this.form.wpUploadFile.value"
                                )) .
                                "</td> 
                        </tr>
 
                        <tr>
                                <td align='right'><b>" . wfMsg( $MsgPrefix . 'startline' ) . ":</b></td>
                                <td>" .
                                wfElement( 'input', array(
                                'type'  => 'text',
                                'name'  => 'wpcurRow',
                                                        'size'  => '5',
                                'value' => $this->curRow
                                )) .
                                "</td>
                        </tr>
 
                        <tr>  
                                <td align='right'><b>" . wfMsg( $MsgPrefix . 'endline' ) . ":</b></td>  
                                <td>" .
                                wfElement( 'input', array(
                                'type'  => 'text',
                                'name'  => 'wpendRow',
                                                        'size'  => '5',
                                'value' => $endRow
                                )) .
                                "</td>
                        </tr>
 
                        <tr>  
                                <td align='right'><b>" . wfMsg( $MsgPrefix . 'status' ) . ":</b></td>  
                                <td>" .
                                wfElement( 'input', array(
                                'type'  => 'text',
                                'name'  => 'wpcurAction',
                                                        'size'  => '20',
                                                        'readonly' => 'readonly',
                                'value' => $curAction
                                )) .
                                "</td> 
                        </tr>
 
                        <tr>
                                <td/>
                                <td>" .
                                wfElement( 'input', array(
                                'type'  => 'submit',
                                'name'  => 'create',
                                'value' => wfMsgHtml( 'uploadbtn' )
                                )) .
 
                                // hidden elements
                                wfElement( 'input', array(
                                'type'  => "$hidden",
                                'name'  => 'wpcurUploadFile',
                                                        'size'  => '20',
                                                        'maxlength' => '150',
                                'value' => $curUploadFile
                                                )) .
 
                                wfElement( 'input', array(
                                'type'  => "$hidden",
                                'name'  => 'wpcurInfo',
                                                        'size'  => '20',
                                'value' => $curInfo
                                )) .
                                "</td>
                        </tr>
                        </tbody>
                        </table>
                        </form>\n"
                        );
 
                // do the works
                // if ($this->curRow > 1) 
                        // $wgOut->addHTML("<b>Finished uploading data for article no. " . ($this->curRow + 1) . ".</b>");
                        // $wgOut->AddHTML ('<script type="text/javascript">
                                        // var jscount = document.userForm.wpcurRow.value;
                                        // document.write("<b>Uploading data for article no2. " +
                                        // jscount +
                                        // ".Ende</b>");
                                        // </script>');
                unset($errormsg);
                $editAllowed = $wgUser->isAllowed('edit');
                if ($editAllowed) {
                        if ($handle = fopen($UploadFile, "r")) {
 
                                // search for pagetitle
                                $headerline = fgets($handle);
                                $headers = preg_split($sepPattern,trim($headerline));
                                unset ($colPageTitle);
                                foreach ($headers as $key => $header) {
                                        $headers[$key] = trim($header);
                                        if ( stripos($header, "pagetitle") === 0 ) $colPageTitle = $key;
                                }
 
                                // Loop through the each line of the file if we have a pagetitle column
                                if (isset($colPageTitle)) {
                                        $cRow = 0;
                                        $sRow = $this->curRow;
                                        if (!is_numeric($this->curRow)) $this->curRow = 0;
                                        while ($dataline = fgets($handle)) {
                                                $cRow += 1;
 
                                                // Process the line if it's not before the start-line
                                                if ($cRow >= $this->curRow) {
                                                        $this->curRow = $cRow;
                                                        $data = preg_split($sepPattern,trim($dataline));
                                                        $curInfo += 1;
                                                        if (is_array($data)) {
                                                                $pageTitle = trim($data[$colPageTitle]);
                                                                if (!empty($pageTitle)) {
                                                                        $ret = $this->MakeArticle($pageTitle, $template, $headers, $data);
                                                                        if ($ret !== true)
                                                                                $wgOut->AddWikiText("Error creating article: $ret");
                                                                }
                                                        }
                                                }
 
                                                // check, if we are through
                                                if (feof($handle) || ($this->curRow >= $endRow && $endRow > 0)) {
                                                        $wgOut->addHTML('<script type="text/javascript">
                                                                if (document.userForm.wpcurAction.value == "start") {
                                                                        document.userForm.wpcurInfo.value = 1; }
                                                                else { document.userForm.wpcurInfo.value = ' . $curInfo . '}
                                                                document.userForm.wpcurAction.value = "running";
                                                                document.userForm.wpcurUploadFile.value = "' . addslashes($UploadFile) . '";
                                                                document.userForm.wpcurRow.value = "' . ($this->curRow+1) . '";
                                                                document.userForm.wpendRow.value = "' . (2*$this->curRow-$sRow+1) . '";
                                                                </script>');
                                                        unset($UploadFile);
                                                        $bolFinished = true;
                                                        $this->curRow = 0;
                                                        break;
                                                }
                                        }
                                }
                                else $errormsg = "One column needs to be defined as \"pagetitle\".";
                                fclose ($handle);                                                  
                        }
                        elseif ($UploadFile) $errormsg = "Couldn't open file.";
                }
                else $errormsg = "Not allowed to edit. Please log in first.";
 
                if (isset($errormsg)) $wgOut->AddWikiText("'''Error: $errormsg'''");
 
                // Output
                $output = "<br />" . wfMsg( $MsgPrefix . 'lastmessage' );
                #$wgOut->addHTML( $output );

                //automatically repeat function until upload is finished
                if (0 && $this->curRow > 1 && !empty($UploadFile)) {
                        #echo "<br>c: $this->curRow";
                 #sleep (2);
                 $wgOut->addHTML('<script type="text/javascript">
                                document.userForm.submit();
                                </script>');
                } 
                elseif ($bolFinished)
                        $txt = wfMsg( $MsgPrefix . 'finished' );
                        $txt = ereg_replace('\$1', utf8_encode($curInfo), $txt);
                        $wgOut->addHTML("<br /><b>$txt</b>");
 
        }
 
        function MakeArticle($pageTitle, $templateName, $tvars, $data, $summary='') {
                global $wgOut;
                // $pageTitle: Article name
                // $templateName: Full name of template, including Template:
                // $tvars: array of template variables
                // $tvarCol: array of column numbers corresponding to $tvars
                // $data: array of data
                // $summary: article change summary information
                $MsgPrefix = $this->MsgPrefix;
 
                $summary .= " (auto upload csv)";
                $summary = trim($summary);
                // get template title without "template:"
                if (preg_match("/:(.*)/", $templateName, $ret ) ) {
                        $templateTitle = $ret[1];
                        #print "<br>$templateTitle";
         }
                else $templateTitle = $templateName;
 
                //create content
                $content = '{{' . "$templateTitle\r\n";
 
                //nice output format
                $maxlen = 0;
                foreach ( $tvars as $tvar ) {
                        if ( mb_strlen ($tvar) > $maxlen ) $maxlen = mb_strlen ($tvar);
                }
                //populate vars
                foreach ( $tvars as $key => $tvar ) {
                        $space = str_repeat(" ", $maxlen - mb_strlen($tvar));
                        $content .= "|$tvar$space = " . utf8_encode($data[$key]) . "\r\n";
                }
                $content .= '}}' . "\r\n";# . time() . "\r\n";
         #print "$content";

                //create article
                $titleNew = title::newFromText(htmlentities($pageTitle));
                $articleNew = new Article( $titleNew );
                if( $titleNew->getArticleID() == 0 ) {
                        $mode = EDIT_NEW;
                        $ctext = 'created';
                }
                else {
                        $mode = EDIT_UPDATE;
                        $ctext = 'changed';
                        // smart edit, only replace template
                        $t = explode('{{', $articleNew->getContent()); //all template starts
                        echo "<br>";
                        #print_r ($t); echo "<br>";
                 if (count($t) > 1) {
                                //find our template, for now expect only one
                                $start = true;
                                $tc = '';
                                foreach ( $t AS $key => $x )
                                {
                                        $xl = ltrim($x);
                                        if (stripos($xl, $templateTitle)=== 0 ) {
                                                // $foundkey = $key;
                                                // now we need the end, but there might be templates within the template or following templates
                                                $start = false;
                                                $te = explode('}}', $x);
                                                #print_r($te); echo "<br>";
                                         if ( count($te) == 2 ) { //no included templates, if there are, count = 1
                                                        $tc .= substr($content,2) . $te[1];
                                                }
                                                else $tc .= implode('', $te);
                                                // foreach ( $te as $key2 => $y ) {
 
                                                // }
                                        }
                                        else $tc .= $x . '{{'; // rebuild content
                                }
                                $content = $tc;
 
                                // $y = explode ( '}}' , $x , 2 ) ;
                                // echo "<br>";
                                // print_r ($y);
                                // if ( count ( $y ) == 2 )
                                // {
                                        // $z = $y[0] ;
                                        // $z = explode ( '|' , $z ) ;
                                        // $tn = array_shift ( $z ) ;
                                        // $t[$key] = '{{' . $x ;
                                // }
                                // else if ( $key != 0 ) $t[$key] = '{{' . $x ;
                                // else $t[$key] = $x ;
                        }
                        else $content = implode('', $t) . $content; //no template found, so we add to the end
 
                        #if (count($t) == 2) { //simple, only one template

                        // $content_old = $articleNew->getContent();
                        // $reg = '/({{' . $templateTitle . '.*?}})/';
                        // $reg = '/.*?(' . $templateTitle . '.*?)B/';
                        // $reg = '/Sofort([^}]*})/';
                        // echo "<br>";
                        // if (preg_match($reg, $content_old, $regs))
                                // print_r ($regs);
                        // else print "Fehler<br>$content_old<br>$reg";
                }
 
                // create/update article
 
                $createSuccess = $articleNew->doEdit( $content, $summary, $mode ); #| EDIT_FORCE_BOT 
         //sleep (2); // wait between  mass creation
                if ($createSuccess) {
                        $cr = $this->curRow;
                        $txt =        wfMsg( $MsgPrefix . $ctext );
                        $txt = ereg_replace('\$1', utf8_encode($cr), $txt); 
                        $txt = ereg_replace('\$2', utf8_encode($pageTitle), $txt);
                        $wgOut->addHTML("<p>$txt</p>");
                        return true;
                }
        }
 
 
        function LoadTemplate($templateName='') {
                global $namespaceNames, $wgOut;
 
                //accept only templates, with or without "template:"
                // echo "<br>Temp: " . Namespace::getCanonicalName(NS_TEMPLATE) . ", " . NS_TEMPLATE ;
                // $tName = str_replace($namespaceNames[NS_TEMPLATE] . ':', '', $templateName);
                // $tName = $namespaceNames[NS_TEMPLATE] . ':' . $tName;
                // if ($tName <> $templateName) 
                        // $wgOut->addHTML('<script type="text/javascript">
                                // document.userForm.wpTemplate.value = "' . $tName . '";
                                // </script>');
                #print "Template: $templateName";
         $title = title::newFromText($templateName);
                $pageID = $title->getArticleID();
                //Maybe the string template: was not given
                if ($pageID == 0) {
                        $title = title::newFromText($templateName, NS_TEMPLATE);
                        $pageID = $title->getArticleID();
                }
                if ($pageID) {
                        #print "page: $pageID";
                 $article = new Article( $title );
                        $text = $article->getContent();
                        $reg = '/{{{(.+?)}}}/';
                        $varExist = preg_match_all($reg, $text, $tvars, PREG_PATTERN_ORDER);
                        #print_r ($tvars);
                 if ($varExist) {
                                // Variables may be used multiple times in an template, we need to delete all double entries.
                                $ret = array_unique($tvars[1]);
                                return $ret; //return array of template vars; does not check on <nowiki>
                        }
                        else return "novars";
                }
                else return "notemplate";
        }
 
        function loadMessages() {
                self::loadMessagesS( 'messages' );
        }
 
        function loadTitles() {
                self::loadMessagesS( 'titles' );
        }
 
        function loadMessagesS( $MsgType )  {
                // using a function to save some memory instead of a global for the messages
                global $wgMessageCache;
                $Specialpage_Name='UploadCSV'; //needs to be defined here, because it is not always called in an object context
                $extensionName = strtolower($Specialpage_Name);
 
                //Need to change the function name accordingly
                $Messages = SpecialUploadCSV_Messages( $MsgType, $Specialpage_Name );
 
                if ( count ($Messages) == 0 ) return;
                foreach ( $Messages as $lang => $langMessages ) {
                                foreach ( $langMessages as $key => $langMessage ) 
                                        $wgMessageCache->addMessage( $key, utf8_encode( $langMessage ), $lang);
                }
                return; 
        }
}
Personal tools
Namespaces
Variants
Actions
Site
Support
Download
Development
Communication
Print/export
Toolbox