Eigene Erweiterung entwerfen/ExtForm

Zur Navigation springen Zur Suche springen
<?php
  /**
   * MediaWiki extension: OraForm
   * =============================
   *
   * To activate, edit your LocalSettings.php,
   * save this code as 'OraForm.php' and copy the file into the subdirectory OraForm of your extensions-directory and add
   * require_once("$IP/extensions/OraForm/OraForm.php");
   */

  # User Settings

  # require_once("$IP/extensions/OraForm/OraForm.php");

  # Parameter

  # default   ...  Standardbelegung für Eingabefeld
  # style     ...  CSS-Formatierung für Buttons
  # namen     ...  String mit den Namen für die Eingabefelder, durch Leerzeichen getrennt
  # cols      ...  String mit den Parameternamen, durch Leerzeichen getrennt
  #                falls die Anzahl der Eingabefelder von der Anzahl der Parameternamen abweicht,
  #                wird das Minimum der beiden Zahlen herangezogen
  # typ       ...  t/m/j, gibt an ob das Datum ein Tag, Monat oder Jahr sein soll, default: t(Tag)
  # ohne      ...  Form ohne Parameter, benötigt noch weitere Eingaben
  # otext     ...  Buttonbeschriftung wenn SQL ohne Parameter
  # End User Settings

