Alternative Codegenerierung für das Frontend

Fragen zur Installation von CONTENIDO 4.9? Probleme bei der Konfiguration? Hinweise oder Fragen zur Entwicklung des Systemes oder zur Sicherheit?
Antworten
xmurrix
Beiträge: 3215
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Hat sich bedankt: 4 Mal
Danksagung erhalten: 17 Mal
Kontaktdaten:

Alternative Codegenerierung für das Frontend

Beitrag von xmurrix »

Hallo zusammen,

viele von euch werden sicherlich wissen, wie der Code für eine Frontendseite in Contenido generiert wird.

Trotzdem mache ich eine kleine Zusammenfassung...

Zuerst gibt es das Layout, in der die Modulcontainer definiert werden. Hier ein vereinfachtes Beispiel mit einem Modulcontainer:

Code: Alles auswählen

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <title>Layout</title>
</head>
<body>
    <container id="10" name="MyContentModule" types="Content" mode="fixed" default="">Content module</container>
</body>
</html>

Dazu kann man ein Modul implementieren, das sich um die Ausgabe kümmert. Hier ein einfaches Moduloutput-Beispiel zum obrigen Modul "MyContentModule":

Code: Alles auswählen

<?php

echo '
    <div class="loremIpsum">
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt 
    ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </div>
';

?>

Der Code der Seite wird beim Generieren aus Layout + Modul zusammmengefügt. Es kommt dann folgendes raus:

Code: Alles auswählen

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <title>Layout</title>
</head>
<body>
<?php

echo '
    <div class="loremIpsum">
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt 
    ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </div>
';

?>
</body>
</html>
Der Modulcontainer wird also gegen die Modulausgabe ersetzt. Der PHP-Code in den Modulen wird innerhalb der Ausgabe der Seite verarbeitet.

Alternative Codegenerierung
Nun möchte ich eine andere Variante der Codegenerierung vorstellen, die Möglichkeit zur Verarbeitung der Module vor der Ausgabe.

Wenn der PHP-Code der Module vor der Ausgabe der Seite ausgeführt wird, also schon vor dem Layout, könnte man folgende Features realisieren, sofern diese Möglichkeiten implementiert sind:
  • Module könnten CSS-/ oder JS-Dateien hinzufügen.

    Code: Alles auswählen

    <?php
    Contenido_FePage::getInstance()->addCSS('/path/to/styles.css');
    Contenido_FePage::getInstance()->addJS('/path/to/javascript.js');
    ?>
    
  • Module könnten CSS-/ oder JS-Code in den head-Bereich hinzufügen

    Code: Alles auswählen

    <?php
    Contenido_FePage::getInstance()->addCSSCode('* {margin:0; padding:0;}');
    Contenido_FePage::getInstance()->addJSCode('alert("foobar");');
    ?>
    
  • In Modulen könnte man auf die Metatags einfluss nehmen.

    Code: Alles auswählen

    <?php
    Contenido_FePage::getInstance()->setMetatag('description', 'Foobar');
    ?>
    
  • In Modulen könnte man weitere zusätzliche Elemente in den head-Bereich einfügen.

    Code: Alles auswählen

    <?php
    Contenido_FePage::getInstance()->addLink(array(
        'rel'   => 'alternate',
        'type'  => 'application/rss+xml',
        'title' => 'RSS Feed',
        'href'  => 'http://domain/path/to/rssfeed'
    ));
    ?>
    
  • Man könnte die Ausgabe eines Modulcodes, das vorher ausgeführt wurde, nachträglich modifizieren

    Code: Alles auswählen

    <?php
    $page = Contenido_FePage::getInstance();
    $output = $page->getModuleOutput('10'); // get moduleputput by container id
    $output = strip_tags($output);
    $output = $page->setModuleOutput('10', $output);
    ?>
    
  • Man könnte sogar im letzten Modul einen HTTP-header setzen oder gar einen richtigen Redirect mit der head-Direktive machen

    Code: Alles auswählen

    <?php
    $page = Contenido_FePage::getInstance();
    
    // HTTP 404 ausgeben
    $page->setHttpHeader('HTTP/1.0 404 Not Found');
    
    // HTTP 302 ausgeben
    $url = Contenido_Url::getInstance()->build(array('idart' => 123, 'lang' => $lang));
    $page->redirect($url);
    ?>
    
  • Wenn der Modulcode aus einer zentralen Stelle kommt, kann man an dieser Stelle sogar einen Modul Cachingmechanismus implementieren oder sogar auf Modulebene die Ausgabe abhängig vom angemeldeten Frontend-Benutzer machen.
    Dann wäre es möglich, dass man das sogar über den Modulcontainer steuert

    Code: Alles auswählen

    <container id="10" name="MyContentModule" types="Content" mode="fixed" default="" cachelifetime="60" cacheoptions="get,post,session" feusergroup="Contenidos">Content module</container>
    
  • Viele weitere Möglichkeiten sind denkbar, z. B. dass jeder Modulcode einen preInit und einen postProcess Hook bekommt...
Eine lauffähige Beispielimplementation dieser Features ist zum größsten Teil vorhanden, das alles ist also nicht nur reine Theorie.
Um das realisieren zu können, musste im Core nur die Erstellung des Codes angepasst werden, die Funktion conGenerateCode().

