Translations
Info
All page names need to be in English.
en da  de  fr  it  ja  km  nl  ru  zh

MVC Framework/Extending Extensions

From TYPO3Wiki
Jump to: navigation, search
This page belongs to the Extension coordination team (category ECT)
This page belongs to the MVC Framework aka lib/div project (category Project)

Main editor: --Daniel Brüßler 10:39, 8 August 2007 (CEST)

notice - Note

This page is currently just a collection of texts belonging to this topic. My "vision" is that we can have in TER
  • a little number of base extensions what can be extended easily
  • many "addon" extensions what provide several features


Examples

ECT-libDiv-extendingExtensions.png
(made with VYM - view your mind, Ubuntu)

add todo-list:

Background info

The problem of tslib_pibase

Analysis

Looking into TER you may get the impression that the quantity of extensions is is getting up while the quality is getting down. Instead of adding new features to existing extensions, people recode similar functionality in alternating combinations of features, to come to the product they personally need. Feature complete tools, that would satisfy the user is regularly missing.

Complaining doesn't help. The phenomenon reveals an underlying structural problem of the TER as it is. Adding new features to existing extensions isn't as simple as it should be. Let's try to solve this quest.

Quest

Get less extensions with more features in TER by successful collaboration. Show up a smart way to reach this, a way that doesn't require much alteration of the given technical infrastructure, a way that doesn't need much alteration of the peoples behavior.

Idea

People are willing to cooperate, else they wouldn't contribute hundreds of extensions to the TYPO3 core. To contribute to an existing extension a defined, open API to that extension is required. That is just like the core has an defined, open API for extensions. So we need a few extensions that act themselves as centers for other extensions, that we could call add-ons.

If the core of TYPO3 is the sun, then this extensions are the planets circling the sun, while little moons circling the planets as add-ons. So let's postulate a few extensions as peripheral centers of the TYPO3 project that each provide a defined API for add-ons.

Gain

This simplifies it for the user, to contribute a single new feature for a given extension in form of an add-on and enables him to flexibly combine given add-ons to match his requirements precisely. The current habit to recode existing features in new combinations becomes unnecessary. TER becomes a better place.

Team-provided extensions

applications

libraries

documentation

Types of glue

  • TypoScript actions - example: efaq
  • hooks - example: tt_products
  • services - example: cal
  • plugins - example: dr_wiki
  • HTML-templates (the "skin" of an extension can be changed by TypoScript)

Comparison and Brainstorming

  • why "easy": many EXT are created by newbee-devs. The quality is better, when the entry-barrier is not too high
  • "complex" means: addons, what can register "before", "instead of" or "after" an existing entry point
variant configuration changeable by TS easy for EXT-authors easy to add simple addon-features to an EXT easy to add complex addon-features to an EXT easy to find bugs implementation --
by Hooks no yes, very easy yes no yes could go into current controller --
like COA yes yes yes no, because of "traffic-jam"-problem when two addon-indices are too near not really easy needs special controller --
by groups yes - very flexible no, because of flexibility no, because of flexibility yes, because the concept is very handy not really easy needs special controller --
by Services no not really easy yes yes, but not really easy no, because services for extension X can be registered in several other extensions could go into current controller --

Extensibility - by Hooks

(see article)

The main difference between common MVC frameworks and the T3 FE api is, that those frameworks are typically used to create one big application in contrast to several small T3 extensions which may interract with each other. So one big question is how to solve the problem of interaction picking up the above named concepts.

One way would be to add a generall hook concept to the dispatcher and all prototype classes (model, controller, view). This could be done as follows (ext_localconf or similar):

$GLOBALS["hooks"]["myext"]["someController"]["someAction"]["before"][]=whatever
$GLOBALS["hooks"]["myext"]["someController"]["someAction"]["after"][]=whatever
$GLOBALS["hooks"]["myext"]["someController"]["someAction"]["overwrite"]=whatever

This would allow an extension to hook in at every place without having explicit hooksupport within the orignal extension.

Hook execution decision could be done within __call() of the particular prototype class. Meta code.

class model {
 function __call(...) {
  //travers Hook array/hook decision 
 }
}


--Pulponair 13:38, 26 January 2007 (CET)

Extensibility - like COA

As we work with a chain of SPL objects, how about using TS to define this stack?

xyAction = ACTION
xyAction {

100 = SPL

       100.class = tx_myext_classX
       100.configurations {
         ...
       }

200 = SPL

       200.class = tx_myext_classY
       200.configurations {
         ...
       }
       ....
}

--Elmar Hinz

Extensibility - groups

definition

Define ACTION as group of ACTIONITEMs without inner sorting. Define ACTIONITEM as object like this:

ACTIONITEM {
  name = <ident>
  inputformat = {txt,pdf,db,doc,...}
  outputformat = {txt,pdf,db,doc,...}
  before = <ident> || NULL
  after = <ident> || NULL
  priority = -<int> ... 0 ... <int>
}

define DBACTIONITEM to be inputformat= && outputformat='db' On execution sort the ACTIONITEMS in a chain so that

a(n+1).inputformat == a(n).outputformat && pos(a.before) > pos(a[name]) && pos(a.after) < pos(a[name]) && a(n+1).priority > a(n).priority.

Process this chain.

--Christian Welzel

example

xyAction = ACTION
xyAction {
       ....
       classX1 = ACTIONITEM
       classX1.inputformat =
       classX1.outputformat = db
       classX1.obj = SPL
       classX1.obj.class = tx_myext_classX
       classX1.obj.configurations {
         ...
       }
       classX2 = ACTIONITEM
       classX2.inputformat = list
       classX2.outputformat = html
       classX2.obj = SPL
       classX2.obj.class = tx_myext_classX
       classX2.obj.configurations {
         ...
       }
       classY = ACTIONITEM
       classY.inputformat = db
       classY.outputformat = list
       classY.obj = SPL
       classY.obj.class = tx_myext_classY
       classY.obj.configurations {
         ...
       }
       classY2 = ACTIONITEM
       classY2.inputformat = list
       classY2.outputformat = list
       classY2.obj = SPL
       classY2.obj.class = tx_myext_classY
       classY2.obj.configurations {
         ...
       }
       ....
}

Execution order: classX1 > classY > classY2 > classX2

Another advantage: works with current TS parser!

--Christian Welzel

Extensibility - by Services

(see TYPO3 Services)


As example I was thinking of maybe a rendering-service. This way a developer could simply override the default php-template system in general with his preferred one and doesn't have to write extension_addons for every extension from TER he uses? Don't know if this makes sense at all - but sounds at least good to me.
--Franz Koch in newsgroup



The main reason for doing this with services (they are part of model) is to be flexible about Data storage. So it's very easy to install a service that overwrites a method reading the data.

May be a diagram of cal is helpful to understand the architecture: http://www.sk-typo3.de/cal-Funktionsdiagramm.273.0.html
--Steffen



The third parameter of t3lib_div::makeInstanceService() allows to pass a list of service keys that should be ignored. This way you can walk through all available services of a type by passing the already used service keys.

 // use 'auth' service to find the user
 // first found user will be used

 $serviceChain='';

 while (is_object($serviceObj = t3lib_div::makeInstanceService('auth', $subType, $serviceChain))) {

   $serviceChain.=','.$serviceObj->getServiceKey();

   if ($tempuser=$serviceObj->getUser($info, $subType, $this)) {

     // user found, just stop to search for more
     break;

   }

 }

--from Rene Fritz' TYPO3 Services-Doku

Standards for Extending Extensions

See ECT/Coding_Guidelines#Standards for Extending Extensions.