Eine kleine Lilypond Extension für MediaWiki

Begonnen von Manuela, Mittwoch, 23. Januar 2019, 19:15

« vorheriges - nächstes »

Manuela

Da die Score-Extension auf meinem Wiki nicht um die Burg laufen wollte, habe ich eine kleine Erweiterung geschrieben. Diese macht nichts anderes als einen Lilypond-Code als Bild auf der aufrufenden Seite darzustellen. Wie kompliziert der Score sein darf, bevor der Server abstürzt, habe ich nicht getestet.

Der Code führt überhaupt keine Sicherheitsprüfungen durch und sollte daher nur in nicht-öffentlichen Wikis verwendet werden. Lilypond muss installiert sein und ohne Pfadangabe ausführbar sein (könnte man relativ leicht ändern). Eine Datei bleibt pro Aufruf im Zwischenverzeichnis stehen, dank meiner beschränkten Kenntnisse von PHP kann ich das derzeit nicht ändern.

Vielleicht kann jemand den Code brauchen, zumindest als abschreckendes Beispiel  ;)
<?php
/**
 * MediaWiki extension: Lily
 * =============================
 *
 * To activate, edit your LocalSettings.php, add
 * require_once("$IP/extensions/Lilypond/Lily.php");
 * and make sure that the images/lilypond directory is writable.
 *
 * Create a subdirectory Lilypond in your extensions directory
 * and copy this code into a file and name it Lily.php
 *
 * This extension creates an image from Lilypond code
 * Example wiki code: <lily>\relative c' { c d e f g }</lily>
 *
 * Tested with Lilypond version 2.19.82.
 * Lilypond must be executable 
 */

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

use MediaWiki\MediaWikiServices;
use MediaWiki\Shell\Shell;

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

$wgExtensionCredits['parserhooks'][] = array(
'path' => __FILE__,
'name' => 'Lily',
'version' => 0.01,
'author' => 'Manuela',
'url' => '',
'descriptionmsg' => 'lilypond-desc',
);
$wgExtensionFunctions[] = 'wfLilyExtension';
/**
 * @param $parser Parser
 */
 function wfLilyExtension() {
new Lilypond();
}

class Lilypond
{
public function __construct()
{
global $wgParser;
$wgParser->setHook('lily', array(&$this'hookLily'));
}

private function rdStr($length 6)
// Zufallstext generieren, Standardlänge = 6 Zeichen
{
$str "";
$characters array_merge(range('A','Z'), range('a','z'), range('0','9'));
$max count($characters) - 1;
for ($i 0$i $length$i++) {
$rand mt_rand(0$max);
$str .= $characters[$rand];
}
return $str;
}

public function hookLily($code$argv$parser)
// hier erfolgt der Aufruf, ein Bild bleibt im tmp-Verzeichnis stehen
{
global $IP$wgServer$wgScriptPath;
$bildurl $wgServer $wgScriptPath "/images/lilypond/";

$lilypath $IP "/images/lilypond/";

$lilyfile $this->rdStr() ;

$kommando "lilypond -o $lilypath$lilyfile -fpng $lilypath$lilyfile";
$lilycodefile fopen("$lilypath$lilyfile.ly" "w" );
fputs $lilycodefile$code);
fclose $lilycodefile);

$cr_name $lilyfile "cr.png";

shell_exec($kommando);
unlink("$lilypath$lilyfile.ly");  // delete ly-file
$im imagecreatefrompng($lilypath $lilyfile .".png");
$cropped imagecropauto($imIMG_CROP_WHITE);
imagepng($cropped$lilypath $cr_name);
imagedestroy($im);
unlink($lilypath $lilyfile ".png"); // delete image, only the cropped images remains

$output $bildurl $cr_name;
$html "<img src='$output' />";
$ret $parser->insertStripItem($html$parser->mStripState);
return "$ret";
}
}
Danke für eure Hilfe
viele Grüße
-- Manuela

Manuela

#1
Funktioniert nur, wenn die Ausgabe auf einer Seite Platz hat
Danke für eure Hilfe
viele Grüße
-- Manuela