Der generierte Code der Startseite des Beispielmandanten unter 4.8.12 sieht, etwas bereinigt, folgendermaßen aus:

Code: Alles auswählen

<?php
// ####################### start module "1" #######################
$C1CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 3;$cCurrentContainer = 1; ?><?php

if (!isset($tpl) || !is_object($tpl) || strtolower(get_class($tpl)) != 'template') {
    $tpl = new Template();
}
$tpl->reset();
$tpl->generate('templates/contenido_header.html');
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("1", $modOut);
// ######################## end module "1" ########################
?><?php
// ####################### start module "10" #######################
$C10CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 22;$cCurrentContainer = 10; ?><?php

cInclude('classes', 'Contenido_FrontendNavigation/Contenido_FrontendNavigation_Breadcrumb.class.php');
try {
    $oBread = new Contenido_FrontendNavigation_Breadcrumb($db, $cfg, $client, $lang, $cfgClient);
    $oBreadCats = $oBread->get($idcat, 1);
    $sBread = 'Contenido - ';
    $aBread = array();
    foreach ($oBreadCats as $oConCat) {
        $aBread[] = $oConCat->getCategoryLanguage()->getName();
    }
    $sBread .= implode(' - ', $aBread);
    $oArticle = new Article($idart, $client, $lang);
    $sHeadline = strip_tags($oArticle->getContent('CMS_HTMLHEAD', 1));
    if ($sHeadline != '') {
        $sBread .= ' - '.$sHeadline;
    }
    echo $sBread;
} catch (InvalidArgumentException $eI) {
    echo 'Contenido';
} catch (Exception $e) {
    echo 'Contenido';
}
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("10", $modOut);
// ######################## end module "10" ########################
?><?php
// ####################### start module "20" #######################
$C20CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 5;$cCurrentContainer = 20; ?><?php

cInclude('classes', 'Contenido_Category/Contenido_Category.class.php');

// get start idcat
$iIdcatStart = (int) getEffectiveSetting('navigation', 'idcat-home', '1');

try {
	// get headline
    $oConCat = new Contenido_Category($db, $cfg);
	$oConCat->load($idcat, true, $lang);
	$sImgEdit = "";
	$sImg = "";
	
	$sHeadline = $iIdcatStart != intval($idcat) 
	                ? $oConCat->getCategoryLanguage()->getName() 
	                : mi18n("Willkommen!");
	$sCssStyle = '';
	if ($contenido && $edit) {
	    echo '<div id="modHeaderImgEdit">'.$sImgEdit.'</div>';
	}
    if ($sImg != '') {
        $sCssStyle = ' style="background-image:url('.$sImg.');"';
    }
	$tpl->reset();
	$tpl->set('s', 'css-style', $sCssStyle);
	$tpl->set('s', 'url', 'front_content.php');
	$tpl->set('s', 'title', mi18n("Zur Contenido Homepage"));
	$tpl->set('s', 'headline', $sHeadline);
	$tpl->generate('templates/header.html');
} catch (InvalidArgumentException $eI) {
    echo 'Some error occured: ' . $eI->getMessage() . ': ' . $eI->getFile() . ' at line '.$eI->getLine() . ' ('.$eI->getTraceAsString().')';
} catch (Exception $e) {
    echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
}
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("20", $modOut);
// ######################## end module "20" ########################
?><?php
// ####################### start module "30" #######################
$C30CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 10;$cCurrentContainer = 30; ?><?php

// include Contenido_FrontendNavigation class
cInclude('classes', 'Contenido_FrontendNavigation/Contenido_FrontendNavigation.class.php');
cInclude('classes', 'Contenido_FrontendNavigation/Contenido_FrontendNavigation_Breadcrumb.class.php');

// get start idcat
$iIdcatStart = getEffectiveSetting('navigation', 'idcat-home', 1);

// instantiate 2nd + 3rd template object, reset all
$tpl2 = new Template();
$tpl3 = new Template();
$tpl->reset();
$tpl2->reset();
$tpl3->reset();

