Extension
Netcos Renting
Von Bernd
Warken bei Fa. Netcos AG
0. Einleitung
0.1 Vorwort
0.2 Lizenz
1. Kickstarter
1.1 Erstellung der Extension
1.2 Neue Datenbanktabelle
1.3 Frontend Plugins
1.4 Abspeichern und beenden
2. Objektmethoden für Termin
3. Zugaben
3.1 smarty
3.2 jscalendar
3.3 Mehrsprachigkeit
4. PHP-Quellcode anpassen
4.1 Datenbankzugriff
4.2 Erstes Plugin (Vermietungsverwaltung)
4.3 Zweites Plugin (vermietet)
5. HTML-Templates
5.1 Erstes Plugin (Vermietungsverwaltung)
5.2 Zweites Plugin (vermietet)
0. Einleitung
0.1 Vorwort
Dieses Dokument beschreibt die Hintergründe für
die Erstellung einer TYPO3-Extension, die Zugriff auf die Datenbank
gestattet. Dies ist eine offizielle Extension, sie ist auf typo3.org
erhältlich.
Die Extension wird vorab mit dem Kickstarter
erzeugt und dann manuell geändert. Als Beispiel wird die
Vermietung eines Apartments behandelt. Dabei werden zwei
Frontend-Plugins angelegt, eine zur Vermietungsverwaltung und eine
zum Anschauen der Buchungen für alle Benutzer.
Die Termine werden im Format yyyymmdd
gespeichert, womit sich das Datum
besser vergleichen läßt.
Zur besseren Darstellung des
Kalenderformats bei der Eingabe wird das Programm jscalender
verwendet. Um die Quellcode-Dateien etwas kleiner zu halten, wird zur
Auslagerung des HTML-Codes in HTML-Dateien die Extension smarty
angewendet.
Die Extension besitzt
Mehrsprachigkeit, bisher wurden die 2 Sprachen Englisch und Deutsch
verwendet. Im Quellcode der Extension werden die mehrsprachigen
Begriffe in den Dateien locallang*.xml gespeichert.
Dieses Dokument wurde auf
Linux entwickelt und beschreibt auch alle Pfade in Linux-typischer
Weise. Dies passt jedoch auch für Mac. Wenn Sie jedoch mit
Microsoft Windows arbeiten, müssen Sie sämtliche
Pfadangaben entsprechend anpassen. Sonst sind keine Änderungen
nötig.
0.2 Lizenz
Dieses Dokument
gehört zum TYPO3-Projekt
über die
Extension
netcos_renting.
Die aktuelle Version dieses Dokuments ist 1.0.1
vom
10. April 2008. Der Autor ist Bernd
Warken
bei
Firma netcos AG.
Alle Elemente des
Projekts (dieses Dokument und der Quellcode) stehen unter der Lizenz
GPL
(GNU General Public License) Version
3.
Der Originaltext dieser Lizenz ist erhältlich unter
http://www.gnu.org/licenses/gpl.html,
eine deutsche Übersetzung befindet sich unter
http://www.gnu.de/documents/gpl.de.html.
Copyright 2008 Bernd Warken
1. Kickstarter
Kickstarter ist eine
Typo3-Extension zur Erstellung eigener Extensions. Zunächst muss
kickstarter über
den Extension Manager installiert
werden.
1.1 Erstellung der Extension
Durch kickstarter
entsteht im Menü des Extension
Managers ein neues Feld Neue
Extension anlegen. Wir wählen
dieses Feld.
Im entstehenden Formular gibt
man zuerst den Namen im Feld Enter extension key:
an, in diesem Fall
netcos_renting.
Bestätigung mit dem Button Update....
Im Folgenden wird die Optionsliste KICKSTARTER WIZARD im
Formular bearbeitet.
Man drückt zuerst das Pluszeichen von General info.
Darin erstellt man den Title Netcos Renting.
Als Category wählt man Frontend Plugins. Man
lässt State auf Alpha. Für Dependencies
gibt man die Extensions an, die zusätzlich gebraucht werden,
also cms und smarty an.
Author hinzufügen. Den Button Update...
betätigen
Als nächstes das Pluszeichen von
Setup languages und darin die Sprache German
wählen.
Bestätigung durch Update.... Die Standardsprache der
Extension ist immer Englisch, die gewählte deutsche Sprache ist
eine Zusatzsprache.
1.2 Neue Datenbanktabelle
Wir werden die Buchungen in einer neuen
Datenbanktabelle speichern. Dazu wird das Pluszeichen von New
Database Tables betätigt. Als Tablename geben
wir an: fromto.
Mit Hilfe dieses Namens wird eine neue Tabelle innerhalb der
Datenbank für die TYPO3-Installation angelegt. Der richtige
Tabellenname lautet: tx_netcosrenting_fromto.
Als Title of the
table geben
wir an rented
und
auf Deutsch vermietet.
Nun werden noch die Felder angegeben,
die in der Tabelle verwendet werden. Ein Buchungstermin hat zwei
Felder zur Speicherung der Zeiträume: from_date und
to_date.
In NEW FIELD tragen
wir daher erst from_date
als
Field name ein,
mit Field title
From in
English und Von
in
German. Der Field
type ist
String input.
Field width
und
Max. characters
sind
jeweils 8. Update....
In dem neu entstehenden NEW FIELD
tragen wir dann to_date
als
Field name ein,
mit Field title
To in
English und Bis
in
German. Der Field
type ist
wieder String
input.
Field width
und
Max. characters
sind
wieder jeweils 8. Update....
1.3 Frontend Plugins
Nun das Pluszeichen von Frontend Plugins zweimal
betätigen. Dadurch entstehen zwei neue Felder zur Erstellung von
Plugins, das eine für die Vermietungsverwaltung und das andere
zum Anschauen der Buchungen.
Im ersten dieser Pluginformulare wird auf Englisch der title:
Renting Administration angegeben
und in Deutsch Vermietungsverwaltung. Auswählen des Buttons Add to 'Insert Plugin' list in Content Elements
und darin Add icon to ‘New Content Element’ wizard. Update.
Im anderen Pluginformular wird auf Englisch der title:
rented angegeben und in Deutsch vermietet.
Anklicken Add to 'Insert Plugin' list in Content Elements und darin Add icon to ‘New
Content Element’ wizard. Update.
1.4 Abspeichern und beenden
Die Eingabe ist jetzt abgeschlossen.
Daher den Feldbutton View result wählen. Dort auf WRITE
klicken. Die Extension wird dann auf typo3conf/ext/netcos_renting/
abgespeichert. Diese Extension wird nun im Menü-Feld Install
extensions des Extension Managers angezeigt
und kann durch Klicken des Pluszeichens installiert werden.
Die
Quellcode-Dateien der Extension können angesehen werden durch
Klicken auf den Extension-Namen im Extension
Manager.
Im entstehenden Menü muss Edit
files ausgesucht
werden. Dies stellt die Verzeichnisstruktur des Quellcodes der
Extension dar. Da zwei Plugins eingerichtet
wurden, enhält der Extension-Quellcode auch zwei
Unterverzeichnisse pi1
und pi2
mit
dem Quellcode für die Plugins.
2. Objektmethoden für Termine
Die Termine für die
Buchungen werden in der Datenbank im Format yyyymmdd
abgespeichert. Der 23.
Januar 2008 würde dann also als Wert 20080123
gespeichert. Bei der
Erstellung der Extension werden wir mit diesem Format in PHP rechnen.
Zum Umwandeln und Handhaben
der verschiedenen Datumsformate ist es sinnvoll, eine PHP-Klasse zu
erstellen. Wir nennen diese Klasse Termin.
Den Code für diese Klasse speichern wir in der Datei
class_termin.php
im
Quellcode-Verzeichnis der Extension.
Da sich die Sprachmeldungen
in dieser Datei nicht so ohne weiteres erstellen lassen, werden alle
Fehlermeldungen in Englisch ausgegeben. Für den normalen Betrieb
reicht das. Die noch vorhandenen deutschen Strings sind nicht mehr
nötig, z.B. $Monatsnamen,
bleiben aber vorläufig noch in der Datei.
Da diese Datei sehr lang ist,
haben wir sie in viele Teile zerlegt. Wenn Sie die gesamte Datei
haben wollen, müssen Sie alle diese Abschnitte in dieser Sektion
zusammensetzen oder schauen Sie im Quellcode der Extension nach.
Start und Lizenz:
|
<?php
/***************************************************************
* Copyright notice
*
* (c) 2007,2008 Bernd Warken <be.warken@netcos.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
****************************************************************/
class Termin {
|
Private Variablen:
|
private $value;
private $max;
private $error = '';
private $timestamp = 0;
static private $max_Tage =
array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
static private $Monatsnamen =
array(0, 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember');
static private $Monatsnummern = array(
'Januar' => 1, 'januar' =>
1, 'Jan' => 1, 'Jan' => 1, 'JAN' => 1,
'Februar' => 2, 'februar' =>
2, 'Feb' => 2, 'feb' => 2, 'FEB' => 2,
'März' => 3, 'märz'
=> 3, 'Maerz' => 3, 'maerz' => 3,
'Mär' => 3, 'mär' =>
3, 'MÄR' => 3, 'Mae' => 3, 'mae' => 3, 'MAE' =>
3,
'April' => 4, 'april' => 4,
'Apr' => 4, 'APR' => 4, 'apr' => 4,
'Mai' => 5, 'mai' => 5,
'Juni' => 6, 'juni' => 6,
'Jun' => 6, 'jun' => 6, 'JUN' => 6,
'Juli' => 7, 'juli' => 7,
'jul' => 7, 'Jul' => 7, 'JUL' => 7,
'August' => 8, 'august' =>
8,'Aug' => 8, 'aug' => 8,'AUG' => 8,
'September' => 9, 'september'
=> 9, 'Sep' => 9, 'sep' => 9, 'SEP' => 9,
'Oktober' => 10, 'oktober' =>
10, 'Okt' => 10, 'okt' => 10, 'OKT' => 10,
'November' => 11, 'november' =>
11, 'Nov' => 11, 'nov' => 11, 'NOV' => 11,
'Dezember' => 12, 'dezember' =>
12, 'Dez' => 12, 'dez' => 12, 'DEZ' => 12
);
static private $char2int =
array('0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' =>
4, '5' => 5,
'6' => 6, '7' => 7, '8' => 8, '9' => 9);
|
Konstruktion eines
Termin-Objekts aus einem Datumstring:
|
public function __construct($value) {
$str = trim((string)$value);
$this->value = '';
if ($str == '') {
$this->append_error('empty Termin data.');
return(FALSE);
}
if ($this->_is_Termin($str)) {
$this->value = $str;
$m = $this->Monat();
if ($m <= 0 || $m > 12) {
$this->append_error('wrong month number: '.$m.'.');
$this->value = '';
return(FALSE);
}
$t = $this->Tag();
$max = $this->max_Tage_des_Monats();
if ($t <= 0 || $t > $max) {
$this->append_error('wrong number of days: '.$t.',
maximal number of days of the month is '.$max.'.');
$this->value = '';
return(FALSE);
}
$this->max = $max;
return(TRUE);
}
$len = strlen($str);
$a = explode("/", $str);
$c = count($a);
$english = 'yes';
switch($c) {
case 3:
$j = $a[0];
$m = $a[1];
$t = $a[2];
break;
case 2:
$j = date('Y');
$m = $a[0];
$t = $a[1];
break;
default:
$english = 'no';
break;
}
if ($english == 'yes') {
$s = '';
if ($this->_is_int($j)) {
$j = (int)$j;
if ($j < 100) $j += 2000;
if ($j < 2000 || $j >= 3000) {
$this->append_error('Wrong year number: '.$j.'.');
return(FALSE);
}
$s = (string)$j;
}
if (strlen($s) != 4) {
$this->append_error('wrong year description: '.$j.'.');
return(FALSE);
}
if ($this->_is_int($m)) {
$m = (int)$m;
if ($m > 0 && $m < 10) {
$s .= '0'.(string)$m;
} elseif ($m <= 12) {
$s .= (string)$m;
} else {
$this->append_error('wrong month number: '.$m.'.');
return(FALSE);
}
} else {
$this->append_error('month must be a number: '.$m.'.');
return(FALSE);
}
if ($this->_is_int($t)) {
$t = (int)$t;
$max = $this->max_Tage_des_Monats($m, $j);
if ($t <= 0 || $t > $max) {
$this->append_error('wrong
number of days: '.$t.', maximal number of days of the month is
'.$max.'.');
return(FALSE);
}
if ($t > 0 && $t < 10) {
$s .= '0'.(string)$t;
} else {
$s .= (string)$t;
}
} else {
$this->append_error('day must
be a number: '.$t.'.');
return(FALSE);
}
$this->value = $s;
return(TRUE);
}
$i = 0;
$s = '';
while ( $this->_is_int(
$str{$i} ) && $i < $len ) {
$s .= $str{$i};
$i++;
}
if ($s) {
$t = (int)$s;
} else {
$this->append_error('no day
number.');
return(FALSE);
}
while ($str{$i} == ' ' && $i < $len) $i++;
while ($str{$i} == '.' && $i < $len) $i++;
while ($str{$i} == ' ' && $i < $len) $i++;
if ($i == $len) {
$m = date('n');
$j = date('Y');
} else {
$s = '';
while ($this->_is_int($str{$i}) && $i < $len) {
$s .= $str{$i};
$i++;
}
if ($s) {
$m = (int)$s;
if ($m <=0 || $m > 12) {
$this->append_error('wrong month number:'.$m.'.');
return(FALSE);
}
} else {
while ($str{$i} != ' ' &&
$str{$i} != '.' && $i < $len) {
$s .= $str{$i};
$i++;
}
if (!$s) {
$this->append_error('no
information for month.');
return(FALSE);
}
if (self::$Monatsnummern[$s]) {
$m = self::$Monatsnummern[$s];
} else {
$this->append_error('wrong
month name: '.$s.'.');
return(FALSE);
}
}
while ($str{$i} == ' ' &&
$i < $len) $i++;
while ($str{$i} == '.' &&
$i < $len) $i++;
while ($str{$i} == ' ' &&
$i < $len) $i++;
if ($i == $len) {
$j = date('Y');
} else {
$s = '';
while ( $this->_is_int(
$str{$i} ) && $i < $len ) {
$s .= $str{$i};
$i++;
}
if ($s) {
$j = (int)$s;
if ($j < 100) $j += 2000;
if ($j < 2000 || $j >= 3000) {
$this->append_error('wrong year
number: '.$j.'.');
return(FALSE);
}
} else {
$this->append_error('wrong year
description: '.$s.'.');
return(FALSE);
}
}
}
$max = $this->max_Tage_des_Monats($m, $j);
if ($t <= 0 || $t > $max) {
$this->append_error('wrong
number of days: '.$t.', maximal number of days of the month is
'.$max.'.');
return(FALSE);
}
$this->max = $max;
$s = (string)$j;
if ($m <= 9) $s .= '0';
$s .= (string)$m;
if ($t <= 9) $s .= '0';
$s .= (string)$t;
$this->value = $s;
return(TRUE);
}
|
Übersetzung von Termin
zu String:
|
public function __toString() {
return($this->string());
}
|
Teste Jahreszahl auf
Schaltjahr:
|
private function _is_Schaltjahr($jahr){
if(($jahr % 400) == 0 || (($jahr %
4) == 0 && ($jahr % 100) != 0))
return TRUE;
else
return FALSE;
}
|
Teste, ob String als Termin
taugt:
|
private function _is_Termin($str) {
$s = (string)(int)$str;
$len = strlen($s);
if ($len != 8) return(FALSE);
if (!$this->_is_int($str))
return(FALSE);
if ($str{0} != '2') {
$this->append_error('wrong
year.');
return(FALSE);
}
return(TRUE);
}
|
Weitere Methoden:
|
private function _char2int($c) {
$n = self::$char2int[$c];
if (isset($n)) return($n); else return(-1);
}
private function _is_int($str) {
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
if ($this->_char2int($str{$i}) < 0) return(FALSE);
}
return(TRUE);
}
public function is_false() {
return($this->string() == '');
}
public function is_true() {
return(!$this->is_false());
}
public function int() {
return (int)$this->value;
}
public function string() {
return (string)$this->value;
}
private function append_error($str) {
if ($this->error) $this->error
.= ' '.$str; else $this->error = $str;
return($this->error);
}
public function get_error() {
return($this->error);
}
|
Ausgabe des aktuellen Termins
als Datumstring:
|
public function Datum() {
if ($this->is_false()) return('');
$str = $this->string();
$s = '';
for ($i = 6; $i <= 7 ; $i++) $s .= $str{$i};
$s .= '.';
for ($i = 4; $i <= 5 ; $i++) $s .= $str{$i};
$s .= '.';
for ($i = 0; $i <= 3 ; $i++) $s .= $str{$i};
return($s);
}
public function date_en() {
if ($this->is_false()) return('');
$str = $this->string();
$s = '';
for ($i = 0; $i <= 3 ; $i++) $s .= $str{$i};
$s .= '/';
for ($i = 4; $i <= 5 ; $i++) $s .= $str{$i};
$s .= '/';
for ($i = 6; $i <= 7 ; $i++) $s .= $str{$i};
return($s);
}
|
Ersetze Tag des aktuellen
Termins durch 01:
|
public function erster_des_Monats() {
if ($this->is_false()) return('');
$str = $this->string();
$str[6] = 0;
$str[7] = 1;
return(new Termin($str));
}
|
Anzahl der Tage innerhalb des
aktuellen Monats:
|
public function max_Tage_des_Monats() {
if (func_num_args() == 2) {
$m = func_get_arg(0);
$j = func_get_arg(1);
} else {
$m = $this->Monat();
$j = $this->Jahr();
}
if ($m == 2 &&
$this->_is_Schaltjahr($j)) return(29);
return(self::$max_Tage{$m});
}
|
Aktueller Tag als Zahl:
|
public function Tag() {
if ($this->is_false())
return(0);
$str = $this->string();
$s = $str{6}.$str{7};
return((int)$s);
}
|
Aktueller Monat als Zahl:
|
public function Monat() {
if ($this->is_false())
return(0);
$str = $this->string();
$s = $str{4}.$str{5};
return((int)$s);
}
|
Aktuelles Jahr als Zahl:
|
public function Jahr() {
if ($this->is_false())
return(0);
$str = $this->string();
$s = $str{0}.$str{1}.$str{2}.$str{3};
return((int)$s);
}
|
Name des aktuellen Monats:
|
public function Monatsname() {
if ($this->is_false())
return(0);
$n = $this->Monat();
if ($n <= 0 || $n > 12)
return('');
return(self::$Monatsnamen[$n]);
}
|
Setze Variable timestamp
aus dem aktuellen Datum und
gib den Variablenwert zurück:
|
public function timestamp() {
if ($this->timestamp == 0)
$this->timestamp = strtotime($this->Datum());
return($this->timestamp);
}
|
Ausgabe des aktuellen
Wochentags als ganzes Wort:
|
public function get_Wochentag() {
return(strftime('%A',
$this->timestamp()));
}
|
Ausgabe der Abkürzung
des aktuellen Wochentags mit 2 Buchstaben:
|
public function get_Wochentag_Abk() {
return(strftime('%a',
$this->timestamp()));
}
|
Aktueller Wochentag als Zahl,
1=Montag, 7=Sonntag:
|
public function get_Wochentag_Zahl() {
return(strftime('%u', $this->timestamp()));
}
|
Aktuelle Woche des Jahres als
Zahlenwert (z.B. 26), mögliche Werte sind 00 bis 53, beginnend
mit dem ersten Montag der ersten Woche (also 1 als letzte Woche des
Vorjahres):
|
public function get_Kalenderwoche() {
return(strftime('%W', $this->timestamp()));
}
|
Strftime angewandt auf
aktuellen Termin:
|
public function strftime($str) {
return(strftime($str, $this->timestamp()));
}
|
Ende der Datei:
3. Zugaben
3.1 smarty
Smarty ist
eine TYPO3-Extension. Sie muss also zuerst installiert werden.
Sie wird in beiden Plugins
der erstellten Extension ausgiebig verwendet. Es gibt einige wenige
Regeln, die bei der Verwendung beachtet werden müssen. Wir
benutzen smarty,
um aus PHP-Code Teile in Templates auszulagern. Diese Templates sind
HTML-Codes, die zusätzlich spezielle Variablen verwenden; diese
funktionieren einfach als Abkürzungen, die vom PHP-Code gesetzt
werden können.
Als erstes muss die Dateien
der Extension smarty eingebettet
werden. Dies geschieht in der Datei
pi1/class.tx_netcosrenting_pi1.php:
|
require_once(t3lib_extMgm::extPath('smarty').'class.tx_smarty.php');
require_once(t3lib_extMgm::extPath('smarty').'Smarty/libs/Smarty.class.php');
|
Im PHP-Code wird erst einmal
eine lokale Instanz der Klasse Smarty
erstellt.
Wir nennen diese Instanz auch smarty.
|
$this->smarty = new Smarty;
|
Dann
müssen wir festlegen, wo die smarty-Templates
zu finden sind. Dieses Verzeichnis ist das Unterverzeichnis tmpl
im
Extension-Verzeichnis, das wir mit dem Argument template_dir
festlegen.
Außerdem wird tmpl_c
intern
genutzt; wir legen es fest mit dem Argument compile_dir.
In beiden Konfigurationen wird das Extension-Verzeichnis durch die
PHP-Konstruktion t3lib_extMgm::extPath($this->extKey)
ermittelt.
|
$this->smarty->compile_dir = t3lib_extMgm::extPath($this->extKey).'tmpl_c';
$this->smarty->template_dir = t3lib_extMgm::extPath($this->extKey).'tmpl';
|
Als
nächstes wird festgelegt, wie die Abkürzungen in den
HTML-Templates erkannt werden können.
|
$this->smarty->left_delimiter = '{..';
$this->smarty->right_delimiter = '..}';
|
Hier ist das Format der
Abkürzungen also {..$WERT..},
wobei in diesem Beispiel WERT
in
PHP gesetzt werden kann. Das Setzen dieser Abkürzungsvariablen
in PHP geschieht durch den Befehl assign.
|
$this->smarty->assign('WERT', 1234);
|
Alle
Abkürzungen werden innerhalb des PHP-Skripts gesetzt, meist
durch Ergebnisse aus einem form-Tag
(mit POST oder GET).
Das
smarty-Template wird aufgerufen durch
|
$content = $this->smarty->fetch($this->smarty->template_dir.'/Datei.tmpl');
return $this->pi_wrapInBaseClass($content);
|
Dies
ist schon alles.
3.2 jscalendar
Jscalendar ermöglicht die Verwendung von komfortablen Kalendern in eigenen Extensions.
Es ist als Extension netcos_jscalendar erhältlich. Nach der Installation ist der Quellcode
positioniert in /typo3conf/ext/netcos_jscalendar/jscalendar/. Dieses Verzeichnis ist relativ
zur Domain-URL, so dass das Root-Verzeichnis / das Hauptverzeichnis der TYPO3-Installation ist.
Man erhält dieses Root-Verzeichnis, wenn man im TYPO3-Code eine Domain anlegt.
Dieses Programm ist in
JavaScript geschrieben und erlaubt die Darstellung komfortabler
Kalender bei Datumseingaben. Um es zu benutzen, muss es durch
script-Tags
im HTML-Code eingelesen werden.
Im
Header einer HTML-smarty-Datei
wird folgender Code angelegt:
|
<style type="text/css">@import
url(/typo3conf/ext/netcos_jscalendar/jscalendar/calendar-green.css);</style>
<script type="text/javascript"
src="/typo3conf/ext/netcos_jscalendar/jscalendar/calendar.js"></script>
<script type="text/javascript"
src="/typo3conf/ext/netcos_jscalendar/jscalendar/calendar-setup.js"></script>
<script type="text/javascript"
src="/typo3conf/ext/netcos_jscalendar/jscalendar/lang/calendar-en.js"></script>
|
Darin wird als erstes eine CSS-Datei eingebettet und
dann werden 3 Source-Dateien des Kalendersystems eingelesen. Dabei
ist die Konfigurationsdatei für die englische Sprache
lang/calendar-en.js unbedingt
nötig, auch wenn mit anderen Sprachen gearbeitet wird.
Wenn die deutsche
Sprache aktiv ist, muss auch das Skript lang/calendar-de.js
aufgerufen werden:
|
<script type="text/javascript" src="/typo3conf/ext/netcos_jscalendar/jscalendar/lang/calendar-de.js"></script>
|
Da wir diesen
Einbettungscode in jede Template-Datei aufnehmen müssten und der
Sprachtest innerhalb von HTML nicht möglich ist, haben wir dies
durch eine smarty-Variable
übernommen, die in der Haupt-Klassen-Datei jedes Plugins
definiert wird. Kapitel 4 gibt die Details hierzu.
Im body-Bereich der
Template-Datei wird der Kalender innerhalb einer Input-Form
aufgerufen, z.B. durch folgenden Code:
<form method="post">
<input type="text" id="data_datum" name="data_datum" />
<button id="trigger_datum">Datum</button>
<script type="text/javascript">
Calendar.setup(
{
inputField : "data_Datum", // ID of the input field
ifFormat : "%d.%m.%Y", // the date format
button : "trigger_datum" // ID of the button
}
);
</script>
<input type="submit" name="anlegen" value="anlegen" />
</form>
|
Dies sind alle Strukturen,
die bei jscalendar zu beachten sind.
3.3 Mehrsprachigkeit
TYPO3 kann mehrere Sprachen
verwenden. Die Begriffe für die unterschiedlichen Sprachen
werden in den locallang*.xml-Dateien definiert. Im
Hauptverzeichnis der Extension gibt es die Dateien locallang.xml
und locallang-db.xml für die allgemeinen Definitionen der
Extension, sodann gibt es in jedem Plugin-Verzeichnis eine Datei
locallang.xml, die für das jeweilige Plugin verwendet
wird.
Innerhalb der Plugins muss
die Mehrsprachigkeit durch den Befehl pi_loadLL aktiviert
werden, die Begriffe werden durch den Befehl pi_getLL
abgefragt und durch den Wert für die jeweilige Sprache
dargestellt.
locallang.xml:
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
<meta type="array">
<type>module</type>
<description>Language labels for extension 'netcos_renting'</description>
</meta>
<data type="array">
<languageKey index="default" type="array">
<label index="pi1_title">Renting Administration</label>
<label index="pi2_title">Rented</label>
</languageKey>
<languageKey index="de" type="array">
<label index="pi1_title">Vermietungsverwaltung</label>
<label index="pi2_title">vermietet</label>
</languageKey>
</data>
</T3locallang>
|
Locallang-db.xml
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
<meta type="array">
<type>database</type>
<description>Language labels for database tables/fields belonging to extension 'netcos_renting'</description>
</meta>
<data type="array">
<languageKey index="default" type="array">
<label index="tx_netcosrenting_fromto">Rented</label>
<label index="tx_netcosrenting_fromto.from">From</label>
<label index="tx_netcosrenting_fromto.to">To</label>
<label index="tt_content.list_type_pi1">Renting Administration</label>
<label index="tt_content.list_type_pi2">Rented</label>
</languageKey>
<languageKey index="de" type="array">
<label index="tx_netcosrenting_fromto">vermietet</label>
<label index="tx_netcosrenting_fromto.from">Von</label>
<label index="tx_netcosrenting_fromto.to">Bis</label>
<label index="tt_content.list_type_pi1">Vermietungsverwaltung</label>
<label index="tt_content.list_type_pi2">vermietet</label>
</languageKey>
</data>
</T3locallang>
|
pi1/locallang.xml:
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
<meta type="array">
<type>module</type>
<description>Language labels for plugin "tx_netcosrenting_pi1"</description>
</meta>
<data type="array">
<languageKey index="default" type="array">
<label index="actual">actual</label>
<label index="apply">apply</label>
<label index="back">Back</label>
<label index="cancel">cancel</label>
<label index="change1">change</label>
<label index="change2">change</label>
<label index="delete">delete</label>
<label index="existing">existing</label>
<label index="from">from</label>
<label index="language">en</label>
<label index="more">more</label>
<label index="new">new</label>
<label index="to">to</label>
<label index="year">year</label>
<label index="administration_bookings_actual">Bookings since today</label>
<label index="administration_bookings_year">Bookings of Year</label>
<label index="administration_date_format">Date format: yyyy/mm/dd</label>
<label index="administration_header">Renting</label>
<label index="administration_new">New Entry</label>
<label index="administration_none">No entries available.</label>
<label index="administration_years">Bookings of whole Years</label>
<label index="calendar_ifformat">%Y/%m/%d</label>
<label index="exists_header">The entry was not generated because it exists already.</label>
<label index="overlap_header">Overlap of Entries</label>
<label index="pi1_comes_after">comes after</label>
<label index="pi1_erroneous">is erroneous</label>
<label index="pi1_has_an_error">has an error</label>
<label index="pi1_has_error">has error</label>
<label index="to_be_changed_header">Change Entry</label>
<label index="to_be_deleted_header">The following entry should be deleted</label>
<label index="was_created_header">The entry was created.</label>
<label index="was_deleted_header">The entry was deleted.</label>
<label index="wrong_entry_header">Wrong entry</label>
</languageKey>
<languageKey index="de" type="array">
<label index="actual">aktuell</label>
<label index="apply">anlegen</label>
<label index="back">Zurück</label>
<label index="cancel">Abbrechen</label>
<label index="change1">ändern</label>
<label index="change2">wechseln</label>
<label index="delete">löschen</label>
<label index="existing">bestehend</label>
<label index="from">Von</label>
<label index="language">de</label>
<label index="more">Weiter</label>
<label index="new">neu</label>
<label index="to">Bis</label>
<label index="year">Jahr</label>
<label index="administration_bookings_actual">Buchungen ab heute</label>
<label index="administration_bookings_year">Buchungen Jahr</label>
<label index="administration_date_format">Datumsformat: tt.mm.jjjj</label>
<label index="administration_header">Vermietung</label>
<label index="administration_new">Neuer Eintrag</label>
<label index="administration_none">Keine Einträge vorhanden.</label>
<label index="administration_years">Buchungen von ganzen Jahren</label>
<label index="calendar_ifformat">%d.%m.%Y</label>
<label index="exists_header">Der Datensatz wurde nicht erstellt, da er bereits existiert.</label>
<label index="overlap_header">Einträge überschneiden sich</label>
<label index="pi1_comes_after">kommt nach</label>
<label index="pi1_erroneous">ist fehlerhaft</label>
<label index="pi1_has_an_error">hat einen Fehler</label>
<label index="pi1_has_error">hat den Fehler</label>
<label index="to_be_changed_header">Eintrag ändern</label>
<label index="to_be_deleted_header">Folgender Eintrag soll gelöscht werden</label>
<label index="was_created_header">Der Datensatz wurde erstellt.</label>
<label index="was_deleted_header">Der Datensatz wurde gelöscht.</label>
<label index="wrong_entry_header">Falscher Eintrag</label>
</languageKey>
</data>
</T3locallang>
|
pi2/locallang.xml:
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
<meta type="array">
<type>module</type>
<description>Language labels for plugin "tx_netcosrenting_pi2"</description>
</meta>
<data type="array">
<languageKey index="default" type="array">
<label index="listFieldHeader_from">From</label>
<label index="listFieldHeader_to">To</label>
<label index="list_mode_1">Mode 1</label>
<label index="list_mode_2">Mode 2</label>
<label index="list_mode_3">Mode 3</label>
<label index="back">Back</label>
<label index="pi_list_browseresults_prev">< Previous</label>
<label index="pi_list_browseresults_page">Page</label>
<label index="pi_list_browseresults_next">Next ></label>
<label index="pi_list_browseresults_displays">Displaying results ###SPAN_BEGIN###%s to %s</span> out of ###SPAN_BEGIN###%s</span></label>
<label index="pi_list_searchBox_search">Search</label>
<label index="booked">booked</label>
<label index="free">free</label>
<label index="year">year</label>
<label index="previous_month">Previous Month</label>
<label index="actual_month">Actual Month</label>
<label index="next_month">Next Month</label>
<label index="january">January</label>
<label index="february">February</label>
<label index="march">March</label>
<label index="april">April</label>
<label index="may">May</label>
<label index="june">June</label>
<label index="july">July</label>
<label index="august">August</label>
<label index="september">September</label>
<label index="october">October</label>
<label index="november">November</label>
<label index="december">December</label>
<label index="calendar_week">calendar week</label>
<label index="monday">Monday</label>
<label index="tuesday">Tuesday</label>
<label index="wednesday">Wednesday</label>
<label index="thursday">Thursday</label>
<label index="friday">Friday</label>
<label index="saturday">Saturday</label>
<label index="sunday">Sunday</label>
<label index="booked_change">change month</label>
<label index="booked_future">Choose future month</label>
<label index="booked_header">Renting</label>
<label index="error_back">back to the actual month</label>
<label index="error_header">No Access to Month</label>
<label index="error_text">The oldest possible month is the previous month.
No limits for the future.</label>
</languageKey>
<languageKey index="de" type="array">
<label index="booked">gebucht</label>
<label index="free">frei</label>
<label index="year">Jahr</label>
<label index="previous_month">Voriger Monat</label>
<label index="actual_month">Aktueller Monat</label>
<label index="next_month">Nächster Monat</label>
<label index="january">Januar</label>
<label index="february">Februar</label>
<label index="march">März</label>
<label index="april">April</label>
<label index="may">Mai</label>
<label index="june">Juni</label>
<label index="july">Juli</label>
<label index="august">August</label>
<label index="september">September</label>
<label index="october">Oktober</label>
<label index="november">November</label>
<label index="december">Dezember</label>
<label index="calendar_week">Kalenderwoche</label>
<label index="monday">Montag</label>
<label index="tuesday">Dienstag</label>
<label index="wednesday">Mittwoch</label>
<label index="thursday">Donnerstag</label>
<label index="friday">Freitag</label>
<label index="saturday">Samstag</label>
<label index="sunday">Sonntag</label>
<label index="booked_change">Monat wechseln</label>
<label index="booked_future">Zukünftigen Monat wählen:</label>
<label index="booked_header">Vermietung</label>
<label index="error_back">Zurück zum aktuellen Monat</label>
<label index="error_header">Kein Zugriff auf den Monat</label>
<label index="error_text">In die Vergangenheit kann
höchstens auf den Vormonat zugegriffen werden. Für die Zukunft bestehen keine
Einschränkungen.</label>
</languageKey>
</data>
</T3locallang>
|
4. PHP-Quellcode anpassen
Die Hauptänderungen geschehen in jedem Plugin-Verzeichnis
typo3conf/ext/netcos_renting/pi? in der Datei
class.tx_netcosrenting_pi?.php.
Dabei steht ? für
1 oder 2,
da wir zwei Plugins eingerichtet haben. Diese Dateien bilden die
Erweiterungsklassen für tslib_pibase.
Die
Methode main
darin
ruft den ganzen Darstellungsprozess auf.
4.1 Datenbankzugriff
Normalerweise greift TYPO3 auf die Datenbank MySQL zu.
Doch es wurde eine allgemeine Schnittstelle kreiert, die auf
beliebige Datenbanken zugreifen kann. Dazu wurden neue Funktionen
geschaffen, die die bekannten MySQL-Befehle
von PHP ersetzen.
Wir verwenden diese
Schnittstelle, obwohl wir z.Z. nur auf MySQL zugreifen.
Dazu muss die TYPO3-Extension
dbal installiert
werden. Dokumentation zu den zugehörigen Datenbankfunktionen
befindet sich in der TYPO3
Core
Documentation,
Kapitel 1.4.
Wir verwenden folgende Variable:
|
$table_name = 'tx_netcosrenting_fromto';
|
In den Plugins werden folgende
Datenbankzugriffe genutzt:
|
$where = 'uid='.$uid;
$GLOBALS['TYPO3_DB']->exec_DELETEquery($table_name, $where);
|
Dies löscht aus der Tabelle
$table_name den Eintrag mit der uid $uid.
|
$query = 'SELECT uid FROM '.$table_name .
' WHERE from_date='.$f->string().'AND to_date='.$t->string();
$res = $GLOBALS['TYPO3_DB']->sql_query($query);
if ($GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
...
} else {
$fields_values = array('from_date'=> $f->string(), 'to_date' => $t->string());
$GLOBALS['TYPO3_DB']->exec_INSERTquery($table_name, $fields_values);
...
}
|
Dies ist ein SELECT-Request, der
durch sql_query() aufgerufen
wird. Das Ergebnis $res
wird
durch sql_fetch_assoc()
in
assoziative Arrays aufgespalten. Falls kein passender Datensatz
existiert, wird ein neuer Datensatz aus den Werten erzeugt und in der
Datentabelle abgespeichert durch exec_INSERTquery().
4.2 Erstes Plugin (Vermietungsverwaltung)
In dieser Sektion stellen wir die Datei
typo3conf/ext/netcos_renting/pi1/class.tx_netcosrenting_pi1.php
vor. Da sie sehr lang ist, haben wir sie in viele Teile aufgeteilt,
die alle zusammengesetzt werden müssen. Sie können
natürlich die gesamte Datei aus dem Quellcode der Extension
herausziehen.
Die Zeilenumbrüche müssen
jeweils entfernt werden.
Start und Lizenz:
|
<?php
/***************************************************************
* Copyright notice
*
* (c) 2007,2008 Bernd Warken <be.warken@netcos.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
|
Einbettung von PHP-Dateien:
|
require_once(PATH_tslib.'class.tslib_pibase.php');
require_once('class_termin.php');
require_once(t3lib_extMgm::extPath('smarty').'class.tx_smarty.php');
require_once(t3lib_extMgm::extPath('smarty').'Smarty/libs/Smarty.class.php');
|
Dokumentation von kickstarter:
|
/**
* Plugin 'own Booking Administration' for the 'eigene_buchungen' extension.
*
* @author Bernd Warken <be.warken@netcos.de>
* @package TYPO3
* @subpackage tx_eigenebuchungen
*/
|
Klassendefiniton und Variabeln
von kickstarter:
|
class tx_netcosrenting_pi1 extends tslib_pibase {
var $prefixId = 'tx_netcosrenting_pi1'; // Same as class name
var $scriptRelPath = 'pi1/class.tx_netcosrenting_pi1.php';
// Path to this script relative to the extension dir.
var $extKey = 'netcos_renting'; // The extension key.
|
Stellt sicher, dass die Daten von
HTML-Forms übertragen werden (POST und GET):
|
var $pi_checkCHash = true;
|
Dokumentation von kickstarter
für function main:
|
/**
* Main method of your PlugIn
*
* @param string $content: The content of the PlugIn
* @param array $conf: The PlugIn Configuration
* @return The content that should be displayed on the website
*/
function main($content,$conf) {
|
Ab jetzt befinden wir uns innerhalb der
Funktion main.
Speichere die Datensicherung des vorigen Durchgangs in $POST:
|
global $_POST, $LANG;
$POST = t3lib_div::_POST();
$_POST = array();
|
Aktiviere die Mehrsprachigkeit:
Allgemeine Konfiguration für smarty:
|
$this->smarty = new Smarty;
$this->smarty->compile_dir = t3lib_extMgm::extPath($this->extKey).'tmpl_c';
$this->smarty->template_dir = t3lib_extMgm::extPath($this->extKey).'tmpl';
$this->smarty->left_delimiter = '{..';
$this->smarty->right_delimiter = '..}';
|
Das legt fest, dass man in den
HTML-Template-Dateien von smarty Variablen durch {..$var..}
benutzen kann. Der Wert für diese Variablen wird in PHP mit
$this->smarty->assign eingestellt.
Die verwendeten smarty-HTML-Template-Dateien:
|
$this->templates['administration'] = 'tmpl/pi1/administration.tmpl';
$this->templates['wrong_entry'] = 'tmpl/pi1/wrong_entry.tmpl';
$this->templates['overlap'] = 'tmpl/pi1/overlap.tmpl';
$this->templates['to_be_changed'] = 'tmpl/pi1/to_be_changed.tmpl';
$this->templates['to_be_deleted'] = 'tmpl/pi1/to_be_deleted.tmpl';
$this->templates['exists'] = 'tmpl/pi1/exists.tmpl';
$this->templates['was_created'] = 'tmpl/pi1/was_created.tmpl';
$this->templates['was_deleted'] = 'tmpl/pi1/was_deleted.tmpl';
|
Smarty-Abkürzung:
|
$this->smarty->assign('DIR_JSCALENDAR',
'/typo3conf/ext/'.$this->extKey.'/jscalendar-1.0/');
|
Name der MySQL-Tabelle des Plugins:
|
$table_name = 'tx_netcosrenting_fromto';
|
Heutiges Datum:
|
$heutetermin = new
Termin((string)date('d').'.'.(string)date('n').'.'.(string)date('Y'));
|
Ersetze im heutigen Termin den Tag durch 01:
|
$erster_des_Monats = $heutetermin->erster_des_Monats();
|
Smarty-Variablen:
|
$this->smarty->assign('ACTUAL', $this->pi_getLL('actual'));
$this->smarty->assign('APPLY', $this->pi_getLL('apply'));
$this->smarty->assign('CANCEL', $this->pi_getLL('cancel'));
$this->smarty->assign('CHANGE1', $this->pi_getLL('change1'));
$this->smarty->assign('CHANGE2', $this->pi_getLL('change2'));
$this->smarty->assign('DELETE', $this->pi_getLL('delete'));
$this->smarty->assign('EXISTING', $this->pi_getLL('existing'));
$this->smarty->assign('FROM', $this->pi_getLL('from'));
$this->smarty->assign('MORE', $this->pi_getLL('more'));
$this->smarty->assign('NEW', $this->pi_getLL('new'));
$this->smarty->assign('TO', $this->pi_getLL('to'));
$this->smarty->assign('YEAR', $this->pi_getLL('year'));
$this->smarty->assign('ADMINISTRATION_DATE_FORMAT', $this->pi_getLL('administration_date_format'));
$this->smarty->assign('ADMINISTRATION_HEADER', $this->pi_getLL('administration_header'));
$this->smarty->assign('ADMINISTRATION_NEW', $this->pi_getLL('administration_new'));
$this->smarty->assign('ADMINISTRATION_YEARS', $this->pi_getLL('administration_years'));
$this->smarty->assign('CALENDAR_IFFORMAT', $this->pi_getLL('calendar_ifformat'));
$this->smarty->assign('EXISTS_HEADER', $this->pi_getLL('exists_header'));
$this->smarty->assign('OVERLAP_HEADER', $this->pi_getLL('overlap_header'));
$this->smarty->assign('TO_BE_CHANGED_HEADER', $this->pi_getLL('to_be_changed_header'));
$this->smarty->assign('TO_BE_DELETED_HEADER', $this->pi_getLL('to_be_deleted_header'));
$this->smarty->assign('WAS_CREATED_HEADER', $this->pi_getLL('was_created_header'));
$this->smarty->assign('WAS_DELETED_HEADER', $this->pi_getLL('was_deleted_header'));
$this->smarty->assign('WRONG_ENTRY_HEADER', $this->pi_getLL('wrong_entry_header'));
|
Durch pi_getLL wird auf die
Mehrsprachigkeit zurückgegriffen. Die Begriffe werden für
dieses erste Plugin in pi1/locallang.xml definiert.
Konfiguration für den Kalender:
|
$dir_jscalendar = '/typo3conf/ext/netcos_jscalendar/jscalendar/';
$import_jscalendar = '
<style type="text/css">@import url('.$dir_jscalendar.'calendar-green.css);</style>
<script type="text/javascript" src="'.$dir_jscalendar.'calendar.js"></script>
<script type="text/javascript" src="'.$dir_jscalendar.'calendar-setup.js"></script>
<script type="text/javascript" src="'.$dir_jscalendar.'lang/calendar-en.js"></script>;
';
$lang = $this->pi_getLL('language');
if ($lang == 'en') {
$date_lang = 'date_en';
} else {
$date_lang = 'Datum';
$import_jscalendar .= '<script type="text/javascript" src="'.
$dir_jscalendar.'lang/calendar-'.$lang.'.js"></script>';
}
$this->smarty->assign('IMPORT_JSCALENDAR', $import_jscalendar);
|
Dabei wird die deutsche Datei nur dann
eingebettet, wenn Deutsch die aktuelle Sprache ist.
Die folgenden Abschnitte der Form if
($POST['...']) {...} fangen
POST-Parameter aus früheren Läufen ab. Es werden eventuell
smarty-Abkürzungen
durch assign gesetzt.
Der Befehl fetch ruft
eine smarty-Template-Datei
auf. Deren Ergebnis $content schließt
diesen Lauf durch
|
return $this->pi_wrapInBaseClass($content);
|
ab.
|
if ($POST['to_be_deleted']) {
$this->smarty->assign('UID', $POST['uid']);
$this->smarty->assign('VALUE_FROM', $POST['data_from']);
$this->smarty->assign('VALUE_TO', $POST['data_to']);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['to_be_deleted']);
return $this->pi_wrapInBaseClass($content);
}
if ($POST['to_be_changed']) {
$this->smarty->assign('UID', $POST['uid']);
$this->smarty->assign('VALUE_FROM', $POST['data_from']);
$this->smarty->assign('VALUE_TO', $POST['data_to']);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['to_be_changed']);
return $this->pi_wrapInBaseClass($content);
}
|
Hier wird der
Datensatz mit einer gegebenen UID aus der Tabelle gelöscht:
|
if ($POST['delete']) {
$uid = $POST['uid'];
if ($uid) {
$where = 'uid='.$uid;
$GLOBALS['TYPO3_DB']->exec_DELETEquery($table_name, $where);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['was_deleted']);
return $this->pi_wrapInBaseClass($content);
}
}
|
Hier wird
ebenfalls der Datensatz mit einer gegebenen UID aus der Tabelle
gelöscht und die Variable $run_apply konfiguriert für
den nächsten Abschnitt:
|
$run_apply = FALSE;
if ($POST['change']) {
$uid = $POST['uid'];
if ($uid) {
$where = 'uid='.$uid;
$GLOBALS['TYPO3_DB']->exec_DELETEquery($table_name, $where);
}
$run_apply = TRUE;
}
|
Hier wird ein
neuer Datensatz angelegt:
|
if ($POST['apply'] || $run_apply) {
$richtig = TRUE;
$errmsg = '';
$df = $POST['data_from'];
if ($df) {
$f = new Termin($df);
if ($f->is_true()) {
} else {
$richtig = FALSE;
$errmsg .=
'"'.$this->pi_getLL("from").'"
'.$this->pi_getLL("pi1_erroneous").' '.
$f->get_error();
}
} else {
$richtig = FALSE;
$errmsg .=
'"'.$this->pi_getLL("from").'"
'.$this->pi_getLL("pi1_erroneous").'.';
}
$dt = $POST['data_to'];
if ($dt) {
$t = new Termin($dt);
if ($t->is_true()) {
} else {
$richtig = FALSE;
$errmsg .=
'"'.$this->pi_getLL("to").'"
'.$this->pi_getLL("pi1_erroneous").': '.
$t->get_error();
}
} else {
$richtig = FALSE;
$errmsg .=
'"'.$this->pi_getLL("to").'"
'.$this->pi_getLL("pi1_erroneous").'.';
}
if ($richtig) {
$query = 'SELECT uid FROM '.$table_name .
' WHERE from_date='.$f->string().' AND to_date='.$t->string();
$res = $GLOBALS['TYPO3_DB']->sql_query($query);
if ($GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['exists']);
return $this->pi_wrapInBaseClass($content);
} else {
$fields_values = array('from_date'
=> $f->string(), 'to_date' => $t->string());
$GLOBALS['TYPO3_DB']->exec_INSERTquery($table_name, $fields_values);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['was_created']);
return $this->pi_wrapInBaseClass($content);
}
} else {
$this->smarty->assign('ERRMSG', $errmsg);
$this->smarty->assign('UID', $uid);
$this->smarty->assign('VALUE_FROM', $df);
$this->smarty->assign('VALUE_TO', $dt);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['wrong_entry']);
return $this->pi_wrapInBaseClass($content);
}
}
|
Teste, ob Jahreswechsel in der
Darstellung ansteht:
|
$jahr = 0;
if ($POST['wechseln']) {
$jahr = $POST['jahr'];
if ($jahr < 100) $jahr += 2000;
if ($jahr >= 3000 || $jahr < 2000) $jahr = 0;
}
|
Suche aus der Datenbank alle gebuchten
Termine:
|
$query = 'SELECT uid,from_date,to_date FROM '.$table_name;
$res = $GLOBALS['TYPO3_DB']->sql_query($query);
$fromto = array();
$from = array();
while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
$u = $row["uid"];
$f = new Termin($row["from_date"]);
$t = new Termin($row["to_date"]);
$act = FALSE;
$errmsg = '';
if ($f->is_false() || $t->is_false()) {
$value_from = '';
$value_to = '';
$act = TRUE;
if ($f->is_false()) {
$msg = $f->get_error();
if ($msg) {
$errmsg .= '
"'.$this->pi_getLL("from").'"
'.$this->pi_getLL("pi1_has_error").': '.$msg;
} else {
$errmsg .= '
"'.$this->pi_getLL("from").'"
'.$this->pi_getLL("pi1_has_an_error").'.';
}
} else {
$value_from = $f->$date_lang();
}
if ($t->is_false()) {
$msg = $t->get_error();
if ($msg) {
$errmsg .= '
"'.$this->pi_getLL("to").'"
'.$this->pi_getLL("pi1_has_error").': '.$msg;
} else {
$errmsg .= '
"'.$this->pi_getLL("to").'"
'.$this->pi_getLL("pi1_has_an_error").'.';
}
} else {
$value_to = $t->$date_lang();
}
} else {
if ($f->int() > $t->int()) {
$value_from = $f->$date_lang();
$value_to = $t->$date_lang();
$errmsg =
'"'.$this->pi_getLL("from").'"
'.$this->pi_getLL("pi1_comes_after").' "'.
$this->pi_getLL("to").'".';
$act = TRUE;
}
}
if ($act) {
$this->smarty->assign('ERRMSG', $errmsg);
$this->smarty->assign('UID', $u);
$this->smarty->assign('VALUE_FROM', $value_from);
$this->smarty->assign('VALUE_TO', $value_to);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['wrong_entry']);
return $this->pi_wrapInBaseClass($content);
}
$from[$u] = $f;
$fromto[$u] = array("from_date" => $f, "to_date" => $t);
}
asort($from);
$sortiert = array_keys($from);
|
Stelle Fehler fest, wenn sich
2 Datensätze überschneiden:
|
$t0 = 0;
$f0 = 0;
$u0 = 0;
foreach ($sortiert as $uid) {
$f = $from[$uid];
$f1 = $f->int();
$t = $fromto[$uid]['to_date'];
$t1 = $t->int();
if ($t0 > $f1) {
$this->smarty->assign('UID1', $u0);
$this->smarty->assign('UID2', $uid);
$this->smarty->assign('VALUE_FROM1', $from[$u0]->$date_lang());
$this->smarty->assign('VALUE_TO1', $fromto[$u0]['to_date']->$date_lang());
$this->smarty->assign('VALUE_FROM2', $f->$date_lang());
$this->smarty->assign('VALUE_TO2', $t->$date_lang());
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['overlap']);
return $this->pi_wrapInBaseClass($content);
}
$f0 = $f1;
$t0 = $t1;
$u0 = $uid;
}
|
Filtere die passenden
Buchungstermine aus:
|
$aktuell_sortiert = array();
if ($jahr) {
$this->smarty->assign('BOOKINGS_TITLE',
$this->pi_getLL('administration_bookings_year').' '.$jahr);
$erster = new Termin('1.1.'.$jahr);
$letzter = new Termin('31.12.'.$jahr);
foreach ($sortiert as $uid) {
$f = $from[$uid];
$t = $fromto[$uid]['to_date'];
if ( ($f >= $erster && $f <= $letzter) ||
($t >= $erster && $t <= $letzter) ||
($f < $erster && $t > $letzter)
) array_push($aktuell_sortiert, $uid);
}
} else {
$this->smarty->assign('BOOKINGS_TITLE',
$this->pi_getLL('administration_bookings_actual'));
foreach ($sortiert as $uid) {
if ($fromto[$uid]['to_date'] > $heutetermin) array_push($aktuell_sortiert, $uid);
}
}
|
Erstelle Monatsdiagramm:
|
if (count($aktuell_sortiert) == 0) {
$aktuelle_buchungen = $this->pi_getLL('administration_none');
} else {
$aktuelle_buchungen = '<table
width="350px"><tr align="center">
<th>UID</th><th>'.$this->pi_getLL("from").'</th><th>'.
$this->pi_getLL("to").'</th><th></th><th></th></tr>';
foreach ($aktuell_sortiert as $uid) {
$aktuelle_buchungen .= '<tr>
<form method="post">
<td style="background-color: yellow;">
<input type="hidden" name="uid" value='.$uid.' />'.$uid.'
</td>
<td style="background-color: LightGreen;">
<input type="hidden" name="data_from" value='.$from[$uid]->$date_lang().'/>'.
$from[$uid]->$date_lang().'</td>
<td style="background-color: yellow;">
<input type="hidden" name="data_to" value='.$fromto[$uid]["to_date"]->$date_lang().
' />'.$fromto[$uid]["to_date"]->$date_lang().'</td>
<td><input type="submit" name="to_be_deleted" value="'.$this->pi_getLL("delete").'" />
</td>
<td><input type="submit" name="to_be_changed" value="'.$this->pi_getLL("change1").
'" /></td>
<td></td>
</form></tr>';
}
$aktuelle_buchungen .= '</table>';
}
$this->smarty->assign('AKTUELLES_JAHR', $heutetermin->Jahr());
$this->smarty->assign('AKTUELLE_BUCHUNGEN', $aktuelle_buchungen);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['administration']);
return $this->pi_wrapInBaseClass($content);
|
Ende der Datei:
}
}
if (defined('TYPO3_MODE') &&
$TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/netcos_renting/pi1/class.tx_netcosrenting_pi1.php'])
{
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/netcos_renting/pi1/class.tx_netcosrenting_pi1.php']);
}
?>
|
4.3 Zweites Plugin (vermietet)
In dieser Sektion stellen wir die Datei
typo3conf/ext/netcos_renting/pi2/class.tx_netcosrenting_pi2.php
vor. Da sie sehr lang ist, haben wir sie in viele Teile aufgeteilt,
die alle zusammengesetzt werden müssen. Sie können sie
jedoch auch aus dem Quellcode der Extension herausziehen.
Die Zeilenumbrüche müssen
jeweils entfernt werden.
Start und Lizenz:
|
<?php
/***************************************************************
* Copyright notice
*
* (c) 2007,2008 Bernd Warken <be.warken@netcos.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
|
Einbettung von PHP-Dateien:
|
require_once(PATH_tslib.'class.tslib_pibase.php');
require_once('class_termin.php');
require_once(t3lib_extMgm::extPath('smarty').'class.tx_smarty.php');
require_once(t3lib_extMgm::extPath('smarty').'Smarty/libs/Smarty.class.php');
|
Kickstarter-Dokumentation,
Klassendefinition, verwendete Variablen:
|
/**
* Plugin 'vermieted' for the 'netcos_renting' extension.
*
* @author Bernd Warken <be.warken@netcos.de>
* @package TYPO3
* @subpackage tx_netcosrenting
*/
class tx_netcosrenting_pi2 extends tslib_pibase {
var $prefixId = 'tx_netcosrenting_pi2'; // Same as class name
var $scriptRelPath = 'pi2/class.tx_netcosrenting_pi2.php';
// Path to this script relative to the extension dir.
var $extKey = 'netcos_renting'; // The extension key.
var $pi_checkCHash = true;
|
Methode main():
|
/**
* Main method of your PlugIn
*
* @param string $content: The content of the PlugIn
* @param array $conf: The PlugIn Configuration
* @return The content that should be displayed on the website
*/
function main($content,$conf) {
$this->conf=$conf;
$this->pi_setPiVarDefaults();
$this->pi_loadLL();
|
Speichere die Datensicherung des
vorigen Durchgangs in $POST:
|
global $_POST;
$POST = t3lib_div::_POST();
$_POST = array();
|
Aktiviere die Mehrsprachigkeit:
Smarty-Konfiguration:
|
$this->smarty = new Smarty;
$this->smarty->compile_dir = t3lib_extMgm::extPath($this->extKey).'tmpl_c';
$this->smarty->template_dir = t3lib_extMgm::extPath($this->extKey).'tmpl';
$this->smarty->left_delimiter = '{..';
$this->smarty->right_delimiter = '..}';
$this->templates['booked'] = 'tmpl/pi2/booked.tmpl';
$this->templates['error'] = 'tmpl/pi2/error.tmpl';
|
Name der MySQL-Tabelle:
|
$table_name = 'tx_netcosrenting_fromto';
|
Smarty-Variablen für
die HTML-Template-Dateien:
|
$this->smarty->assign('PREVIOUS_MONTH', $this->pi_getLL('previous_month'));
$this->smarty->assign('ACTUAL_MONTH', $this->pi_getLL('actual_month'));
$this->smarty->assign('NEXT_MONTH', $this->pi_getLL('next_month'));
$this->smarty->assign('MONDAY', $this->pi_getLL('monday'));
$this->smarty->assign('TUESDAY', $this->pi_getLL('tuesday'));
$this->smarty->assign('WEDNESDAY', $this->pi_getLL('wednesday'));
$this->smarty->assign('THURSDAY', $this->pi_getLL('thursday'));
$this->smarty->assign('FRIDAY', $this->pi_getLL('friday'));
$this->smarty->assign('SATURDAY', $this->pi_getLL('saturday'));
$this->smarty->assign('SUNDAY', $this->pi_getLL('sunday'));
$this->smarty->assign('CALENDAR_WEEK', $this->pi_getLL('calendar_week'));
$this->smarty->assign('BOOKED_CHANGE', $this->pi_getLL('booked_change'));
$this->smarty->assign('BOOKED_FUTURE', $this->pi_getLL('booked_future'));
$this->smarty->assign('BOOKED_HEADER', $this->pi_getLL('booked_header'));
$this->smarty->assign('ERROR_BACK', $this->pi_getLL('error_back'));
$this->smarty->assign('ERROR_HEADER', $this->pi_getLL('error_header'));
$this->smarty->assign('ERROR_TEXT', $this->pi_getLL('error_text'));
|
Variablen zu aktuellem Datum:
|
$aktuelles_jahr = date('Y');
$aktueller_monat = date('n');
$heutetermin = new Termin((string)date('d').'.'.(string)date('n').'.'.(string)date('Y'));
$monate = array(0, $this->pi_getLL("january"), $this->pi_getLL("february"),
$this->pi_getLL("march"), $this->pi_getLL("april"), $this->pi_getLL("mai"),
$this->pi_getLL("june"), $this->pi_getLL("july"), $this->pi_getLL("august"),
$this->pi_getLL("september"), $this->pi_getLL("october"),
$this->pi_getLL("november"), $this->pi_getLL("december"));
|
Variablen aus POST-Werten vom vorigen
Lauf:
|
$monat = $POST['Monat'];
$jahr = $POST['Jahr'];
|
Stelle auf passenden Monat um:
|
$aktuell_text = '';
if ( (int)$monat > 0 && (int)$jahr > 0 ) {
if ($jahr == $aktuelles_jahr && $monat == $aktueller_monat)
$aktuell_text = $this->pi_getLL('actual_month').': ';
else {
$vormonat = $aktueller_monat - 1;
$vormonat_jahr = $aktuelles_jahr;
if ($vormonat == 0) {
$vormonat = 12;
$vormonat_jahr -= 1;
}
if ($jahr < $vormonat_jahr ||
($jahr == $vormonat_jahr && $monat < $vormonat)) {
# Verbot für Monate vor dem Vormonat
$this->smarty->assign('ZEIT', $monate[$monat].' '.$jahr);
$this->smarty->assign('AKTUELLES_JAHR', $aktuelles_jahr);
$this->smarty->assign('AKTUELLER_MONAT', $aktueller_monat);
$content = $this->smarty->fetch(t3lib_extMgm::extPath($this->extKey).
$this->templates['error']);
$res = $this->pi_wrapInBaseClass($content);
return $res;
}
if ($jahr == $vormonat_jahr && $monat == $vormonat)
$aktuell_text = $this->pi_getLL('previous_month').': ';
else {
$folgemonat = $aktueller_monat + 1;
$folgemonat_jahr = $aktuelles_jahr;
if ($folgemonat == 13) {
$folgemonat = 1;
$folgemonat_jahr += 1;
}
if ($jahr == $folgemonat_jahr && $monat == $folgemonat)
$aktuell_text = $this->pi_getLL('next_month').': ';
}
}
} else {
switch($monat) {
case $this->pi_getLL('previous_month'):
if ($aktueller_monat == 1) {
$monat = 12;
$jahr = $aktuelles_jahr - 1;
} else {
$monat = $aktueller_monat - 1;
$jahr = $aktuelles_jahr;br/>
}
$aktuell_text = $this->pi_getLL('previous_month').': ';
break;
case $this->pi_getLL('next_month'):
if ($aktueller_monat == 12) {
$monat = 1;
$jahr = $aktuelles_jahr + 1;
} else {
$monat = $aktueller_monat + 1;
$jahr = $aktuelles_jahr;
}
$aktuell_text = $this->pi_getLL('next_month').': ';
break;
default:
$jahr = $aktuelles_jahr;
$monat = $aktueller_monat;
$aktuell_text = $this->pi_getLL('actual_month').': ';
}
}
|
Erstelle Display zum ausgesuchten
Monat:
|
$termin_erster = new Termin('1.'.$monat.'.'.$jahr);
$tei = $termin_erster->int();
$max_tage = (string)($termin_erster->max_Tage_des_Monats());
$termin_letzter = new Termin($max_tage.'.'.$monat.'.'.$jahr);
$tli = $termin_letzter->int();
$tage_gebucht = array();
for ($i = 0; $i<=$max_tage; $i++) $tage_gebucht[$i] = 0;
$query = 'SELECT from_date,to_date ' .
'FROM '.$table_name.' ' .
'WHERE (from_date>='.$tei.' AND from_date<='.$tli.') OR ' .
'(to_date>='.$tei.' AND to_date<='.$tli.') OR ' .
'(from_date<'.$tei.' AND to_date>'.$tli.')';
$res = $GLOBALS['TYPO3_DB']->sql_query($query);
while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
$v = new |