Eigene Erweiterung entwerfen

Zur Navigation springen Zur Suche springen

Erweiterungen müssen ständig aktualisiert werden, wenn eine neue MediaVersion erscheint, weil die verwendeten Klassen die Tendenz haben, abgeschafft zu werden.

Ein Formular für Berechnungen entwerfen

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

  # User Settings

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

  # Parameter

  # inlabels  ...  Beschriftung der Eingabefelder
  # inids     ...  eindeutige IDs für die Eingabefelder (muss je Seite eindeutig sein)
  # ivalues   ...  Vorbelegung der Eingabefelder
  # outlabels ...  Beschriftung der Ausgabefelder
  # outids    ...  eindeutige IDs für die Ausgabefelder (muss je Seite eindeutig sein)
  # onclick   ...  Berechnungsvorschrift, was bei Mausklick passieren soll
  # oninput   ...  Berechnungsvorschrift, was bei Dateneingabe passieren soll
  #                zumindest eine der beiden Eingaben muss vorhanden sein
  #                die fehlende wird automatisch durch die andere ergänzt
  # *********************************************************************************************
  #                Formatierung
  # marginright ...  Abstand zwischen Beschriftung und Ein/Ausgabefeld
  # marginleft  ...  Abstand links
  # fontsize    ...  Schriftgröße
  # lwidth      ...  Breite der Beschriftungsfelder
  # nwidth      ...  Breite der numerischen Felder
  # End User Settings

  # Diese Erweiterung erzeugt ein Formular zur Durchführung einfacher Berechnungen.
  # Damit sollen gewisse Überprüfungen einfacher gemacht werden.
  # Durch eine Extension wird die Aktivierung von RawHTML im Wiki überflüssig,
  # somit werden viele Bearbeitungsschritte wieder einfacher
  # es wird ein Formular erzeugt, dieses besitzt jedoch keinen Submit-Button
  # jedes Formular erhält eine zufällige ID, dadurch können mehrere Formulare auf einer Seite 
  # verwendet werden
  # JavaScript muss aktiviert sein, sonst funktioniert die Berechnung nicht
  # im IE funktioniert die Berechnung ebenfalls nicht
  
  define("X_CALC_TAG", "calc");
  define("X_CALC_HOOK", "hookCalc");
  define("X_CALC_NAME", "CalcForm");
  
  if ( !defined( 'MEDIAWIKI' ) ) {
    die( "This is not a valid entry point.\n" );
  }

  $wgExtensionCredits['parserhooks'][] = array(
    'path' => __FILE__,
    'name' => X_CALC_NAME,
    'version' => '0.9',
    'author' =>$extension_AUTH,
    'url' => "$wgServer$wgScriptPath/index.php/Extension:" . X_CALC_NAME,
    'description' => 'erzeugt Eingabeformulare zum Rechnen'
  );
  $wgExtensionFunctions[] = 'wfCalcFormExtension';

  /*
   * Setup OraForm extension.
   * Sets a parser hook for <X_CALC_HOOK></X_CALC_HOOK>.
   */
  function wfCalcFormExtension()
  {
    $extension_name = X_CALC_NAME;
    new $extension_name();
  }

  class CalcForm
  {
    public function __construct()
    {
      global $wgParser;
      $wgParser->setHook(X_CALC_TAG, array(&$this, X_CALC_HOOK));
    }
    public function hookCalc($input, $argv, $parser)
    {
      global $IP, $wgServer, $wgScriptPath, $wgUploadPath, $wgHooks, $wgParser, $wgHtml5, $wgScript, $wgTitle, $wgOut;

      #return debug_zval_dump($_POST);
      $input = trim($input);
      $br = '<br>';
      $onclick = $oninput = $inlabels = $outlabels = $inids = $outids = $ivalues = '' ;
      $lwidth = '10em'; $nwidth = '5em';
      $owidth = $iwidth = $lwidth;
      $marginright = '0.5em'; $marginleft = '0'; $marginbottom = '0.5em'; $oright='0';
      $fontsize = '1em'; $addstyle= '';

      foreach ( $argv as $arg => $val )
      {
        $$arg = $val; # die Variablen erhalten den Namen der Parameter
      }

      if (empty($onclick) and empty($oninput)) return "irgendeine Berechnungsvorschrift sollte schon vorhanden sein";
      else {
        if (empty($onclick)) $onclick=$oninput;
        if (empty($oninput)) $oninput=$onclick;
      }

      # Ein- und Ausgabebeschriftungen werden als Text übergeben, der durch ? getrennt ist
      $ilabels = preg_split("/[\?\t\r\n\f\x0B]/", $inlabels);
      $olabels = preg_split("/[\?\t\r\n\f\x0B]/", $outlabels);

      # Ids für In- und Out-Felder
      # deswegen erforderlich, damit mehrere Formulare auf einer Seite verwendet werden können
      # automatische Generierung ist mir derzeit zu kompliziert
      # da ich die Berechnungsergebnisse dann irgendwie auf diese Id's hintrimmen müsste
      $iids = preg_split("/[\?\t\r\n\f\x0B]/", $inids);
      $oids = preg_split("/[\?\t\r\n\f\x0B]/", $outids);

      $istyle = "width: $iwidth; display: inline-block; font-size: $fontsize; font-weight: bold; padding: 0 0.5em;" .
                "background-image: linear-gradient(#eaeaea, #f9f9f9, #eaeaea); margin-right: $marginright; margin-bottom: $marginbottom;";
      $ostyle = "width: $owidth; display: inline-block; font-size: $fontsize; font-weight: bold; padding: 0 0.5em;" .
                "background-image: linear-gradient(#eaeaea, #f9f9f9, #eaeaea); margin-right: $marginright; margin-bottom: $marginbottom;";

      $nstyle = "width: $nwidth; font-size: $fontsize; display: inline-block; background-image: linear-gradient(#f9f9f9, #eaeaea); " .
                "padding: 0 0.2em 0 0; margin-bottom: $marginbottom; margin-right: $oright;";
      #return $style . $lstyle;
      if (empty($class)) $class = "mono";

      $izahl = count($iids);
      $ozahl = count($oids);

      $ivals  = array_fill(0, $izahl, '');
      $ivals  = !empty($ivalues) ? preg_split("/[\?\t\r\n\f\x0B]/", $ivalues) : array_fill(0, $izahl, '');

      $iput = "<div style='margin-left: $marginleft;$addstyle'>";
      for ($x = 0; $x < $izahl; $x++)
      {
        $iput .=   "<div style='$addstyle'><div style='$istyle' class='$class'>$ilabels[$x]</div><input " .
                  "style='$nstyle' id='$iids[$x]' type='text' value='$ivals[$x]' min='0'></input></div>
";
      }
      $iput .= '</div>';
      
      $oput = '';
      for ($x = 0; $x < $ozahl; $x++)
      {
        $oput .=   "<div style='$ostyle' class='$class'>$olabels[$x]</div><output " .
                  "style='$nstyle' class='$class' id='$oids[$x]' type='text'></output>";
      }
      
      $formid = str_shuffle('abcdefghijklm');
      $myform = "<form id='$formid' oninput='$oninput' onclick='$onclick'>" . $iput . $oput . "</form>";

      return $myform;

    }

  }