// build navigation
try {
    $oFeNav = new Contenido_FrontendNavigation($db, $cfg, $client, $lang, $cfgClient);
    $oBreadcrumb = new Contenido_FrontendNavigation_Breadcrumb($db, $cfg, $client, $lang, $cfgClient);
    $aBreadcrumb = $oBreadcrumb->getAsArray($idcat, 1); // this nav starts at level 1
    $oFeNav->setAuth($auth); // to make sure user sees what he's allowed to see
    $oContenidoCategories = $oFeNav->getSubCategories($iIdcatStart, true);
    if ($oContenidoCategories->count() > 0) {
        foreach ($oContenidoCategories as $oContenidoCategory) {
            $sSubcats = '';
            $tpl2->reset();
            $bHasActiveSubCat = false;
            // check if we need to load subcategories
            $oSubCatsLevel2 = $oFeNav->getSubCategories($oContenidoCategory->getIdCat(), true);
            $aSubCatsLevel2 = $oFeNav->getSubCategories($oContenidoCategory->getIdCat(), false);
            $bShowSubcatLevel2 = (intval($idcat) == $oContenidoCategory->getIdCat() || in_array(intval($idcat), $aSubCatsLevel2) 
                                || (isset($aBreadcrumb[2]) && intval($idcat) == $aBreadcrumb[2] && in_array($aBreadcrumb[1], $aSubCatsLevel2)))
                                ? true : false;
            if ($bShowSubcatLevel2 === true && $oSubCatsLevel2->count() > 0) {
                foreach ($oFeNav->getSubCategories($oContenidoCategory->getIdCat(), true) as $oSubCategory) {
                    $bHasActiveSubSubCat = false;
                    // check if we need to load subsubcategories
                    $oSubCatsLevel3 = $oFeNav->getSubCategories($oSubCategory->getIdCat(), true);
                    $aSubCatsLevel3 = $oFeNav->getSubCategories($oSubCategory->getIdCat(), false);
                    $bShowSubcatLevel3 = (intval($idcat) == $oSubCategory->getIdCat() || 
                                            in_array(intval($idcat), $aSubCatsLevel3))
                                            ? true : false;
                    $sSubcats2 = '';
                    if ($bShowSubcatLevel3 === true) {
                        foreach ($oSubCatsLevel3 as $oSubSubCategories) {
                            if ($bHasActiveSubCat === false && intval($idcat) == $oSubSubCategories->getIdCat()) {
                                $bHasActiveSubCat = true;
                            }
                            if ($bHasActiveSubSubCat === false && intval($idcat) == $oSubSubCategories->getIdCat()) {
                                $bHasActiveSubSubCat = true;
                            }
                            toTpl($tpl3, $oSubSubCategories, (intval($idcat) == $oSubSubCategories->getIdCat() ? ' class="active"' : ''), '');
                        }
                        $sSubcats2 = $tpl3->generate('templates/navigation_main_item.html', true, false);
                        $tpl3->reset();
                        $tpl3->set('s', 'items', $sSubcats2);
                        $tpl3->set('s', 'css-class', ' class="subSubNavigation"');
                        $sSubcats2 = $tpl3->generate('templates/navigation_main_container.html', true, false);
                    }
                    if ($bHasActiveSubCat === false && intval($idcat) == $oSubCategory->getIdCat()) {
                        $bHasActiveSubCat = true;
                    }
                    toTpl($tpl2, $oSubCategory, 
                            (intval($idcat) == $oSubCategory->getIdCat() || $bHasActiveSubSubCat === true ? ' class="active"' : ''), 
                            $sSubcats2);
                }
                $sSubcats = $tpl2->generate('templates/navigation_main_item.html', true, false);
                $tpl2->reset();
                $tpl2->set('s', 'items', $sSubcats);
                $tpl2->set('s', 'css-class', ' class="subNavigation"');
                $sSubcats = $tpl2->generate('templates/navigation_main_container.html', true, false);
            }
            toTpl($tpl, $oContenidoCategory, ($bHasActiveSubCat === true || intval($idcat) == $oContenidoCategory->getIdCat() ? ' class="active"' : ''), $sSubcats);
        }
        $sCats = $tpl->generate('templates/navigation_main_item.html', true, false);
        $tpl->reset();
        $tpl->set('s', 'css-class', '');
        $tpl->set('s', 'items', $sCats);
        $tpl->generate('templates/navigation_main_container.html');
    }
} catch (Exception $e) {
    echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
}

function toTpl(&$oTpl, Contenido_Category $oCat, $sActiveCssClass, $sSubcats) {
    $oTpl->set('d', 'css-class', $sActiveCssClass);
#   $oTpl->set('d', 'url', 'front_content.php?idcat='.$oCat->getIdCat());
    $oTpl->set('d', 'url', $GLOBALS['sess']->url('front_content.php?idcat='.$oCat->getIdCat()));
    $oTpl->set('d', 'title', $oCat->getCategoryLanguage()->getName());
    $oTpl->set('d', 'label', $oCat->getCategoryLanguage()->getName());
    $oTpl->set('d', 'subcategories', $sSubcats); // followup level
    $oTpl->next();
}
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("30", $modOut);
// ######################## end module "30" ########################
?><?php
// ####################### start module "40" #######################
$C40CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 17;$cCurrentContainer = 40; ?><?php

$tpl->reset();

$sTargetIdcat = getEffectiveSetting('search-results', 'idcat', '1');
$sTargetIdart = getEffectiveSetting('search-results', 'idart', '1');
$sFormAction = 'front_content.php?idcat='.$sTargetIdcat.'&idart='.$sTargetIdart;

$tpl->set('s', 'form_action', $sFormAction);
$tpl->set('s', 'label_search', mi18n("Suche"));
$tpl->generate('templates/search_input.html');
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("40", $modOut);
// ######################## end module "40" ########################
?><?php
// ####################### start module "50" #######################
$C50CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 6;$cCurrentContainer = 50; ?><?php