Manuela

#2
Der Code ist jetzt hübscher, er funktioniert auch bei Mehrseitenausgabe, außerdem gibt es Einstellmöglichkeiten für Abstand und Größe der Bilder per CSS bzw. CSS-Klasse

<?php
/**
 * MediaWiki extension: LilyPond
 * =============================
 *
 * To activate, edit your LocalSettings.php, 
 * save this code as 'Lily.php' and copy the file into the subdirectory Lily of your extensions-directory and add
 * require_once("$IP/extensions/Lily/Lily.php");
 * and make sure that the images/lilypond directory is writable.
 * Make sure that Lilypond is installed on your system and executable without path info
 *
 * Example wiki code: <lily3>\version "2.19.80" \relative c' { c d e f g }</lily3>
 * this code produces three pages without tagline and pagenumbers
<lily3>\version "2.19.80"
\header { tagline = ##f }
\paper {
  ragged-bottom = ##t
  ragged-last-bottom = ##t
  print-page-number = ##f
  ragged-right = ##t
}
\relative c' {
  \override Score.BarNumber.stencil = ##f
  c d c c \pageBreak c c c c \pageBreak c c c c
}</lily3>
 *
 * Tested with Lilypond version 2.19.82.
 *
 */

# User Settings

# The following variables can be set in LocalSettings.php
# before the line:
# require_once("$IP/extensions/Lily/Lily.php");

# You can set the variable $wgLilyTmp if you want/need to override the
# path to the Lilypond temporary files. For example:
# /images/lilytemp/
# make sure that the variable begins and ends with a slash
# the path will be a subpath of the Wiki Scriptpath $wgScriptPath

# Parameter

# res    ... Auflösung der Images in dpi, default 300
# width  ... Breite der Bilder, auch breite, w, b; default: Wert aus zugeschnittenem Bild
# height ... Höhe der Bilder, wird bei Angabe von width ignoriert
# max    ... maximale Seitenzahl, die angezeigt wird, default: 10
# incl   ... Include-Path, wird relativ zum Lilypond-Tmp Verzeichis angegeben
# sep    ... Trennzeichen zwischen den Bilder, default: <br>
# style  ... CSS-Formatierung für Bilder, auch stil https://www.w3schools.com/css/default.asp
# class  ... CSS-Klasse, auch klass/klasse

# End User Settings

use MediaWiki\MediaWikiServices;
use MediaWiki\Shell\Shell;

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

$wgExtensionCredits['parserhooks'][] = array(
'path' => __FILE__,
'name' => 'Lily3',
'version' => 0.1,
'author' => 'Manuela',
'url' => 'Extension:Lily',
'descriptionmsg' => 'lilypond-desc',
);
$wgExtensionFunctions[] = 'wfLilyExtension3';
/**
 * @param $parser Parser
 */
 function wfLilyExtension3() {
new Lilypond3();
}