define("ORA_NAME",  "ora");        # Name of tag
define("ORA_IDENTIFIER", "sendOra");  # Name of POST identifier flag
define("ORA_HOOK", "hookOra");      # Name of hook

  if ( !defined( 'MEDIAWIKI' ) ) {
    die( "This is not a valid entry point.\n" );
  }

  $wgExtensionCredits['parserhooks'][] = array(
    'path' => __FILE__,
    'name' => 'OraForm',
    'version' => '0.9',
    'author' =>$extension_AUTH,
    'url' => "$wgServer$wgScriptPath/index.php/Extension:OraForm",
    'description' => 'ermöglicht es, SQL-Abfragen mittels Formulareingabe zu steuern'
  );
  $wgExtensionFunctions[] = 'wfOraFormExtension';

  /*
   * Setup OraForm extension.
   * Sets a parser hook for <ORA_NAME></ORA_NAME>.
   */
  function wfOraFormExtension()
  {
    new OraForm();
  }

  class OraForm
  {
    public function __construct()
    {
      global $wgParser;
      $wgParser->setHook(ORA_NAME, array(&$this, ORA_HOOK));
    }
    public function hookOra($input, $argv, $parser)
    {
      global $IP, $wgServer, $wgScriptPath, $wgUploadPath, $wgHooks, $wgParser, $wgHtml5, $wgScript, $wgOut;

      #if ( !($wgTitle->isProtected ('edit')))
      #  return $this->clear_input(" Die Erweiterung <" . ORA_NAME .
      #  "> darf nur auf geschützten Seiten verwendet werden.");
      #return debug_zval_dump($_POST);
      $input = trim($input);
      $sent = $neu = $reset = $i_felder = $ohne = $otext = '';
      if (!empty($_POST) and !empty($_POST["tuwas"])) $sent= true;

      if ($sent)
      {
        #if (empty($_POST["tuwas"])) return;  # irgendeine andere Aktion
        $reset = ($_POST["tuwas"] == 2); # if sent: do or reset
        $neu   = ($_POST["tuwas"] == 1);
      }

      $div_beg = '<div style="margin-bottom: 0"><div style="';
      $div_beg .= 'width: 15em; ';
      $div_beg .= 'display: inline-block; padding-right: 0.5em; text-align: right">';

      $button_style = 'border-radius: 1em; background-image: linear-gradient(90deg, #8f8,#cfc); padding: 0.5em 1.5em;'
        . ' box-shadow: inset -2px -2px 5px #080; color: #080; font-weight: bold; font-size: 110%' ;
      if (!empty($argv["style"])) # Änderung der Buttons möglich
        $button_style = $argv["style"];

      $ohne = false;
      if (!empty($argv["ohne"])) # Buttonbeschriftung wenn SQL Statement ohne Parameter
      {
        $ohne = $argv["ohne"];
        #$reset = false; # wenn keine Parameter dann gibt es auch kein Zurücksetzen
      }

      # Radiobutton abfragen
      $radio = '';  # initialisieren um Fehlermeldungen zu vermeiden
      if (!empty($argv["radiobutton"]) ) # es soll ein Feld mit Radiobuttons initialisiert werden
      {
        #$radioidx= intval($argv["radioindex"]);
        #íf (!empty($radioindex)) # wenn Index fehlt ist alles andere hinfällig
        #return $radioidx;
        $radiolabels =  preg_split("/[\?\t\r\n\f\x0B]/", $argv["radiolabels"]);
        $radiobuttons = preg_split("/[;\?\t\r\n\f\x0B]/", $argv["radiobuttons"]);

        $buttonzahl = count($radiobuttons) < count($radiolabels) ? count($radiobuttons) : count($radiolabels);

        #return implode(":",$radiobuttons) . count($radiobuttons);
        $radioname = $argv["radiobutton"];
        $radio = '<div style="width: 15em; margin-left: 15em;"><fieldset><legend>' . $radioname . ':</legend>';
        for ($x = 0; $x < $buttonzahl; $x++)
        {
          $radio .= "<label>" . '<input type="radio" name="' . $radioname . '" value="' . $x;
          $radio .= $x ? '' : 'checked="checked"' ; # das erste Element checken
          $radio .= '">' . $radiolabels[$x] . "</label><br>";
        }
        $radio .= "</fieldset></div>";

      }

      $dtyp   = 'd'; $datumtext = 'Datum'; $dtxt = '{{#time:Ymd|'; # Datumseinstellungen: d/m/y
      # wenn nach Tag abgefragt wird: dtyp=d, Standardwert: gestern
      # wenn Monat gebraucht wird:    dtyp=m, Standardwert: Vormonat

      if (!empty($argv['typ']) and empty($ohne))
        switch(strtolower($argv['typ']))
      {
        case 'j':
        case 'y':
        case 'jahr':
        case 'year':
          $dtyp   = 'j';
          $datumtext = 'Jahr';
          $dtxt = '{{#time:Y0101|';
          break;
        case 'm':
        case 'monat':
        case 'month':
          $dtyp   = 'm';
          $datumtext = 'Monat';
          $dtxt = '{{#time:Ym01|';
          break;
      }

      if (!empty($argv['datetext']))
        $datumtext = $argv['datetext'];

      if (empty($ohne))
        if (empty($argv["default"])) $defdatum  =  $this->check_input('44.14.2011', 'd', $dtyp);
        else $defdatum  =  $this->check_input($argv["default"], 'd', $dtyp);
      if (!$sent and empty($ohne)) $datum = $defdatum;               # wenn Formular noch nicht abgeschickt wurde
      #return $defdatum . 'sent' . count($_POST);
      $ccol = $cnames = -1;
      $felder = [];

      if (!empty($argv["cols"]))
      # Namen der Vorlagenparameter
      # falls man benannte Parameter verwenden will
      {
        #return "eingabefelder: " . $argv["cols"];
        $felder = explode(' ', $argv["cols"]);
        $ccol   = count($felder);
      }
      else
      {
        $felder = false;
        $ccol   = 999;
      }

      if (!empty($argv["namen"]) )
      # die Beschriftung der Eingabefelder
      # durch Leerzeichen getrennt (jetzt mag ich es nicht mehr auf regex ändern)
      {
        $namen = str_replace('_', ' ', explode(' ', $argv["namen"])); # "_" durch Leerzeichen ersetzen
        $cnames = count($namen);
      }

      $zahl = ($ccol < $cnames) ? $ccol : $cnames; # Zahl der Eingabefelder ermitteln, es dürfen nur so viele sein wie Feldnamen angegeben
      $feld  = array_fill(0, ($zahl>0) ? $zahl : 0, '');

      if (empty($ohne))
      {
        $datum =  $defdatum;
        if (!empty($_POST['datum']))
          $datum = $this->check_input($_POST['datum'],'d', $dtyp);
      }

      if ($sent and !$reset)
      {
        if ($zahl>=0) $feld = $_POST['feld'];
        if (!empty($_POST['datum']))
          $datum = $this->check_input($_POST['datum'],'d', $dtyp);
        else
        {
          if (!empty($argv["default"]))
            $datum =  $this->check_input($defdatum, 'd', $dtyp);
          else
            $datum = $this->check_input('44.14.2011', 'd', $dtyp);
        }
      }

      if ($reset)
      {
        $az    = ($zahl>0) ? $zahl : 0;
        $feld  = array_fill(0, $az, '');
        $datum = $this->check_input('44.14.2011', 'd', $dtyp);
        if (!empty($argv["default"])) $datum = $defdatum;
      }

      # variable Feldanzahl für Abfragemöglichkeiten
      # zuerst steht immer ein Datumswert außer es wird ohne angegeben
      if (empty($ohne))
        $i_felder = '<div style="margin-bottom: 1em">' . $div_beg . $datumtext
        . ':</div><input type="text" name="datum" size="10" maxlength="10" value="' . $datum . '"></div>';
      #else
        #$i_felder = '<div style="margin: 1em; border: 1px solid green"></div>';
      for ($x = 0; $x < $zahl; $x++)
      {
        $i_felder .= $div_beg . $namen[$x] . ':</div><input type="text" name="feld[]" size="10" value="' . $feld[$x] . '"></div>';
      }
      if (empty($ohne)) $i_felder .= '</div>';
      #$meintitel = $wgOut->getPageTitle();
      
      $formid = str_shuffle('abcdefghijklmnopqrst');
      $myForm = '<div style="border: 2px dotted #afa; display: inline-block; padding: 1em"><form id="' . $formid . '" method="post">';
      $myForm .= '<input type="hidden" name="action" value="view" >' ;
      $myForm .= '<input type="hidden" name="' . ORA_IDENTIFIER . '" value="send" >';
      $myForm .= $i_felder . $radio;
      if (!empty($ohne)) $myForm .= '<div style="margin: 0.5em; "></div>';
      $myForm .= $div_beg . '<button style="' . $button_style . '" type="submit" name="tuwas" value="3" formmethod="post">';
      $myForm .= 'Abfrage durchführen';
      $myForm .=  '</button></div>';
      $myForm .= '<div style="display: inline-block; padding-right: 0.5em;"><button style="';
      $myForm .= $button_style . '" type="submit" name="tuwas" value="1" formtarget="_blank" formmethod="post">';
      $myForm .= 'Abfrage in neuem Fenster durchführen';
      $myForm .= '</button></div>';
      $myForm .= '<button style="' . $button_style . '" type="submit" name="tuwas" value="2" formmethod="post">Eingabe zurücksetzen</button></div>';

      $myForm .= '</form></div>';
      $erg = $dateval = '';
      if ($sent and !$reset)
      # das Formular wurde gesendet und nicht zurück gesetzt
      {
        if (empty($ohne)) $dateval = $datum;# $this->check_input($_POST['datum'],'d', $dtyp); else $dateval = '1.1.2019';
        $mitradio = '';
        #return "Das soll das Eingabedatum sein : " . $dateval;
        #return implode(":", $feld) . count($feld); # . implode(":", $felder) ;
        if ($radio) # Radiobuttons
        # die Vorlage sollte die Parameter radio und radiolabel auswerten
        {
          $i = intval($_POST[$radioname]);
          $mitradio = '|radio=' . $radiobuttons[$i] . '|radiolabel=' . $radiolabels[$i];
          #return "index: "  . $radioidx . $radioname . $radiolabels[$i] . $radiobuttons[$i];
          #$feld[$radioidx-2] = $radiobuttons[$i];
          #$feld[$radioidx-1] = $radiolabels[$i];
        }
        #return implode(":", $feld) . '<br>Zahl: ' . $radioidx .  $radiobuttons[$i] .  $radiolabels[$i]; # . implode(":", $felder) ;
        # dateval: Datumswert
        # feld: Array mit den Parameterwerten
        # felder: Array mit den Parameternamen, optional
        $content = array($dateval, $feld, $felder);
        #return implode(':',$felder) . $dateval;
        $erg   = $this->DoSomething($content, $input . $mitradio);
        $seite = $this->render_wikitext($erg);
        if ($neu)
          $myForm  = $seite;
        else
          $myForm .= $seite;
        if (!empty($argv["mitvorlage"]))
          $erg="<p><pre>" . $erg . "</pre>";
          else $erg='';
        }
      return $myForm . $erg;
    }
    private function clear_input($data)
    {
      return htmlspecialchars(stripslashes(trim($data)));
    }

    private function render_wikitext($input)
    {
      global $wgParser;
      $output = $wgParser->recursiveTagParse( $input );
      return $output;
    }

    private function check_input($data, $typ = 'int', $was = 'd')
    {
      global $IP, $wgServer, $wgScriptPath, $wgUploadPath, $wgHooks, $wgParser, $wgHtml5, $wgScript, $wgTitle;

      switch($typ)
      {
        case 'int':
        case 'i':
        default:
          return intval($data );
          break;
        case 'date':
        case 'd':
        case 'datum':
          $datestring = '{{#time:j.n.Y|';
          if ($was == 'y' or $was == 'j') $datestring = '{{#time:Y|';
          if ($was == 'm')                $datestring = '{{#time:1.n.Y|';
          $test = $wgParser->recursiveTagParse( '{{#time:l, j. F Y|' .  $data . '}}' );
          if (strpos($test, 'error'))
          {
            if ($was == 'm')
              return $wgParser->recursiveTagParse( $datestring . '-1 months}}' );
            if ($was == 'y' or $was == 'j')
              return $wgParser->recursiveTagParse( $datestring . '-1 years}}' ) ;
            return $wgParser->recursiveTagParse( $datestring . '-1 days}}' ) ;
          }
          else
            return $wgParser->recursiveTagParse($datestring .  $data . '}}');
      }
    }

    private function DoSomething($params, $input)
    {
      global $IP, $wgServer, $wgScriptPath, $wgUploadPath, $wgHooks, $wgParser, $wgHtml5, $wgScript, $wgTitle, $wgOut;
      #
      # derzeit ist außer dem Datum noch keine Auswertefunktion implementiert
      #
      # wenn wir ein Select-Statement haben, müssen wir orasql hinzufügen
      # params[0]: Datum
      # params[1]: Array mit den restlichen Parametern
      # params[2]: Array mit den Parameternamen, optional

      $sel = strtolower(substr($input,0,6));
      if ($sel == "select")
      {
        # wenn die Abfrage direkt eingefügt wird, können keine Parameter berücksichtigt werden
        #$wrapped = $this->render_wikitext('<orasql>' . $input . '</orasql>');
        $wrapped = '<orasql>' . $input . '</orasql>';
      }
      else
      {
        # als input muss eine Vorlage übergeben werden, die orasql auswertet
        $argstr   = '|1=' . $params[0] ;                 # der erste Parameter muss das Datum sein

        if (!empty($params[1]) and is_array($params[1])) # Auswertung der restlichen Parameter
        {
          $argnames = false;
          $args     = $params[1];
          $n        = count($args);
          if (is_array($params[2])) # ist ein Array mit Parameternamen vorhanden?
            $argnames = $params[2]; # wenn ja übernehme Parameternamen für Vorlage
          for ($x = 0; $x < $n; $x++)
          {
            if (!empty($args[$x])) $argstr .= '|' . (!$argnames ? $x+2 : $argnames[$x]) . '=' . $args[$x];
          }

        }
        $sql = "{{" . $input . $argstr . "}}";

        $wrapped = "{{" . $input . $argstr . "}}";
      }

      return $wrapped;
      #return $this->render_wikitext($wrapped) . '<p>' . $wrapped . '<p>' . $sql;
      #return "insert a useful action here";
    }
  }