$tpl->reset();
if ($contenido && $edit) {
    $tpl->set('s', 'text', "Ihre Installation hat geklappt!
");
} else {
    $tpl->set('s', 'text', strip_tags("Ihre Installation hat geklappt!
"));
}
$tpl->generate('templates/headline_h1.html');
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("50", $modOut);
// ######################## end module "50" ########################
?><?php
// ####################### start module "51" #######################
$C51CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 20;$cCurrentContainer = 51; ?><?php

$sText = "";

$tpl->reset();
if ($contenido && $edit) {
    $tpl->set('s', 'text', $sText);
    $tpl->generate('templates/subheadline_h2.html');
} else {
    if ($sText != '') {
	    $tpl->set('s', 'text', strip_tags($sText));
	    $tpl->generate('templates/subheadline_h2.html');
    }
}

?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("51", $modOut);
// ######################## end module "51" ########################
?><?php
// ####################### start module "60" #######################
$C60CMS_VALUE[0]="http://www.contenido.org/rss/de/news"; $C60CMS_VALUE[1]="teaser_right.html"; $C60CMS_VALUE[2]="3"; 
ob_start();
?>
<?php $cCurrentModule = 16;$cCurrentContainer = 60; ?><?php

cInclude("pear", "XML/Parser.php");
cInclude("pear", "XML/RSS.php");

if ("http://www.contenido.org/rss/de/news" == "")
{
  $sFeed = "http://www.contenido.org/rss/de/news";
} else {
  $sFeed = "http://www.contenido.org/rss/de/news";
}

if ("3" == "")
{
  $FeedMaxItems = 999;
} else {
	$FeedMaxItems = intval("3");
}

/* Preparse feed for an encoding due to the poorly designed
   PHP XML parser */
$sFeedContent = substr(@file_get_contents($sFeed),0,1024);

$regExp = "/<\\?xml.*encoding=[\"\'](.*)[\"\']\\?>/i";
		
preg_match($regExp,trim($sFeedContent),$matches);

if ($matches[1])
{
  $rss = new XML_RSS($sFeed, $matches[1]);
} else {
  $rss = new XML_RSS($sFeed);
}

$rss->parse();

$tpl = new Template;

$i = 0;
foreach ($rss->getItems() as $item)
{
	if ($i < $FeedMaxItems) {
	    $tpl->set("d", "TITLE", htmlentities($item['title'],ENT_QUOTES));
    	$tpl->set("d", "LINK", htmlentities($item['link'],ENT_QUOTES));
    	$tpl->set("d", "DESCRIPTION", htmlentities($item['description'],ENT_QUOTES));
    	$tpl->set("d", "READ_ON", mi18n("weiterlesen"));
	    $tpl->next();
	}
	$i++;
}

$tpl->generate($cfgClient[$client]["path"]["frontend"]."templates/"."teaser_right.html");
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("60", $modOut);
// ######################## end module "60" ########################
?><?php
// ####################### start module "70" #######################
$C70CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 8;$cCurrentContainer = 70; ?><?php

$tpl->reset();
$tpl->generate('templates/logo_bottom.html');
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("70", $modOut);
// ######################## end module "70" ########################
?><?php
// ####################### start module "75" #######################
$C75CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 11;$cCurrentContainer = 75; ?><?php

// include Contenido_FrontendNavigation class
cInclude('classes', 'Contenido_FrontendNavigation/Contenido_FrontendNavigation.class.php');

// get start idcat
$iIdcatStart = getEffectiveSetting('navigation', 'idcat-meta', 2);

// reset template object
$tpl->reset();

// build navigation
try {
	$oFeNav = new Contenido_FrontendNavigation($db, $cfg, $client, $lang, $cfgClient);
	$oContenidoCategories = $oFeNav->getSubCategories($iIdcatStart, true);
    if ($oContenidoCategories->count() > 0) {
		foreach ($oContenidoCategories as $oContenidoCategory) {
		    $tpl->set('d', 'url', $sess->url('front_content.php?idcat='.$oContenidoCategory->getIdCat()));
		    $tpl->set('d', 'title', $oContenidoCategory->getCategoryLanguage()->getName());
		    $tpl->set('d', 'label', $oContenidoCategory->getCategoryLanguage()->getName());
		    $tpl->next();
		}
		$sItems = $tpl->generate('templates/navigation_meta_item.html', true, false);
		$tpl->reset();
		$tpl->set('s', 'items', $sItems);
		$tpl->generate('templates/navigation_meta_container.html');
    }
} catch (Exception $e) {
	echo 'Shit happens: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
}
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("75", $modOut);
// ######################## end module "75" ########################
?><?php
// ####################### start module "76" #######################
$C76CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 4;$cCurrentContainer = 76; ?><?php

$tpl->reset();
$tpl->generate('templates/footnotes_'.strval($lang).'.html');
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("76", $modOut);
// ######################## end module "76" ########################
?><?php
// ####################### start module "80" #######################
$C80CMS_VALUE[]=""; 
ob_start();
?>
<?php $cCurrentModule = 7;$cCurrentContainer = 80; ?><?php

$tpl->reset();

if ($auth->auth["uid"] == "nobody") {
	$sTargetIdcat = getEffectiveSetting('login', 'idcat', '1');
	$sTargetIdart = getEffectiveSetting('login', 'idart', '1');
	$sFormAction = 'front_content.php?idcat='.$sTargetIdcat.'&idart='.$sTargetIdart;
	
	$tpl->set('s', 'headline', mi18n("Geschlossener Bereich Login"));
	$tpl->set('s', 'form_action', $sFormAction);
	$tpl->set('s', 'label_name', mi18n("name"));
	$tpl->set('s', 'label_pass', mi18n("pass"));
	$tpl->set('s', 'label_login', mi18n("einloggen"));
	$tpl->generate('templates/login_form.html');
} else {
    cInclude('classes', 'class.frontend.users.php');
    cInclude('classes', 'Contenido_Category/Contenido_Category.class.php');
    try {
	    $oConCat = new Contenido_Category($db, $cfg);
		$oConCat->load($idcat, true, $lang);
		$bCatIsPublic = ($oConCat->getCategoryLanguage()->getVisible() == 1 && $oConCat->getCategoryLanguage()->getPublic() == 1) 
		                ? true : false;
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    $oFeUserCollection = new FrontendUserCollection();
	$oFeUser = $oFeUserCollection->loadItem($auth->auth["uid"]);
    $sText = str_replace('[uname]', $oFeUser->get('username'), mi18n("Willkommen <strong>[uname]</strong>, schön, dass Sie wieder bei uns vorbeischauen."));
    if ($bCatIsPublic === true) {
        $sUrl = 'front_content.php?idcat='.$idcat.'&idart='.$idart.'&logout=true';
    } else {
        $iIdcatHome = (int) getEffectiveSetting('navigation', 'idcat-home', '1');
        $sUrl = 'front_content.php?idcat='.$iIdcatHome.'&logout=true';
    }
    $tpl->set('s', 'headline', mi18n("Geschlossener Bereich Logout"));
	$tpl->set('s', 'text', $sText);
	$tpl->set('s', 'url', $sUrl);
	$tpl->set('s', 'label_logout', mi18n("ausloggen"));
	$tpl->generate('templates/login_form_loggedin.html');
}
?>

<?php
$modOut = ob_get_contents();
ob_end_clean();
ConMp_FePage::getInstance()->addModuleOutput("80", $modOut);
// ######################## end module "80" ########################
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
    <head>
        <?php echo ConMp_FePage::getInstance()->getModuleOutput("1"); ?>
        <title><?php echo ConMp_FePage::getInstance()->getModuleOutput("10"); ?></title>
        <link rel="stylesheet" href="css/contenido_sample.css" type="text/css" media="all" />
        <!--[if lte IE 6]>
            <style type="text/css">
                .clearfix {height:1px;}
            </style>
        <![endif]-->
    <meta name="generator" content="CMS Contenido 4.8.12" />
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=iso-8859-1" />
<meta name="author" content="Systemadministrator" />
<meta name="date" content="2010-01-08 17:54:10" />
<meta name="description" content="Ihre Installation hat geklappt! " />
<meta name="keywords" content="k&amp;ouml;nnen, contenido, ihnen, seite, einer, diese, anhand, einen" />
</head>
    <body>

        <div id="outerContainer">
            
            <div id="head">
                <?php echo ConMp_FePage::getInstance()->getModuleOutput("20"); ?>
            </div>
            
            <div id="contentContainer" class="clearfix">
                <div id="navigation">
                    <?php echo ConMp_FePage::getInstance()->getModuleOutput("30"); ?>
                    <?php echo ConMp_FePage::getInstance()->getModuleOutput("40"); ?>
                </div>
                <div id="whiteBg">
                    <div id="content">
                        <?php echo ConMp_FePage::getInstance()->getModuleOutput("50"); ?>
                        <?php echo ConMp_FePage::getInstance()->getModuleOutput("51"); ?>
                        <img src="images/hr_article.gif" alt="" class="hr" />
                    </div>
                    <div id="teasersRight">
                        <?php echo ConMp_FePage::getInstance()->getModuleOutput("60"); ?>
                    </div>
                </div>
            </div>
            
        </div> <!-- /outerContainer -->
        
        <div id="footer">
            <div id="footerContainer">
                <?php echo ConMp_FePage::getInstance()->getModuleOutput("70"); ?>
                <div id="footerContentContainer" class="clearfix">
                    <div id="footerContentLeft">
                        <?php echo ConMp_FePage::getInstance()->getModuleOutput("75"); ?>
                        <?php echo ConMp_FePage::getInstance()->getModuleOutput("76"); ?>
                    </div>
                    <div id="footerContentRight">
                        <?php echo ConMp_FePage::getInstance()->getModuleOutput("80"); ?>
                    </div>
                </div>
            </div>
        </div>

    </body>

</html>
Dieser Ansatz kann meiner Meinung nach die Modulentwicklung und die Möglichkeiten davon ein großes Stück voranbringen.

Natürlich gibt es die Möglichkeit, weiterhin die originale Variante (inline Modulcodes) zu verwenden.

Bei Interesse stelle ich den Code dazu gerne zur Verfügung, und würde diesen mit der Commmunity zusammen weiter entwickeln.

Nachtrag:
Damit der Zugriff auf den Head-Bereich im Dokument, also die Möglichkeit zum Setzen der Meta-/Link-Tags usw., möglich ist, müsste die Contenido-Interne Metatag-Generierung auch angepasst werden.

Nachtrag 2:
Nun, den Code für das Ganze habe ich dem Beitrag hinzugefügt. Schaut euch das an, vielleicht ist es brauchbar, vielleicht auch nicht.
Das Ganze ist experimentiell und mehr Prototyp als eine saubere Implementierung.

Grüße
xmurrix
Dateianhänge
Contenido_Frontendcode_Generation_20100202.zip
Sourcen für die alternative Codegenerierung
(30.44 KiB) 253-mal heruntergeladen
Zuletzt geändert von xmurrix am Di 2. Feb 2010, 17:51, insgesamt 4-mal geändert.
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.
kummer
Beiträge: 2423
Registriert: Do 6. Mai 2004, 09:17
Wohnort: Bern, Schweiz
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von kummer »

gute idee. die könnte fast von mir sein... ;-)
aitsu.org :: schnell - flexibel - komfortabel :: Version 2.2.0 (since June 22, 2011) (jetzt mit dual license GPL/kommerziell)
xmurrix
Beiträge: 3215
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Hat sich bedankt: 4 Mal
Danksagung erhalten: 17 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von xmurrix »

Bin mir sicher, dass du schon in der Art was gemacht hast.

Es wäre schön, wenn solche Ideen in den Core einfließen - Schaumermal, was da rauskommt...

Gruß
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.
Oldperl
Beiträge: 4316
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Eltmann, Unterfranken, Bayern
Hat sich bedankt: 6 Mal
Danksagung erhalten: 4 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von Oldperl »

Ich finds gut, man muss halt den Code mal schaun. Falls es funktioniert bin ich auch für eine Integration in den Core.

Gruß aus Franken

Ortwin
ConLite 3.0.0-dev, alternatives und stabiles Update von Contenido 4.8.x unter PHP 8.x - Download und Repo auf Gitport.de
phpBO Search Advanced - das Suchwort-Plugin für CONTENIDO 4.9
Mein Entwickler-Blog
kummer
Beiträge: 2423
Registriert: Do 6. Mai 2004, 09:17
Wohnort: Bern, Schweiz
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von kummer »

xmurrix hat geschrieben:Bin mir sicher, dass du schon in der Art was gemacht hast.
ich bin mir sicher, dass du dir sicher bist... oder ist die ähnlichkeit zufall?

einbindung von javascript und css: http://www.aitsu.org/dokumentation/tipp ... inden.html
caching auf modulebene: http://www.aitsu.org/cms/caching/modulcache/

ist ja im übrigen auch kein geheimnis...
xmurrix hat geschrieben:Es wäre schön, wenn solche Ideen in den Core einfließen - Schaumermal, was da rauskommt...
das haben sie getan. bloss nicht hier. und auch contenido kriegt jetzt offenbar davon was ab. immer vorausgesetzt, dass 4fb nicht das veto einlegt.

ich habe - nur um dem vorwurf vorzubeugen - nichts dagegen, dass kopiert wird. ich halte es im gegenteil für ein kompliment. wir zeigen offenbar nicht nur auf, wo der schuh drückt, sondern auch, wie man es lösen kann. und wer das original einsetzt, kriegt sogar noch ein paar dinge mehr... ;-) und früher...
aitsu.org :: schnell - flexibel - komfortabel :: Version 2.2.0 (since June 22, 2011) (jetzt mit dual license GPL/kommerziell)
xmurrix
Beiträge: 3215
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Hat sich bedankt: 4 Mal
Danksagung erhalten: 17 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von xmurrix »

Ja, ich gebe zu, dass es Ähnlichkeiten gibt, das kann man aber nie ganz vermeiden.

Bei Joomla nennt sich das z. B. JDocument, bei Zend gibt es z. B. Zend_View_Helper_HtmlPage, da gibt es viele Andere CMS/Frameworks, die das so in der Art machen, die Idee ansich gibt es schon seit langem, ist für Contenido in Kombination mit den Modulen noch nicht umgesetzt worden.
Soweit ich mich erinnere, war das Cachen von Modulen sogar deine Idee, als ich die erste Cache Implementation mit PEAR-Cache vor vielen Jahren vorgestellt habe.

Mit Experimenten in dieser Richtung habe ich vor langer Zeit noch zu PHP4-Zeiten begonnen, also bevor irgend etwas in der Richtung über in Contenido spruchreif war.

Mag sein, dass das jetzt als eine Art Kopie interpretiert wird, das ist aber nicht so. Jeder, der sich mit dem Core beschäftigt und etwas Ahnung von PHP hat, ist in der Lage, auf solche Ideen zu kommen.

Viele hier in der Communitiy tüfteln an irgendwelchen Eigenentwicklungen am Core, und vieles davon bleibt in der Schublade, ab und an kommt halt was raus...

und auch contenido kriegt jetzt offenbar davon was ab. immer vorausgesetzt, dass 4fb nicht das veto einlegt.
Ob das in den Core kommt, kann ich nicht sagen. Das was ich machen kann, ist es hier vorzustellen. Es wäre wünschenswert, wenn der Vorschlag übernommen wird.


Wie gesagt, ich stelle den Code zur Verfügung. Jeder kann sich das ansehen und überprüfen, ob es da irgendwelche Ähnlichkeiten alá "Copy & Paste" mit eigenem Code gibt.

Grüße
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.
OliverL
Beiträge: 870
Registriert: Do 28. Jun 2007, 09:28
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von OliverL »

Hi ho Mädels *duck

Richtig cool!
Wie oft hatte ich es schön das ich für einpaar Module (z.B. Lightbox) auf allen Seiten im Head, Scripte- und Css-Files einbinden musste.
So wie im BE das einbinden von Scripts passiert fand ich das immer schon cool.

So und nun noch einpaar Anmerkungen/Wünsche/Verbesserungen:

---- 1 ----
xmurrix hat geschrieben:Contenido_FePage::getInstance()->addJSCode('alert("foobar");');
Das ist mir zulang. da verliehrt mann/frau zuschnell die übersicht im Code.
Ein Objekt das ganz simpel mit $page oder $fepage benannt ist, wäre sicher von Vorteil.
Contenido_FePage::getInstance()->addJSCode('alert("foobar");');
$page->addJSCode('alert("foobar");');

Und speziell bei dieser Funktion würde ich das so händeln wie im BE mit titel. Um doppele Einbindungen zu vermeiden.
$page->addJSCode('alert', 'alert("foobar");');

---- 2 ----
xmurrix hat geschrieben:[*]Wenn der Modulcode aus einer zentralen Stelle kommt, kann man an dieser Stelle sogar einen Modul Cachingmechanismus implementieren oder sogar auf Modulebene die Ausgabe abhängig vom angemeldeten Frontend-Benutzer machen.
Dann wäre es möglich, dass man das sogar über den Modulcontainer steuert

Code: Alles auswählen

<container id="10" name="MyContentModule" types="Content" mode="fixed" default="" 
cachelifetime="60" cacheoptions="get,post,session" feusergroup="Contenidos"
>Content module</container>
Hier würde ich die Konfigurationen nicht einbauen.
Ich würde empfehlen unter Style > Templates einen Reiter zwischen "Editieren" und "Vorkonfiguration" einzusetzen.
Denn es mach solange sinn solange ich genau ein Modul drin habe, aber bei einem Container für DL-Liste, Ala oder Formular wo sich das Layout nicht ändert aber das Template.

Wunsch: ich hätte dann noch gerne eine Option "Nutze Template-Vorkonfiguration". Das ist sinnvoll für Menüs, Newslisten usw. :D



mfg OliverL

(ein paar Anmerkungen sind 2)
kummer hat geschrieben:... wir zeigen offenbar nicht nur auf, wo der schuh drückt, sondern auch, wie man es lösen kann. ...
erinnert mich an meinen alten Bug-Post hier im Forum ;)
OliverL
Beiträge: 870
Registriert: Do 28. Jun 2007, 09:28
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von OliverL »

xmurrix hat geschrieben:Mag sein, dass das jetzt als eine Art Kopie interpretiert wird, das ist aber nicht so. Jeder, der sich mit dem Core beschäftigt und etwas Ahnung von PHP hat, ist in der Lage, auf solche Ideen zu kommen.
ich sag nur Backend!

mfg oli
kummer
Beiträge: 2423
Registriert: Do 6. Mai 2004, 09:17
Wohnort: Bern, Schweiz
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von kummer »

xmurrix hat geschrieben:Mag sein, dass das jetzt als eine Art Kopie interpretiert wird...
Don't worry, Murat, niemand macht dir einen Vorwurf.
xmurrix hat geschrieben:Jeder, der sich mit dem Core beschäftigt und etwas Ahnung von PHP hat, ist in der Lage, auf solche Ideen zu kommen.
Völllig korrekt. Niemand hat was anderes behauptet. Unklar nur, wieso über Jahre hinweg sowas nie in Contenido auftaucht, wenn doch alles so Nahe liegt.

Wie bereits gesagt, ob kopiert oder nicht, die Idee bleibt gut. Nichts anderes habe ich eingangs gesagt. Und dieser Meinung bin ich nach wie vor.

Nachtrag: Ich hoffe, du verstehtst mich richtig, Murat. Das war auch nie als Vowurf gemeint. Es muss erlaubt sein - sollte es überhaupt so sein -, dass man Gutes aus dem einen nimmt, um etwas anderes zu verbessern. Genau das ist es, was bei Contenido eben nicht geschieht. Immer muss es aus der eigenen Küche sein. Das wär' auch nicht so schlimm, wenn hier ein 3-Sterne-Koch hinter dem Herd stehen würde. Und es mag auch sein, dass 4fb über diese verfügt. Aber die kochen offenbar einen anderen Brei...
aitsu.org :: schnell - flexibel - komfortabel :: Version 2.2.0 (since June 22, 2011) (jetzt mit dual license GPL/kommerziell)
xmurrix
Beiträge: 3215
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Hat sich bedankt: 4 Mal
Danksagung erhalten: 17 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von xmurrix »

Hallo zusammen,

vielen Dank schon mal für die Feedbacks.

Dass mit diesem Beitrag so eine Aufregung entsteht, war in keinster Weise nicht beabsichtigt. Wie auch immer, der Sturm scheint sich gelegt zu haben, ist auch gut so.

Falls ihr am Code interessiert seid, der hängt im Beitrag als Anhang dran. Das zip-Package könnt ihr herunterladen und in eine Contenido-Installation packen.

Grüße
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.
Oldperl
Beiträge: 4316
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Eltmann, Unterfranken, Bayern
Hat sich bedankt: 6 Mal
Danksagung erhalten: 4 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von Oldperl »

xmurrix hat geschrieben:Dass mit diesem Beitrag so eine Aufregung entsteht, war in keinster Weise nicht beabsichtigt.
Ich finds cool 8)
Und es zeigt mal wieder, wie groß so manche Krawatte sein kann, daß man sie erwischt. Oder soll ich Schlips sagen? ;-)