class Lilypond3
{
public function __construct()
{
global $wgParser;
$wgParser->setHook('lily3', array(&$this'hookLily3'));
}

private function rdStr($length 6)
// Zufallstext generieren, Standardlänge = 6 Zeichen
{
$str "";
$characters array_merge(range('A','Z'), range('a','z'), range('0','9'));
$max count($characters) - 1;
for ($i 0$i $length$i++) {
$rand mt_rand(0$max);
$str .= $characters[$rand];
}
return $str;
}

private function mycrop ($bild$pfad ""$b ""$h "")
{

$im imagecropauto(imagecreatefrompng($pfad $bild), IMG_CROP_WHITE); // weißen Rand entfernen
unlink($pfad $bild);  // ungeschnittenes Bild löschen
imagepng($im"$pfad"cr-$bild"); // Bild im Verzeichis speichern

// Berechnung von Breite und Höhe
// die Bilder sollen im richtigen Seitenverhältnis dargestellt werden
// Breite geht vor Höhe, wenn beide Angaben vorhanden sind, wird die Höhe ignoriert
$br imagesx($im);  // Breite ermitteln
$ho imagesy($im);  // Höhe ermittelns
$sv $br $ho;  // Seitenverhältnis
$width = (empty($b) ? $br $b );
$heigh = (empty($h) ? $ho $h );

if (!empty($b))  // breite ist angegeben
{
$heigh round($width $sv);
}
elseif (!empty($h)) // Höhe ist angegeben
{
$width round($heigh $sv);
}
$size = array($width$heigh"cr-$bild");
imagedestroy($im);
return $size// Bildgröße + Name
}

public function hookLily3($code$argv$parser)
{
global $wgLilyTmp$IP$wgServer$wgScriptPath$wgUploadPath;

// temporärer Pfad als Unterverzeichnis vom Wiki-Verzeichnis
if (isset($wgLilyTmp))
$tmppath $wgLilyTmp;
else
$tmppath "/images/lilypond/";

// $width = (empty($wgLilyW) ? auto : $wgLilyW );
// Konstruktion der Bildurl für Link
$bildurl "$wgServer$wgScriptPath$tmppath";
//Verzeichnis für Lilypond Dateien auf dem Webserver
$lilypath "$IP$tmppath";

$lilyfile $this->rdStr() ;  // wir generieren einen zufälligen Namen

//Parameterauswertung

$res=300;  // Standardauflösung 300dpi
$incl="";  // Include Path
$w=""$h=""$max 10$sep="<br>"$style=""$class="";
foreach ($argv as $key => $val
{
if ($key == 'res')
$res $val;
else if ($key == 'sep')
$sep $val;
else if (($key == 'incl') or ($key == 'inc') or ($key == 'path') or ($key == 'pfad'))
$incl $val// Include Path
else if (($key == 'breite') or ($key == 'width') or ($key == 'w') or ($key == 'b'))
$w $val;  // Breite
else if (($key == 'hoehe') or ($key == 'hoch') or ($key == 'height') or ($key == 'h'))
$h $val;  // Höhe
else if (($key == 'max') or ($key == 'zahl') or ($key == 'maxzahl') or ($key == 'anzahl'))
$max $val;
else if (($key == 'style') or ($key == 'stil'))
$style $val;
else if (($key == 'class') or ($key == 'klass') or ($key == 'klasse'))
$class $val;
}
$inc = (empty($incl) ? "" "-I$lilypath$incl); // include Path

// Aufbau des Lilypond-Zeilenkommandos und Durchführung
$kommando "lilypond -l=NONE -o $lilypath$lilyfile -fpng $inc -dresolution=$res $lilypath$lilyfile;

$lilycodefile fopen("$lilypath$lilyfile.ly" "w" );
fputs $lilycodefile$code);
fclose $lilycodefile);
shell_exec($kommando);
unlink("$lilypath$lilyfile.ly");

// jetzt müssen wir auf mehrere Seiten checken 
$lilybild "$lilypath$lilyfile.png";
$html "";

if (file_exists($lilybild))
{
$im $this->mycrop("$lilyfile.png"$lilypath$w$h);
$html .= "<img src='$bildurl$im[2]' width='$im[0]' height='$im[1]' style='$style' class='$class'/>";
}
else
{
for ($i=1$i<=$max$i++)  // maximale Seitenzahl: max, zahl, maxzahl 
{
$ibild "$lilyfile-page$i.png";
if (file_exists("$lilypath$lilyfile-page$i.png"))
{
$im $this->mycrop($ibild$lilypath$w$h);
$width = (empty($wgLilyW) ? $im[0] : $wgLilyW );
$heigh = (empty($wgLilyH) ? $im[1] : $wgLilyH );
$html .= "<img src='$bildurl$im[2]' width='$im[0]' height='$im[1]' style='$style' class='$class'/>$sep"//<br>Bildbreite: $im[0] Bildhöhe: $im[1]<br>";
}
else 
{
// alle Seiten wurden verarbeitet
break;
}
}
}
return "$html";
}
}
Danke für eure Hilfe
viele Grüße
-- Manuela