Hola Mundo - Why should your Joomla based extension speak spanish - JandBeyond 2011
Turbocharging your extension // Joomla
-
Upload
kauselot -
Category
Technology
-
view
2.801 -
download
0
Transcript of Turbocharging your extension // Joomla
![Page 1: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/1.jpg)
TURBOCHARGINGYOUR
EXTENSION
© Klas Berlič & BzZzZ 2010
![Page 2: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/2.jpg)
![Page 3: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/3.jpg)
HOW IT ALL CAME ABOUT// How I got involved with cache //
![Page 4: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/4.jpg)
Quite an amazing storyof a willpower
and turning a failure into a sucess
with contributions to common goodas a final consequence
![Page 5: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/5.jpg)
In 2007 approached by a client to build travel portal for a client.
No clearly defined business strategy, exact site scope was unknown
Joint venture starting with visibility study
![Page 6: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/6.jpg)
NOT AT ALL AN EASY TASK!especially if you look unimportant in the eyes of big players
![Page 7: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/7.jpg)
![Page 8: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/8.jpg)
2Took 2 years
![Page 9: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/9.jpg)
Only after then
development finally began.
![Page 10: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/10.jpg)
TrafficsTibetXML
TrafficsTibet
Cosmo
Ge
rma
n
sup
plie
rs
Manual booking
Routing searchesCombining resultsRouting booking requests
XML search
sta
tic X
ML
ADMINISTRATION
Own inventory management
Bookings management
Website search box
Rendering results
Booking request formPa
lma
XML results
XM
LO
the
r SL
O s
up
plie
rs
Already made airticket booking engine
html integration
Vacations, Hotels, Travel and Airtickets booking management system
temporary bookingover XML
CORE
![Page 11: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/11.jpg)
And then..
![Page 12: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/12.jpg)
Development subcontractor left withonly 10% done
..when we should have been at beta stage
actual plan
![Page 13: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/13.jpg)
If your partners fail, you have to do the job yourself.
// Problem was I knew php only briefly //
![Page 14: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/14.jpg)
3ßLearned php & OOP & brought it to level in 3 months.
// compare that to Joomla 1.6. :))
![Page 15: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/15.jpg)
End result
![Page 16: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/16.jpg)
Probably one of the most complex and technologically advanced sites ever built on Joomla (it is simple..but in a Google way)
![Page 17: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/17.jpg)
Combined power of Joomla php framework
and ExtJS javascript framework used on a presentation layer
![Page 18: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/18.jpg)
TrafficsTibetXMLG
erm
an
sup
plie
rs
Routing searchesCombining resultsRouting booking requests
XML search
Own database
Website search box
Rendering results
Booking requests
XML results
temporary bookingover XML
CORE
De
scrip
tions
& im
ag
es
2
De
scrip
tions
& im
ag
es
1
Results from own database merged with results from multiple different on-demand XML data sources
![Page 19: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/19.jpg)
Initially it took 45-65 seconds to perform a search & render results.
Site badly needed a speed boost.
on average
![Page 20: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/20.jpg)
Speed?
![Page 21: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/21.jpg)
Speed?
// No, nothing illegal :)
![Page 22: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/22.jpg)
![Page 23: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/23.jpg)
Found an an answer in
CACHING
![Page 24: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/24.jpg)
JOOMLA! CACHE// explained //
![Page 25: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/25.jpg)
How simple solutionscan speed up things
10 timesor more
![Page 26: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/26.jpg)
CACHETemporary store an unit of informationto be reused later
// a kind of digital recycling //
![Page 27: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/27.jpg)
Multiple layers of web caching:
�Network (content delivery networks)�Server (proxy servers, load distribution..)�Daemons and interpreters – Apache mod_cache, Php –
opcode caching, Mysql query cache
�Web application (Joomla cache)�Customer (browser cache) - used by Joomla Page cache
plugin
![Page 28: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/28.jpg)
Web application caching
creating temporary static copies of otherwise dynamic pages (or smaller data units).
![Page 29: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/29.jpg)
Typical web site is displaying the same content over and over again
No cache: everything has to be generated for each and every page view
Caching: �store some or all of the information your code generates
in a cache object�serve it when next user requests the same page or
particular piece of information.
![Page 30: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/30.jpg)
JOOMLA! CACHING TYPOLOGY& when to use each of them
![Page 31: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/31.jpg)
page cache componentview cache
module cache
function/callback cache
output cacheraw cache
smallerunits
modules
functions
component
template
![Page 32: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/32.jpg)
PAGE CACHE
![Page 33: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/33.jpg)
Takes snapshots of entire pages including everything - component, modules, plugins and a template.
The widest and the least flexible approach of all caching options.
// enabled by core system plugin -> site administrators choice //
![Page 34: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/34.jpg)
MODULE & COMPONENT VIEW CACHE
![Page 35: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/35.jpg)
A group as they they both create a static copy of complete output of a component or a module
J1.5. Records based on the calling URL
J1.6. Changes
// UNSAFE, DOS //
// more later //
![Page 36: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/36.jpg)
Important difference
module caching can only be set on/off for all instances, can’t be controlled from within the module
// J1.5., changed in J1.6! //
![Page 37: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/37.jpg)
Most widespread cache type, sometimes equaled with J caching in general.
Performs well in the speed terms
Disables any user<->extension<->framework
interaction until a cached copy has expired
Not suitable for any components or modules that react to user actions or render frequently changing content.
![Page 38: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/38.jpg)
Side effect Cached copy includes only modules or components own output -> any external file that is called by using methods like won't get included
Workarounds performed to come around this limitations
Catch22 Workarounds require computing time -> diminish the effect
$document->addStyleSheet()
![Page 39: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/39.jpg)
FUNCTION / CALLBACK CACHE
![Page 40: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/40.jpg)
The first of flexible caching types that enable us to differentiate between various parts of the extension and cache only those parts that are cacheable, while keeping dynamic parts uncached.
![Page 41: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/41.jpg)
Caches results of function calls
Records (cacheID) based on the arguments passed to the function
![Page 42: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/42.jpg)
Often useful to cache model methods and keep views uncached.
Example useModel performing expensive queries or similar operations is run only once to create a larger pool of data which is then further manipulated inside the view (sorting, pagination, calculations etc.)
![Page 43: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/43.jpg)
OUTPUT CACHE
![Page 44: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/44.jpg)
Caches output of some part od the script
Records based on id passed
![Page 45: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/45.jpg)
Basically output buffering with caching
![Page 46: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/46.jpg)
RAW CACHE
![Page 47: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/47.jpg)
Caches any data units
Records based on id passed
![Page 48: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/48.jpg)
Fully controlled by the coder – what, when to store, how to classify stored units (cache id).
Highly useful when we are dealing with finite number of reusable data units
![Page 49: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/49.jpg)
Example useHigh number of possible combinations of relatively small number of units – e.g. products in online store. No point to cache multiple parameter searches, cache each product separately.
Other examplesExpensive queries, remote XML, thumbnails, reusable texts or any reusable data set.
![Page 50: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/50.jpg)
Also useful to pass large amounts of data between different parts of application (e.g. steps in click flow)
Used in Joomla core: list of components, list of modules, menu tree, available languages, user groups, html renderers etc.
![Page 51: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/51.jpg)
CASE STUDYtravel booking engine
![Page 52: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/52.jpg)
PROBLEM
It took on average 45 to 65 seconds to display a search result
![Page 53: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/53.jpg)
DIAGNOSIS
Largest portion of time spent on remote XML requests, waiting for and receiving replies.
Other two performance hogs were resizing images and internal database queries.
2nd and other pages of paginated results displayed instantly
![Page 54: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/54.jpg)
TrafficsTibetXMLG
erm
an
sup
plie
rs
Routing searchesCombining resultsRouting booking requests
XML search
Own database
Website search box
Rendering results
Booking requests
XML results
temporary bookingover XML
CORE
De
scrip
tions
& im
ag
es
2
De
scrip
tions
& im
ag
es
1
Each result from badly designed primary XML paired with description and image that come from separate XML sources (one by one)
![Page 55: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/55.jpg)
TrafficsTibetXMLG
erm
an
sup
plie
rs
Routing searchesCombining resultsRouting booking requests
XML search
Own database
Website search box
Rendering results
Booking requests
XML results
temporary bookingover XML
CORE
De
scrip
tions
& im
ag
es
2
De
scrip
tions
& im
ag
es
1
SLOW
![Page 56: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/56.jpg)
SOLUTIONCache data on multiple levels:
�Cache pages that were fully rendered - a lot of users search with default parameters or click lastminute links, most just check one or two pages of paginated results
�Cache XML queries (with longer lifetime). Pass data from short results to detail pages
�Long-term caching of images and descriptions -> most important one
![Page 57: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/57.jpg)
ALSO..
Add more indexes to Mysql tables
Query and render images and descriptions per page: primary source queried once, secondary separately for each subpage (pagination).
![Page 58: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/58.jpg)
RESULT
Site runs 10 times fasterAverage first page loads in 5-6 secondsSubpages (paginated) load in 0.5 - 1 seconds
Those timings further drop dramaticaly (50% or more) on peak hours, when most popular searches are returned from the cache.
The bigger number of users on a site, the faster it goes.
// within the hosting limits //
![Page 59: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/59.jpg)
JOOMLA! 1.6. CACHE CHANGES// firsthand //
![Page 60: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/60.jpg)
A very long story made short:
"It finally works"
![Page 61: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/61.jpg)
FRAMEWORK LEVEL
Almost everyhing was redone under the hood.
Cache library has been completely refactored.
![Page 62: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/62.jpg)
Most important framework changes
Cache handlers are now known as cache controllers (page, view, output, callback)
Parent JCacheController was added - among other things it controls raw get and store calls.
![Page 63: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/63.jpg)
New cachelite and wincache storage handlers (drivers). File cache handler heavily optimised
All other handlers fixed with missing functions (gc, clean) added, their code cleaned and tested and should now be working properly.
Semaphore locking was added for reliability and improved performance
![Page 64: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/64.jpg)
Changed component view caching (replaced unsafe cacheID creation method)
Module cache completely reconceptualized
![Page 65: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/65.jpg)
CMS FRAMEWORK LEVEL CHANGES
Caching implemented in all components and modules that can potentially gain from using it
Caching added to some most expensive and frequent framework calls:JComponentHelper::_load(), JModuleHelper::_load(), JMenuSite::load(), JDocumentHTML::getBuffer()..
![Page 66: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/66.jpg)
USER LEVEL FUNCTIONAL CHANGES
Cache administration (Clean cache, Purge cache) now works with all storage handlers
New standalone garbage collect script to be run from a crontab added
libraries/joomla/utilities/garbagecron.php
![Page 67: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/67.jpg)
API changes// and other changes important for developers //
![Page 68: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/68.jpg)
COMPONENT VIEW CACHE
Takes an array of url parameters and their types to create
Cacheid.
A replacement for a previous unsafe way which took the whole URL and so opened the doors for DOS attacks via random parameters/values added to request
// Old cacheid created from URL retained for backwards compatibility if there are no $safeurlparams (to be removed in 1.7) //
![Page 69: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/69.jpg)
Com_contact controler usage example:
$safeurlparams = array('id'=>'INT', 'catid'=>'INT', 'limit'=>'INT', 'limitstart'=>'INT', 'filter_order'=>'CMD', 'filter_order_Dir'=>'CMD’, 'lang'=>'CMD');
parent::display($cachable,$safeurlparams);
![Page 70: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/70.jpg)
MODULE CACHE
5 different modes of operation, 3 of them are to be set from module XML file, while 2 are meant to be used from within the module itself.
Default is backwards compatible oldstatic mode that requires no changes to a module.
![Page 71: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/71.jpg)
MODES TO BE SET IN XML
Static - one cache file for all pages with the same module parameters
Oldstatic - 1.5. definition of module caching, one cache file for all pages with the same module id and user aid. Default for backwards compatibility
Itemid - changes on itemid change
![Page 72: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/72.jpg)
In addition to cache field that was required in 1.5 there is
now new hidden field called cachemode that sets any of the above modes.
<field name="cachemode" type="hidden" default="static"><option value="static"></option>
![Page 73: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/73.jpg)
MODES TO BE CALLED FROM INSIDE THE MODULE:
Safeuri - id is created from URL params array, as in component view cache
Id - module sets own cache id's
To use this modes rename 'cache' field in xml to
'owncache' field and call from within JModuleHelper::ModuleCache
// actually a shortcut to cache callback to avoid code duplication in every module //
![Page 74: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/74.jpg)
An example that uses safeuri mode and replaces uncached $list = modRelatedItemsHelper::getList($params) :
$cacheparams->modeparams = array('id'=>'int','Itemid'=>'int');$cacheparams->methodparams = $params;$cacheparams->method = 'getList';$cacheparams->class = 'modRelatedItemsHelper';$cacheparams->cachemode = 'safeuri';$cacheparams = new stdClass;
$list = JModuleHelper::ModuleCache ($module, $params, $cacheparams);
![Page 75: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/75.jpg)
RAW CACHE
Raw cache get and store are easily accesed by passing '' (empty string) as cache controller to
Data is auto serialized / deserialized
Locking & unlocking are performed automaticaly
JFactory::getCache
![Page 76: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/76.jpg)
AND HERE THE STORY ENDS// ok..a little more //
![Page 77: Turbocharging your extension // Joomla](https://reader033.fdocuments.net/reader033/viewer/2022060108/555099b0b4c90590208b47d7/html5/thumbnails/77.jpg)
If you still remember how it all started..
I hope you like where it ended.// tried to do my best //