Ich finde die Idee gut, plädiere dafür diesen Ansatz weiter zu verfolgen. Wichtig wäre mir persönlich aber dabei 2 Mechanismen einzubauen.
  1. Ein durchdachtes Caching, da ja das vorhandene mit der con_cache dann eigentlich sinnlos wird.
  2. Eine Funktion zur Vermeidung doppelter JS-Einbindungen und Prüfung von JS-Lib-versionen.
Vielleicht sollte sogar Contenido bestimmte JS-Libs zentral anbieten (können). Hierbei sollte man aber an eine Art Wrapper denken, der diese pro Mandantenverzeichnis zur Verfügung stellt.

Gruß aus Franken

Ortwin
ConLite 3.0.0-dev, alternatives und stabiles Update von Contenido 4.8.x unter PHP 8.x - Download und Repo auf Gitport.de
phpBO Search Advanced - das Suchwort-Plugin für CONTENIDO 4.9
Mein Entwickler-Blog
kummer
Beiträge: 2423
Registriert: Do 6. Mai 2004, 09:17
Wohnort: Bern, Schweiz
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von kummer »

Oldperl hat geschrieben:Und es zeigt mal wieder, wie groß so manche Krawatte sein kann, daß man sie erwischt. Oder soll ich Schlips sagen? ;-)
ist dir denn auf den schlipps getreten worden, ortwin? weil sonst ist niemand da, der sich aufregt...
aitsu.org :: schnell - flexibel - komfortabel :: Version 2.2.0 (since June 22, 2011) (jetzt mit dual license GPL/kommerziell)
Oldperl
Beiträge: 4316
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Eltmann, Unterfranken, Bayern
Hat sich bedankt: 6 Mal
Danksagung erhalten: 4 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von Oldperl »