Ein Formular für Vorlagenauswertung entwerfen

Diese Erweiterung wertet Vorlagen aus, deren Parameter über ein Eingabeformular eingegeben werden
<?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";
    }
  }


Vorlagenauswertung

Diese Erweiterung wertet Vorlagen mit Parametern aus, wobei die Parameter über die URL übergeben werden.

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

	# User Settings

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

	# Parameter

	# derzeit keine

	# End User Settings
	# diese Erweiterung ruft eine Vorlage mit Parametern zum Auswerten auf
	# das Tag wird in der Seite gespeichert <auswertung />
	# für die Anwendung wird die Seite folgendermaßen aufgerufen: Auswertung?vorlage=xxx&name=was_soll_ausgewertet_werden
	# es erfolgt auch eine Auswertung der im Tag enthaltenen Parameter
	# da diese später ausgewertet werden, überschreiben sie evtl. über die URL übergebene Paramter

	define("AUSWERT_NAME",  "auswertung");				# Name of tag
	define("AUSWERT_IDENTIFIER", "sendAuswertung");	# Name of POST identifier flag
	define("AUSWERT_HOOK", "hookAuswertung");			# Name of hook

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

	$wgExtensionCredits['parserhooks'][] = array(
		'path' => __FILE__,
		'name' => 'ExtAuswertung',
    'version' => '0.9',
    'author' => $extension_AUTH,
		'url' => "$wgServer$wgScriptPath/index.php/Extension:ExtAuswertung",
		'description' => 'wertet eine Vorlage mit Parametern aus'
	);
	$wgExtensionFunctions[] = 'wfExtAuswertung';

	/*
 	* Setup ExtAuswertung extension.
 	* Sets a parser hook for <auswertung></auswertung>.
 	*/
	function wfExtAuswertung()
	{
		new ExtAuswertung();
	}

	class ExtAuswertung
	{
		public function __construct()
		{
			global $wgParser;
			$wgParser->setHook(AUSWERT_NAME, array(&$this, AUSWERT_HOOK));
		}
		public function hookAuswertung($input, $argv, $parser)
		{

			global $IP, $wgServer, $wgScriptPath, $wgUploadPath, $wgHooks, $wgParser, $wgHtml5, $wgScript;
			$output = 'Vorlagenauswertung';
	   	global $wgUploadDirectory, $wgArticlePath, $wgTmpDirectory;

		$vorlage = $was = $liste = "";

		foreach ( $_REQUEST as $arg => $val )
		{
		  $$arg = $val; # die Variablen erhalten den Namen der Parameter
		  if ($arg != 'vorlage') $liste .= "|$arg=$val";
		}

		foreach ( $argv as $arg => $val )
		{
		  $$arg = $val; # die Variablen erhalten den Namen der Parameter
		  if ($arg != 'vorlage') $liste .= "|$arg=$val";
		}
		
		$output = "{{" . $vorlage . $liste . "}}";
		if (empty($vorlage)) $output="{{Bluetitel|1=Diese Seite enthält eine Anwendung der [[Extension:OraAuswertung|{{Taste|Erweiterung ExtAuswertung}}]]}}"
		. "{{Absatz2}}"
		. "Der Aufruf soll folgendermaßen erfolgen: In einer Wikiseite {{Taste|seitenname}} das Tag <nowiki><auswertung /></nowiki> speichern, " 
		. "{{Absatz2}}"
		. "die Seite folgendermaßen aufrufen {{Taste|1=seitenname?vorlage=xxx&name=was_soll_ausgewertet_werden}}";
		return $wgParser->recursiveTagParse($output);
		}
	}

