<marcimat>you have to puts initialisations in your php.ini or in your mes_options.php to see all errors : <marcimat>error_reporting(E_ALL^E_NOTICE); <marcimat>ini_set ("display_errors", "On"); <marcimat>define('SPIP_ERREUR_REPORT',E_ALL^E_NOTICE); <marcimat>define('SPIP_ERREUR_REPORT_INCLUDE_PLUGINS',E_ALL^E_NOTICE); <marcimat>you can also install the php xdebug librairie
The documentation of {doublons} explains how this criterion, like {unique}, enables you to exclude some elements from the results of a query.
However, {doublons} can do much more than that : like {unique}, it stores in an array the results from successive loops. But, with {doublons}, this array can be re-used later in another loop, thanks to a special criterion : {!doublons} (named "anti-doublons")
Example : BOUCLE2 displays in a chronological order the titles of the articles that are either tagged with the keyword number 2, OR that has been writen by the author number 1.
This commit introduced a functionality that is used everywhere, especially with CVT forms :
Every functions xxx_yyy_zzz() can be defined in a unique file xxx/yyy.php.
Application in CVT : formulaires_yyy_charger(), formulaires_yyy_verifier(), and formulaires_yyy_traiter() can be defined in a unique file formulaires/yyy.php (which uses the template formulaires/yyy.html)
What I've discovered is that the functions can be independently overwritten by the same function defined in xxx/yyy/zzz.php !
Used with the function search path, this can be really usefull when you want to override a general plugin (such as Agenda).
Models are not restricted to shortcuts within the text of articles. They can also be called from within a template by using the tag #MODELE{model} or [(#MODELE{model}{p1=thing,p2=whatsit}{p3=etc}|filter...)]. But this is less new, because it is equivalent to a (static) inclusion of another template (already made possible by the tag #INCLURE).
However it was quite buggy and not really homogeneous. For ex. a few abnormal differences were found between #MODELE{my_model, ..} and #INCLURE(fond=modeles/my_model){..}.
Now, the codes with parenteses and/or several braces delimited blocks are considered as deprecated : You should write instead #INCLURE{a,b,c} and #MODELE{a,b,c}. The old syntax is still accepted.
Parentheses, brakets and filters can also be used to display elements only where #INCLURE returns a content : Ex. :
[Lastest articles in the feed #FEED_TITLE :
<ul>
(#INCLURE{fond=rss-read, url=#FEED_URL, date=#DATE}|extract_post_titles)
</ul>
]
Edit : The first argument of an INCLURE can be calculated. The common syntax indicates that filters require parentheses. But, for reason of compatibility, the following simplified syntax is accepted :
The SPIP template language has two constructions: loops (which determine the objects to be “output”) and tags (which actually output particular values). The reasonably simple syntax of tags — most look like ”#THE_TAG” — belies their power and flexibility and the ease with which we can use them to extend SPIP with additional features and integrate it with other PHP-based packages.
It's post is really well documented. I love the way Thomas precisely explains how all this stuff really works !
The SPIP team is really active and improve it regularly. Here is a list of new functions that can help you develop plugins :
supprimer_objets_lies ( array($type, $id) ) : Type : pipeline Removes the objects of plugins linked to core objects (used when these core objects are deleted)
optimiser_sansref ($table, $id, $sel) : This pipeline is called in genie/optimiser.php It completes the removal process of orphelin objects. (dead links between tables, that results from the suppression of articles, authors, etc)
example :
/**
* Optimizes the database by removing orphelins forums
*
* @param int $n
* @return int
*/
function forum_optimiser_base_disparus ($n){
# detect forums that are linked to an id_rubrique that doesn't exist anymore
$res = sql_select("forum.id_forum AS id",
"spip_forum AS forum
LEFT JOIN spip_rubriques AS rubriques
ON forum.id_rubrique=rubriques.id_rubrique",
"rubriques.id_rubrique IS NULL
AND forum.id_rubrique>0");
$n+= optimiser_sansref ('spip_forum', 'id_forum', $res);
...
return $n;
}
filtre_lien_ou_expose ($url, $text, $on=false, $class="", $title="", $rel="") : This filter creates a link or a tag <strong class='on'> note : class, title and rel are optional usage ; [(#URL|lien_ou_expose{texte,condition_selection_on,class,title,rel})] example : [(#GET{self}|parametre_url{type,public}|lien_ou_expose{<:onglet_messages_publics:>,#ENV{type,public}|=={public}})]
filtre_balise_img ($img, $alt="", $class="") : This filter creates an <img> tag usage : [(#CHEMIN{monimage.png}|balise_img)] (the opposite of filtre_fichier())
filtre_icone ($link, $text, $template_name, $align="", $function="", $class="") : This filter is a shortcut for creating icons in the templates of the private area usage : [(#URL|icone{text,template_name,align,function,class})]
test_plugin_actif ('prefix_of_the_plugin') : This function tests if a plugin is activated and returns a boolean.
This is not a fresh news, but I've just read a mail that Pat sent on SPIP-ZONE.
It give the complete records of the most used plugins, at the begining of October. It have been calculated with the websites declared on spip.net and some other sites.
A little changelog for SPIP2.0 : - Translation in asturiano, Burmese, Khmer (Kampuchean), Indonesian, Swedish - Unified private interface using AJAX - Programming interface for SQL Server (MySQL, Postgres, SQLite) - New forms for use on the site in public and private area - Improved interface for documents and forums (documents joints possible) - Access to several databases from a single skeleton - Models and pagination in AJAX by simply adding a new criterion - Hierarchical URLs (like: http://www.example.com/sector/section1/subsection2/article_name) - Automatic compaction of CSS and javascript files - Amelioration of the filter system and automatic installer - And more...
Modifications between 1.9.2e of 13 September 2008 (svn [12624]) and 1.9.2f of 10 December 2008 (svn [13443]):
- Correction of a spelling error in the language list - Correction of the criteria {par multi titre} in MySQL 5 and utf-8 (alphabetical sorting correct even with accented characters) - Correction of the RSS of del.icio.us - Unification of the calculation of the date of publication (now in php) in case of time lag between php and sql - Optimization of SQL (use of the MySQL requests cache) - Protection of redirects urls (not < or ") - Corrections of Ukrainian - Fix of a security problem
SPIP is fantastic because it can automatically merge and compress the css and javascript files.
But sometimes it can crash our scripts (especially if some parameters are stored inside). To solve it, just change, in your template, the type of your script. Instead of "text/javascript" use "application/javascript"
Until now, it was impossible if the arguments where passed in the url.
[12798], however, made it possible with a POST : The 4th arg of generer_url_action forces the production of an URL executable in the public area, even if it should use a POST (it's also the case for redirige_par_entete).
With this commit, an additional boolean parameter, $public, has been added to some functions to make them work in the public area : generer_form_action, and securiser_action_auteur
Howto detect if a plugin is activated : 1. PHP : if (defined('_DIR_PLUGIN_XXX')){ /* My action for this plugin */ } 2. SPIP1.9.2 : [(#EVAL{DIR_PLUGIN_PREFIX}|?{' ',”}) My action for this plugin ] 3. SPIP2.0 : [(#PLUGIN{XXX}) My action for this plugin ]
Howto do not display the admin toolbar in the public area : Put at the first line (with #CACHE) : [(#HTTP_HEADER{Content-type: text/html[; charset=(#CHARSET)]})]
Howto replace any text with an image : [(#REM|=={''}|?{My beautifull text}|image_typo{police=Victor.ttf,taille=14,largeur=150})]
Howto directly link an element : <a href="#URL_ARTICLE{54}">Link</a>
Howto get the articles that are tagged with a keyword : Instead of using the keword id, you can directly refere to it's value : <BOUCLE(ARTICLES){titre_mot=we love America}>#TITRE</BOUCLE>
And you : Which are the best code tips that you use ?
Don't use generer_url_{article, auteur, breve, mot, rubique, site} : these functions are obsolete, and should be replaced by the unique function generer_url_entite($id='', $entity='', $args='', $anchor='', private='', $type='')
For example, generer_url_entite($id, 'article', $arg, $anchor) replaces generer_url_article($id, $arg, $anchor).
But what makes the difference ?
The 5th argument determinates if the generated url is private ou not, whatever the context (if it's for ex. called from a filter or a plugin in the private area).
But more important, the 6th argument specifies the url type you want to produce : it overwrites the global variable type_urls ! Now you can mix every form of url (arbo, html, libres, page, propres, propres2, propres_qs, and standard) !
"New" filter |image_format{} : it saves the image in the chosen format, and keeps its transparency ; in fact it's a shortcut for the "transparency" option that has just added ARNO* ([12638]) to the filter |image_aplatir{}
Example : in inc-head.html, |image_format{ico} for the favicon
Note : image_aplatir corresponds to the following definition :
function image_aplatir($im, $format='jpg', $color='000000', $quality=NULL, $transparency=false)
$im : the image itself $format : the format to generate $color : the background color that normaly replaces the alpha layout $quality : see below $transparency : Should the result image keep the transparency of the orginal, when possible (gif, png, ico)
image_aplatir normaly replaces the alpha layout by a specified color ($color). It can be used to change the format or the compression of an image. For such usage, it's also possible to maintain the transparency with the last parameter.
$quality is used like this : - For the jpg format, it correspond to the compression level (85 by default) - for the gif format, it correspond to the number of colors of the palette (128 by default) - for png pictures, $quality corresponds to the number of colors of the palette or, if equal to 0, to a truecolor image(default value)
SPIP 2.0 supports favicons (.ico extension) : it integrates a part of phpThumb, by James Heinrich (available at http://phpthumb.sourceforge.net ).
Application : the favicon can be dynamically calculated and is compatible with IE6 and other modern browsers like Firefox The filter to use : |image_aplatir{ico}
With this commit, some keyword groups can be displayed/hidden in specific sections. The customization can be done with autoriser_xxx_editermots($action,$what,$id,$who,$opts. $opts contains the id of the concerned keyword group, and also the fields of this group that can be displayed. By default, the function only checks if the author is authorized to this group.
So it works like this : - The action is the same url (and the form can display errors). - The form initially contains several hidden values that will make the submit action more secure. - When the focus is set to the password field, the form verifies that the encryption parameters are OK, and indicates it with a brown padlock. - Before been submitted, the password is encrypted into two md5+salt values, and the non-encrypted password field is erased : Therefore the password is never directly sent to the server, so it can't be catched by a bad guy. That makes the login form really secure ! - Finally, the server calculates the md5+salt values of the password in database. It compares these values to the encrypted received values. If the values match, the password that has been submitted is correct. Elsewhere it's bad and SPIP returns to the login form with an error.
3 new functions enable to create and delete views for PG, SQlite and MySQL :
sql_get_select() : same arguments as sql_select() but returns the query without evaluating it
sql_create_view($view_name, $select_request) : creates the view $view_name for the select request $select_request.
sql_drop_view($view_name) : drops the view.
/!\ Warning ! Yous must give an explicit name to every field prefixed with a table name or an alias. Elsewhere SQLite won't be able to read the view (which contains 'a.titre' instead of 'titre').
SQL views are known to be used like tables. They enable to : - mask the schema complexity ( -> simplification of queries) - give access to a limited number of fields ( -> security) - manipulate calculated fields (sum(), max(), avg(), ..)
Now you can avoid writing complexe loops by using views :
Example :
mysql> create view v AS
SELECT a.titre,a.id_article,b.id_rubrique,b.titre AS titre_rub
FROM spip_articles AS a
LEFT JOIN spip_rubriques AS b ON(a.id_rubrique=b.id_rubrique)
WHERE b.titre REGEXP '^A'
ORDER BY a.titre DESC;
Note that the {doublons} are transmitted from the main template to the included one. But it's not possible to transmit the information from the included template : Especially <INCLURE /> isn't always calculated at the same time that the main template - For this reason and to keep a coherent behavior, #INCLURE keeps the same restriction for {doublons}
During the normal execution of several commands, call-outs are made to optional scripts that allow a developer to add functionality or checking. Typically, the hooks allow for a command to change the values of function arguments before any other call, and allow for a post-processing treatment that will always change the function result.
Exemple :
function prefix_treatment($flow) {
/* add something to the flow */
$flow .= 'This is some html code';
return $flow;
}
plugin.xml defines the implemented hooks with a list of <pipeline> tags:
#ARRAY{key1,value1,key2,value2...} allows the creation of a variable length table (useful for constructing a table for a #SET and/or for use with a dynamic "IN" criterion )
Short but an exemple should be helpfull..
Here is an exemple extracted from the plugin SpipBB
#ARRAY{#COMPTEUR_BOUCLE,#ID_AUTEUR} creates an array containing the author's id at an index that isn't used yet. The standard PHP function array_merge() finally does it's job : this value is now stored on the last index of the array 'modos'.
Another loop completes this array with the other authors of articles that are in the same section.
Note that the PHP function is used as a filter : it's possible because it's first argument is the array to manipulate.
Of course all this can be done with PHP code inside the template. The advantage of using the tag #ARRAY is that your template is better managed by the cache.
With the revision [11350], any custom field can directly be used in templates with the tags #FOO and #EDIT{foo} (with the plugin "crayons" [fr]) You don't have to change inc/modifier or specify the structure of the table : the core directly manages them.
However the private interface actually doesn't integrate these fields. You have to custom it with hooks.
The value of any field 'foo' can be displayed in your templates with #FOO -- Even if this is a field of the 'official' tables. Much more, this value can be edited in the public area with an inline content editor (actually it's still not possible in the private area) :
sql_showtable() is used to describe the fields (that's better than the corresponding php descriptor in tables_principales, etc..)
inc/modifier now uses a list of private fields (instead of a fixed list of public fields)
includes the template and ajaxifies all it's links.
By default, the javascript variable "ajaxbloc_selecteur" is used. It transforms into ajax call each link that corresponds to the jquery selector '.pagination a,a.ajax'.
An ajax call refreshes the template's result by restauring it's #ENV, plus some parameters in the url. When a refresh occurs, the bloc's opacity is changed to 50% and it's class to 'loading' (this div is automatically created) The loaded part is cached on the browser with javascript. It also can be preloaded by adding the class 'preload' to the corresponding links.
Combined with a filter like |parametre_url, you can do whatever you want :
For example :
<a href="#URL_PAGE{identifiants,focus=nom_inscription}&mode=(#URL_SITE_SPIP|tester_config{1comite})" (in dist/login.html) that returns <a href="spip.php?page=identifiants&focus=nom_inscription&mode=.."
It should possible to write #URL_ECRIRE{forum_envoi,statut=prive&id=363&script=articles#formulaire}
but you can also use this : [(#URL_PAGE{my_backend}|parametre_url{id_mot,#ID_MOT}|parametre_url{id_rubrique,#_:ID_RUBRIQUE})] to generate <a href="spip.php?page=my_backend&id_mot=32&id_rubrique&..
when a title of an article is changed, the url isn't automatically recalculated.
It's interresting if you don't want to lost backlinks, but it can be disturbing because the url may not correspond to the content of the linked page.
Here is the trick : Just clic on the link 'See online' when you display the article inside the private area. It will not only clear the cached content for this page, but it will also force the url to be recalculated according to the title field.
1.9.2d is a bug-fix update. It is advisable to upgrade to this version which should not have any visible impact for the visitors to your site if you are already using a version 1.9.2 (a,b or c). You can download this version at http://www.spip.net/en_article3103.html.
The changes are:
For authors and admins:
correction of an inconsistency in the managing of the date of attached documents (date/time on creation, but only date thereafter);
correction of a bug on the sections menu which hid some of them (bug #1113);
avoid javascript error when loading a page and the mouse was moved too quickly;
the graphic configuration and site address are no longer overwritten when restoring a backup, as they are linked to the server;
the correct display of successive screenshots in the statistics;
updated Indonesian translation;
correction of a bug on the permissions on modification of sites syndicated by restricted admins;
correction of several bugs to do with the permissions on logos;
correction of an SQL bug on the section selector which made it unusable on big sites (sections are now sorted {par num titre, titre};
correction of a bug which could allow a restricted admin to move a published article to a section of which he/she is not an administrator.
For developers of plugins:
$GLOBALS['_INC_PUBLIC'] replaces the constant _INC_PUBLIC.
It is incremented in each template inclusion. This is used in the plugin "balise_session" that reproduces a new session mechanism introduced in the development version of SPIP: Tipically, if you want to create templates which results depend on the user, you actually needn't include session.php: a specific tag, #SESSION, automatically handles the cleaning process of the cached files -- even in statical includes like models --
Correction of the cache cleaning process in CRON (it sometimes failed when a bot visited the site)
url_de_base() can now be used in mes_options.php
This release Fixes a missing inclusion which could make the function autoriser_voir_dist() crash.
recuperer_page() properly takes care of https uri (If php was compiled with the support of ssl)
Thanks Paolo for this translation of the original announcement by Cédric.
When the cron doesn't manage to empty correctly the cache, the site crashes rapidly. The only solution then is to empty completly the cache directory.
It's what does this commit, but it's a poor patch with a huge side effect : the cache delay specified in a template isn't really taken into account because the cached file is erased rapidly
There is no doubt that a better solution will come soon
note : Cache explosion was also partially corrected in :