OT: Mir nicht, ich trag sowas eigentlich nie. :mrgreen:
ConLite 3.0.0-dev, alternatives und stabiles Update von Contenido 4.8.x unter PHP 8.x - Download und Repo auf Gitport.de
phpBO Search Advanced - das Suchwort-Plugin für CONTENIDO 4.9
Mein Entwickler-Blog
xmurrix
Beiträge: 3215
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Hat sich bedankt: 4 Mal
Danksagung erhalten: 17 Mal
Kontaktdaten:

Re: Alternative Codegenerierung für das Frontend

Beitrag von xmurrix »

Oldperl hat geschrieben:...Ich finde die Idee gut, plädiere dafür diesen Ansatz weiter zu verfolgen. Wichtig wäre mir persönlich aber dabei 2 Mechanismen einzubauen.
  1. Ein durchdachtes Caching, da ja das vorhandene mit der con_cache dann eigentlich sinnlos wird.
  2. Eine Funktion zur Vermeidung doppelter JS-Einbindungen und Prüfung von JS-Lib-versionen.
Vielleicht sollte sogar Contenido bestimmte JS-Libs zentral anbieten (können). Hierbei sollte man aber an eine Art Wrapper denken, der diese pro Mandantenverzeichnis zur Verfügung stellt...
Beim Caching könnte man Pear_Cache_Lite verwenden, der ist schon dabei, ist klein und schnell. Allerdings vermisse ich da andere Cache Container, wie z. B. eines für memcached.
Bei kleineren Auftritten mag das Cachen auf dem Dateisystem noch in Ordnung sein - Nehmen die Zugriffe zu, ist memcached & co. die erste Wahl.