Datenbankzugriff auf eine Oracle-SQL-Datenbank

Diese Erweiterung ermöglicht den Direktzugriff auf eine Otacle-Datenbank. Die Ausgabetabellen können mittels CSS-Klassen formatiert werden wie im nachfolgenden Beispiel angegeben.

CSS-Code

/*/Klassen für Oracle-Tabellen
.oratable td:last-of-type  { border:none; }
.oratable tr    { background-image: linear-gradient(#f9f9f9, #eaeaea); border:none; }
/*/
.oratable       { border-collapse: collapse; }
.oratable table,
table.wikitable
                { border: 1px solid #036; border-collapse: collapse; box-shadow: 3px rgba(0,0,0,.35); }
.oratable tr    { background-image: linear-gradient(#f9f9f9, #eaeaea); border:none; }
.oratable td    { padding: 0.1em 0.5em; border-left: 1px solid #666; }
.oratable th    { padding: 0.1em 0.5em; border-left: 1px solid #008fd1; border-bottom: 1px solid #036; font-weight: bold; font-size: 105%; color: #fff; 
                  background-image: linear-gradient(#036, #008fd1); }
.oratable th:first-of-type    { border-left: none; }
.oratable tr:first-child      { border: 1px solid #666; border-radius: 0.5em 0 0 0.5em; }

/*/ Links in einer durch eine Oracle-Abfrage erzeugten Tabelle /*/
.oratable a,			
.oratable a:link,
.oratable a:visited { text-decoration: none; color: inherit; }

.oratable a:hover,
.oratable a:active	{ cursor: default; border: 1px dotted #036; color: #036; }

/* wenn die Tabelle rechts offen sein soll */
.rechtsoffen table         { border-right: none; }
.rechtsoffen td:last-child { border-right: none; background-color: #fff; }

table.sortable > tr > th,
table.sortable > * > tr > th,
table.wikitable > tr > th,
table.wikitable > * > tr > th,
.headerSort
              { background-color: #036; background-image: linear-gradient(#036, #008fd1) !important; color: #fff !important; font-weight: bold !important; font-size: 105%;  }

.single       { border-collapse: collapse; }
.single table { border: 1px solid #005cb8; border-collapse: collapse; box-shadow: 2px 2px 4px #002e5c; }
.single tr    { background-image: linear-gradient(#f9f9f9, #eaeaea); border:none; }
.single td    { padding: 0.1em 0.5em; border-left: 1px solid #666; }
.single th    { padding: 0.1em 0.5em; border-left: 1px solid #85c2ff; border-bottom: 1px solid #005cb8; font-weight: normal; color: #fff; 
                  background-image: linear-gradient(#005cb8, #85c2ff); text-align: right; }

PHP-Code

<?php
  $extension_TAG  = "orasql";
  $extension_HOOK = "hookSql";
  $extension_NAME = "OraSql";    

  $wgExtensionFunctions[] = "wfOraSqlSetup";
  $wgExtensionCredits['parserhook'][] = array(
  'name' => 'OraSql',
  'url' => "$wgServer$wgScriptPath/index.php/Extension:OraSql",
  'author' => $extension_AUTH,
  'version' => '0.9',
  'description' => 'Zugriff auf eine Oracle-Datenbank, nur SELECT erlaubt',
  );

function wfOraSqlSetup()
/*/
  Die Stelle, an der das Programm in das Wiki "eingehängt" wird
  Der [[Hilfe:Tags|Text des Tags]] wird hier festgelegt
  der Aufruf der Erweiterung erfolgt mit <orasql>...</orasql>
/*/
{
  global $wgParser;
  $wgParser->setHook( "orasql", "wfOraSql" );
}

function wfOraSql( $input, $argv, $parser )
/*/
  Eintragungen in der LocalSettings.php
/*/
{
  global $oraDBUser, $oraDBPass, $oraDBDatabase, $wgParser;

  $dbID = 'Standard-Oracle-Instanz'; 
  $class = $view = $onlycode = $table = $code = $header = $spaltentitel = $entiti = $offen = '';
  #return '';
  /*/
  Abfrage von zusätzlichen parametern
  das sind jene, die innerhalb der spitzen Klammern stehen
  /*/
  foreach ($argv as $key => $val)
  {
    $$key = $val; # die Variablen erhalten den Namen der Parameter
    if ($key == 'dbid')
      $dbID = $val;
    else if ($key == 'spaltentitel')
              $spaltentitel = preg_split("/[\?\t\r\n\f\x0B]/", $val);
    else if (($key == 'onlycode') or ($key == 'codeonly'))
              $onlycode = $val;
  }

  $input = $input;
  if (!empty ($onlycode))  # nur Code darstellen
  {
    $coco = $wgParser->recursiveTagParse("{{coco|lang=sql|border=none|kla=|code=" . $input . "}}");
    return $coco;
  }
  
  $page = str_replace('"', "\"", $input); // doppelte Anführungszeichen escapieren

  // wenn zu Beginn kein select steht, wird eines dazu gefügt
  $sel = strtolower(substr($page,0,6));
  if ($sel != "select" and substr($sel,0,2) != "--")
    $page .= 'SELECT ' . $page;
  $wiki = ($table != 'wiki');
  
  // Zugangsdaten für die Oracle-Datenbank
  // es können verschiedene UserIDs bzw. Datenbankserver in der LocalSettings.php festgelegt werden

  $db_server   = $oraDBDatabase[$dbID];
  $db_username = $oraDBUser[$dbID];
  $db_password = $oraDBPass[$dbID];

  // öffnen der Verbindung
  $conn = oci_connect($db_username, $db_password, $db_server, 'AL32UTF8');
  if (!$conn)
  {
    // Verbindung hat nicht geklappt, Rückgabe einer Fehlermeldung
    $m = oci_error();
    $output = $m['message'] . "\n";
  }
  else
  {
    $zz = true;
    //$output = "Connected to Oracle!";
    // Verbindung hat geklappt
    $tablinks = '';
    $stid = oci_parse($conn, $page);
    $result = oci_execute($stid);
    
    if (!$result)
      return "SQL Fehler : " . $wgParser->recursiveTagParse("{{coco|lang=sql|border=none|kla=|code=" . $page . "}}");
    $ncols = oci_num_fields($stid);  
    $nrows = oci_num_rows ($stid);
    #var_dump($view );
    $crlf = chr(13) . chr(10);
    if ($view == 'single' and $nrows <= 1) # Einzelansicht nur wenn eine Zeile zurückgeliefert wurde
    {
      $output = "<div class='mono single $class' ><table>\n";
      $row = oci_fetch_array($stid, OCI_NUM+OCI_RETURN_NULLS);
      #var_dump($row );
      for ($i = 1; $i <= $ncols; $i++)
      {
        $column_name  = empty($spaltentitel[$i-1]) ? oci_field_name($stid, $i) : $spaltentitel[$i-1];
        $val = ($row[$i-1] !== null ? htmlentities($row[$i-1], ENT_QUOTES) : " ");
        $output .= "<tr><th>$column_name:</th><td>$val</td></tr>";
      }  
    }
    else 
    {
      if ($view == 'zahl')
      {
        # es wird ein einziger Wert ohne Formatierung als Ergebnis zurück geliefert
        $row = oci_fetch_array($stid, OCI_NUM+OCI_RETURN_NULLS);
        if ($row == false) return "---";
        $mywert = $row[0];
        return $mywert;  
      }
      $oclass = empty($offen) ? "" : " rechtsoffen";
      
      $output = $wiki ? "<div class='mono oratable plainlinks tablink neu $oclass' ><table class='$class'>\n"
      : "{| class='wikitable sortable mono plainlinks tablink neu $class'" . $crlf; #  . "\n|-" . $crlf; 
      $output .= $wiki ? "<tr>" : $crlf . "\n!";
      $snrcol = ''; $tablinks = array();
      for ($i = 1; $i <= $ncols; $i++)
      {
        $feldname = strtolower (oci_field_name($stid, $i));
        if ($feldname == "snr" or $feldname == "sondennummer"  or strpos(strtolower ($feldname), 's#') !== False)
        {
          $snrcol=$i; # Spalte mit Sondennummer eruieren
          $tablinks[] = $i-1;
        }
        else if (strpos( $feldname, 'name') !== False or strpos($feldname, 'sond') !== False)
           $tablinks[] = $i-1;
        $column_name  = empty($spaltentitel[$i-1]) ? oci_field_name($stid, $i) : $spaltentitel[$i-1];
        $output .= $wiki ? "<th>$column_name</th>" : "$column_name !!";
      }  
        #return $feldname . strpos( $feldname, 'name') . " sonde " . strpos($feldname, 'sonde') . "<pre>" . print_r($tablinks) . "</pre>";
      $output = rtrim($output,' !');
      $output .= $wiki ? "</tr>" : $crlf . "\n|-";

      if (!empty($auswertung))
      {
        $mylink ="[{{fullurl:Auswertung}}?vorlage=$auswertung&name=";
        #return $mylink;
      }

      while ($row = oci_fetch_row($stid))
      // alle gefundenen Sätze abarbeiten
      {
        $zz = false;
        $output .= $wiki ? "<tr>" : $crlf . "\n\r|class='$class'|";  // Tabellenzeile
        for ($i = 0; $i < $ncols; $i++)
        {
          $item = $row[$i];
          #$item = htmlentities($row[$i], ENT_QUOTES);
          if (!empty($snrcol)) # eine Spalte mit Sondennummer ist vorhanden
          {
            $snr = $row[$snrcol-1];
            if (in_array($i, $tablinks) and is_numeric($snr)) # eine referenzierbare Spalte liegt vor, aber nur wenn die Sondennumer nicht leer ist
            {
              $item = '[{{fullurl:Snr}}?snr=' . $snr . " " . $item . "]";
            }
          }
          else 
          if (!empty($auswertung) and ($i==0)) # die Spalten sollen mit Auswertung verlinkt werden, in der 1. Spalte muss das Kriterium stehen
            {
              #$item = '[{{fullurl:Snr}}?snr=234 ' . $item . "]";
              #$item = $row[$i] . "$i";
              #return $item . " *** " . htmlentities($row[$i], ENT_NOQUOTES);
              $item = $mylink . urlencode($row[0]) . " " . $item . "]";
            }
          else 
          {
            if (!empty($entiti)) $item = '<span style="white-space: pre">' . htmlentities($row[$i], ENT_NOQUOTES) . '</span>';
          }
          $val = $item !== null ? $item : " ";
          $output .= $wiki ? "<td class='$oclass'>$val</td>\n" : "$val ||";
        }
        $output = rtrim($output,' |');
        $output .=  $wiki ? "</tr>\n" : $crlf . "\n|-";
      }
      if ($zz and (!empty($header))) return "";
    }
    $output .= $wiki ? "</table></div>" : $crlf . "\n|}";
    $output = $wgParser->recursiveTagParse($output);
    #$output .= "<pre>" . print_r($tablinks) . "</pre>" . count($tablinks);
    // Close the Oracle connection
    oci_close($conn);
  
    if (!empty($code))
    {
      if (!isset($titel) or (empty($titel)))
        $titel="";
      else
        $titel = "<div style='font-weight: bold; font-size: larger; margin: 0.75em 0 -0.5em 0; '>$titel</div>";
      $coco = $titel . $wgParser->recursiveTagParse("{{coco|lang=sql|border=none|kla=|code=" . $input . "}}");
      $output .= "$coco";
    }
  }
  return $output;
}

Tabellenwerte mittels SVG darstellen

<?php
  /**
   * MediaWiki extension: OraSVG
   * =============================
   *
   * To activate, edit your LocalSettings.php,
   * save this code as 'OraSVG.php' and copy the file into the subdirectory OraSVG of your extensions-directory and add
   * require_once("$IP/extensions/InlineSVG/OraSVG.php");
   * Verwendung: <orasvg></orasvg>
   */

/*/  # User Settings

  # Parameter

  # default   ...  derzeit keine

  # End User Settings
/*/
  if ( !defined( 'MEDIAWIKI' ) ) {
    die( "This is not a valid entry point.\n" );
  }

  $wgExtensionCredits['parserhooks'][] = array(
    'path' => __FILE__,
    'name' => 'OraSVG',
    'version' => '0.9',
    'author'  =>$extension_AUTH,
    'url' => "$wgServer$wgScriptPath/index.php/Extension:OraSVG",
    'description' => 'stellt SVGs dar'
  );
  $wgExtensionFunctions[] = 'wfOraSVGExtension';

  function wfOraSVGExtension() {
      new OraSVG();
  }

class OraSVG
  {
      public function __construct()
     {
          global $wgParser;
          $wgParser->setHook('orasvg', array(&$this, 'wfOraSVG'));
     }
      public function wfOraSVG($input, $argv, $parser)
     {
       global $wgUploadDirectory, $wgUploadPath, $IP, $wgArticlePath, $wgTmpDirectory, $wgParser;
       global $oraDBUser, $oraDBPass, $oraDBDatabase;
       global $wgServer, $wgScriptPath, $wgUploadPath;
       $dbID = 'Standard-Oracle-Instanz';
      //  Aktionen und Definitionen
      $style = '
<style type="text/css"><![CDATA[
.numbers { fill: green; font-size: 12px; }
.smallnumbers { fill: green; font-size: 10px; }
.label { fill: blue; font-size: 15px; }
.linethick { fill: none; stroke:#6c0; stroke-width: 1; }
.linethin  { fill: none; stroke: #6c0; stroke-width: 0.5; }
.bar { stroke: #036; fill: none; opacity: 1; stroke-width: 0; }
.barg { fill: #6c0; }
.pfad { fill: none; stroke-width: 2; }
]]>
</style>';

      $text_a = '
<g transform="translate(' ;
      $text_b = ') rotate(60)"><text class="label" >' ;

      if (empty($input))
      {
        $page = "SELECT LEVEL X, TRUNC (DBMS_RANDOM.VALUE (1, 1000)) A
,TO_CHAR (ADD_MONTHS (TRUNC (SYSDATE, 'MM'), 1 - LEVEL), 'fmDay, fmDD. fmMonth YYYY', 'NLS_DATE_LANGUAGE=german') TAG
FROM DUAL CONNECT BY LEVEL < 20   ORDER BY 1";
      }
      else $page = str_replace('"', "\"", $input);

      // Zugangsdaten für die Oracle-Datenbank
      // es können verschiedene UserIDs bzw. Datenbankserver in der LocalSettings.php festgelegt werden

      $db_server   = $oraDBDatabase[$dbID];
      $db_username = $oraDBUser[$dbID];
      $db_password = $oraDBPass[$dbID];
      
      // öffnen der Verbindung
      $conn = oci_connect($db_username, $db_password, $db_server, 'AL32UTF8');
      if (!$conn)
      {
        // Verbindung hat nicht geklappt, Rückgabe einer Fehlermeldung
        $m = oci_error();
        return $m['message'] . "\n";
      }
      
      $code = empty($argv["mitcode"]) ? '' : $wgParser->recursiveTagParse("{{hili|lang=sql|code=" . $page . "}}");

      $tablinks = '';
      $stid = oci_parse($conn, $page);
      $result = oci_execute($stid);

      if (!$result)
        return "SQL Fehler : " . $wgParser->recursiveTagParse("{{hili|lang=sql|code=" . $page . "}}");

      $ncols = oci_num_fields($stid);  # Anzahl der Spalten
      $nrows = oci_num_rows ($stid);  # Anzahl der Zeilen
      $y_wert = $label = [];
      while ($row = oci_fetch_row($stid))
      {
        $y_wert[] =$row[1];   # Spalte 2 enthält den Produktionswert
        $label[]  =$row[2];   # Spalte 3 enthält die Beschriftung
      }

      if (empty($y_wert)) return "Im angegebenen Zeitraum sind keine Mengen vorhanden</p>" . $code;
      $max_y = max($y_wert);
      $min_y = min($y_wert);
      if ($min_y > 0) $min_y = 0; # wir fangen nicht über der Nullinie an

      $pfaddaten = [];

      if ($max_y == 0 and $min_y == 0)
      {
        return "Im angegebenen Zeitraum sind keine Mengen vorhanden</p>" . $code;
      }
      $punkte = count($y_wert);
      $faktor = 1200/$punkte;
      #$rh = round($max_y,-round(log10($max_y))) ;

      $hoch = empty($argv["hoch"]) ? 600 : intval($argv["hoch"]);
      $yfaktor = $hoch/($max_y - $min_y); # der Skalierungsfaktor für die y-Koordinaten, damit das Ausgaberechteck genau 600 hoch ist
      $rb = 1200;
      $ry = 0; # Startpunkt des Rechtecks mit den Querlinien

      for ($i=0; $i<$punkte; $i++)
      {
        $pfaddaten[$i] = $y_wert[$i] * $yfaktor;
      }
      #return implode(':', $pfaddaten);

      $farbe = '#036';
      if (!empty($argv["farbe"])) $farbe=$argv["farbe"];
      $pfad = '
<path d="' . $this->toPfad($pfaddaten, $faktor) . '"
class="pfad" stroke="' . $farbe . '" />';

      $rect = '
<rect width="' . $faktor . '" height="';
      $rectg = '
<rect class="barg" width="' . $faktor . '" height="';
      $labels = $bars = '';

      $delta = $faktor/5;
      $lablen = 0;
      #return $punkte;
      for ($i=0; $i<$punkte; $i++)
      {
        $x = $i * $faktor; $xx = $x + $delta;
        $y = $yfaktor * ($max_y - $y_wert[$i] - $min_y);
        $yy = $hoch;
        $ywert = $pfaddaten[$i];

        if (!empty($label[$i]))
        {
          $labels .= $text_a . $xx . ',' . $yy . $text_b . $label[$i] . '</text></g>';
          $bars .= $rectg . $ywert . '" x="' . $x . '" y="0"></rect>';
          if (strlen($label[$i]) > $lablen) $lablen=strlen($label[$i]);
        }
        else
        $bars .= $rect . $ywert . '" x="' . $x . '" y="0"></rect>';
      }
      $bars = '
<g class="bar" transform="translate(0,' . $hoch . ') scale(1,-1)">' . $bars . '</g>';

      if (!empty($argv["bars"]) and $argv["bars"] == 'no')
        $bars='';

      $ylabel = '
<g class="numbers">';
      $ysmall = '
<g class="smallnumbers">';
      $linethick = '
<g class="thick">';
      $linethin = '
<g class="thin">';

      $log = floor(log10($max_y)); # 10er logarithmus des Maximums der Messwerte
      $pow = 10**$log; # die Größenordnung der Messwerte z.B. 0.1, 1, 10...
      $steps = floor($max_y / $pow ); # die Zahl der Querlinien
      #return '<br>ordnung: ' .  $pow . '<br>max: ' .  $max_y . '<br>schritte: ' . $steps;
      for ($i=1; $i<= $steps; $i++)
      {
        $j = $i * $pow ;
        $jj = $hoch - $yfaktor * $j;
        if ($log < 2) $maxlab = number_format($j,2,",",".");
        else $maxlab = number_format($j,0,",",".");
        $ylabel .= '
<text text-anchor="start" dy="0.5" y="' . $jj . '">' . $maxlab . '</text>';
        #if ($i>0 and $i<$val)
        $linethick .= '
<rect y="' . $jj . '" width="1200" height="0.01" class="linethick"/>';
        $j = $j - $pow/2;
        if ($log < 2) $maxlab = number_format($j,2,",",".");
        else $maxlab = number_format($j,0,",",".");
        $jj = $hoch -  $yfaktor * $j;
        $ysmall .= '
<text text-anchor="start" dy="0.5" y="' . $jj . '">' . $maxlab . '</text>';
        $linethin .= '
<rect y="' . $jj . '" width="1200" height="0.01" class="linethin"/>';
        if ($steps < 2)
        {
          $j = $i * $pow - $pow/4;
          if ($log < 2) $maxlab = number_format($j,2,",",".");
          else $maxlab = number_format($j,0,",",".");
          $jj = $hoch -  $yfaktor * $j;
          $ysmall .= '
<text text-anchor="start" dy="0.5" y="' . $jj . '">' . $maxlab . '</text>';
        $linethin .= '
<rect y="' . $jj . '" width="1200" height="0.01" class="linethin"/>';
          $j = $i * $pow - 3 * $pow/4;
          if ($log < 2) $maxlab = number_format($j,2,",",".");
          else $maxlab = number_format($j,0,",",".");
          $jj = $hoch -  $yfaktor * $j;
          $ysmall .= '
<text text-anchor="start" dy="0.5" y="' . $jj . '">' . $maxlab . '</text>';
        $linethin .= '
<rect y="' . $jj . '" width="1200" height="0.01" class="linethin"/>';
        }
      }
      #number_format("1000000",2,",",".")
      # und jetzt noch das Maximum der Messwerte explizit dazu schreiben
      if ($log < 2) $maxlab = number_format($max_y,3,",",".");
      else $maxlab = number_format($max_y,0,",",".");
      $ylabel .= '
<text text-anchor="start" dy="0.5" y="0">' . $maxlab . '</text>
</g>';
      $ysmall .= '
</g>';
      $linethick .= '
</g>';

      $linethin .= '
</g>';
      #return $pow . ' * ' . $max_y . ' * ' . $val . ' # ' . floor(log10($max_y)) . ' + ' . $ry;

      #return '<p>' . $pfad ; <g transform="translate(50,30) rotate(180)">
      $lablen = $lablen * 10;
      $boxheight = $lablen + $hoch;
      $output  = '
<svg
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1"
viewbox="0 0 1300 ' . $boxheight . '" width="1300" height="' . $boxheight . '">
' .
$style .
'
<g transform = "translate(0,20)">
<g transform = "translate(15)">
<rect width="1200" height="' . $hoch . '" y="0"
id="paper" fill="#85c2ff" opacity="0.1" />' .
$bars .
$labels . 
$linethick . $linethin .
$pfad . '
</g>
<g transform = "translate(0)">' .
$ylabel . $ysmall . '
</g> 
</g>' .
'
</svg>';

        #$output = empty($input) ? $svgtest : $input;
        $tmppath = "/images/png/";
        $bildurl = "$wgServer$wgScriptPath$tmppath";
        $bildfolder = $_SERVER['DOCUMENT_ROOT'] . $wgScriptPath . '/images/png/';
        $mydatum = date('Y-m-d-His'); 
        $bildname = "produktionsgrafik-" . $mydatum;
        $html = "<p style='font-size:0.7em'>
<a href='$bildurl$bildname.png' target='_blank'><img src='$bildurl$bildname.png' width='50'>Grafik im PNG-Format speichern</a> 
&middot; <a href='$bildurl$bildname.svg' target='_blank'>Grafik im SVG-Format speichern</a>
</p>";
        $erzeug = $this->toPng($output, $bildfolder, $bildname);
        
        if (!empty($argv["svg"])) $output .= '<pre>' . $wgParser->recursiveTagParse($output) . '<pre>';
        #return $code;
        return '<p>' . $output . '</p>' . $html . '</p>' . $code; 
     }

    private function toPfad($daten, $xfaktor = 10)
    {
      # liefert einen Pfad als Ergebnis zurück
      # aufeinanderfolgende Elemente sollen nur ein Pfadelement ergeben
      # optional können die Daten skaliert werden

      $pfad = '';

      #return implode('+', $daten);
      if (!is_array($daten)) return; # wenn kein Array übergeben wurde, zurück

      #$faktor = 1;
      $max_y = max($daten);
      $wert = $max_y - $daten[0]; # Y-Startwert
      $pfad  = "M0," . $wert;
      $hor   = $xfaktor;

      for ($i=1; $i<count($daten); $i++)
      {
        if ($daten[$i] == $wert) ## Wiederholung des y-Wertes, wir erhöhen nur den Zähler
        {
          $hor+=$xfaktor;
        }
        else
        {
          $vert = ($daten[$i-1] - $daten[$i]);
          $pfad .= "h $hor v $vert ";
          $hor=$xfaktor;
          $wert = $daten[$i];
        }
      }
      # Abschluss des Pfades
      $pfad .= "h $hor";
      return $pfad;
    }

    private function toPng($bild, $pfad, $name, $breit=1300, $hoch=700)
    {
      # wandelt ein SVG in ein PNG um
      # der SVG-Inhalt muss in der Variablen bild gespeichert sein
      # Parameter:
      # bild ... string mit dem SVG-Text
      # pfad ... Pfad des zu speichernden Bildes
      # name ... Name unter dem das Bild gespeichert werden soll
    
       global $wgServer, $wgScriptPath, $wgUploadPath;

      if (empty($bild) or empty($pfad) or empty($name))
      {
        return 'Fehler bei Bildererzeugung, fehlender Parameter';
      }
  
      $bname = $pfad . $name . ".png";
      $im = new Imagick();
      #return "$pfad $name .png";
      
      $svg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
' . $bild;
    
      $im->readImageBlob($svg);
      $geo = $im->getImageGeometry ();
      $hoch= $geo['height']*2 ;
      $breit = $geo['width']*2;
      #return $geo['width'] . $geo['height'] ;
      $svgname = "$pfad$name.svg";
      $x = file_put_contents($svgname, $svg);
      #return "svgname" . $svgname;
      #return "imageblob";
      $im->setImageBackgroundColor(new ImagickPixel('transparent'));
      $im->resizeImage($breit, $hoch, imagick::FILTER_BOX, 1);
      $im->setImageFormat("png");
      #$im->scaleImage($breit, $hoch); 
      $im->borderImage('#fff', 10, 10);
      $im->writeImage($bname);
      $im->clear();
      $im->destroy();
  
      return "Bild als $bname gespeichert";
    }

}