Das Cachen von ganzen Seiten kann auch sinnvoll sein, wenn man dies nicht auf einzelne Module anwenden möchte, beides zusammen macht aber keinen Sinn...

Die Vermeidung zum mehrfachen Einfügen von gleichen JS-Codes gehört auf jeden Fall rein.

Wie meinst du das mit dem Prüfen von JS-Lib-Versionen, soll es in Modulen möglich sein, anzugeben, welche JS-Lib und welche Version verwendet werden muss?
Das würde nur dann funktionieren, wenn man eine strikte Konvention einhält, entweder auf dem Dateisystem /js/{library}/{version}/file.js oder per Konfiguration.

Manche Module verwenden Framework A, manche das Framework B, andere wiederum brauchen exakt die Version xy vom Framework B, die aber nicht kompatibel mit einem anderen Modul ist, weil der Version yz vom Framework B will.

Das ist nur so ein mögliches Szenario, muss nicht unbedingt zutreffen, kann aber sein. Vielleicht reicht es aus, wenn man sich um das Einbinden der Sourcen beschränkt. Welches Framework dann letzendlich benutzt wird, kann der Administrator/Entwickler feststlegen. Der muss ja sowieso die Auswahl an Modulen treffen und Validieren ob die sich überhaupt vertragen.

Als Weiterntwicklung von ConMp_FePage (Frontend Page) habe ich mir folgendes gedacht:
- Ein Interface für FePage Generatoren.
- Abstrakte Klasse, das Features für alle FePage Generatoren zur Verfügung stellt
- Jeweils eine Klasse für HTML/XHTML, XML, JSON, Plaintext Generatoren.

Je nach definiertem Template, könnte die richtige Instanz generiert werden, die sich dann um die Ausgabe kümmert, ist nur so eine Idee...

Gruß
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.
Antworten