Skip to the content
Documentation

Help center

Help for Developers

Build on it: extensions, templates, settings, the APIs, the command line and upgrades.

5997 pages

Start here

Read these pages in this order.

  1. Develop with Git: grow from user to developer The recommended way to build websites with Exponential. Install the kernel and every se7enxweb extension as...
  2. Extension development: the book (start here) A complete book on growing from user to builder, extension developer and theme developer with Exponential:...
  3. Add a database table A migration that creates a table of the site's own on every engine from a share/db_schema.dba definition, w...
  4. AI, agents and agentic: start here The landing page for people who use AI with Exponential and for people who build agents and agentic workflo...
  5. Ecosystem: start here The landing page for the Exponential Ecosystem - the greater Exponential world within the PHP stack, its us...
  6. Integrators: start here The landing page for system integrators and integration developers who connect Exponential with CRM, ERP, P...

Good to know

  • Migrations

    The start of everything about migrations in Exponential 6.0.15 - schema and content changes written once as files under version control and applied to every installation of a site in the same order, with a caption…

  • Migrations: a first PHP migration, step by step

    In this tutorial you write two PHP migrations for a site: one creates a table exp_news_note with a first row, the other publishes a folder "News" below the content root and notes it in the table. You check them, look at…

  • Add a database table

    A migration that creates a table of the site's own on every engine from a share/db_schema.dba definition, writes a first row, and drops it again in down() - with the dry run, the run, the checks and the rollback.

  • Testing migrations: check, simulate, diff and CI

    Four layers of tests for migrations - the lint without a database, the dry run, the simulation with a diff on PostgreSQL or SQLite, and a PHPUnit test on a throwaway SQLite database - and how to run them in CI.

  • Deploying with migrations: CI/CD and GitHub Actions

    Run migrations as part of every deploy - the order of the steps, a complete GitHub Actions workflow that checks pull requests and deploys over SSH, the exit codes a pipeline acts on, the installation lock, and runs…

  • Team workflow with git: branches, conflicts and order

    How several developers write migrations on branches without stepping on each other - timestamps and order, requires for real dependencies, two migrations with the same timestamp, rebasing, renaming only before a merge…

Search by topic

Each button lists the pages of one topic for Developers.

What changed in the source code most recently: the main branch of se7enxweb/exponential, read from its public feed by this server.

Hide merge commits

  1. Updated: A code block keeps its line breaks, tabs and indentation whe… (opens in a new window) ·
    Message
    Updated: A code block keeps its line breaks, tabs and indentation when the online editor saves it
    
    eZXMLInputParser::process() removes every line break of HTML input (they are no content in HTML) and makes
    every tab a space, before it parses. Inside , which becomes , the white space is the content:
    every code block was stored as one long line, its indentation left as runs of spaces in the middle of it.
    This hit every block an editor saved in the online editor and every page an import wrote through it.
    
    preformattedWhitespace() now writes the line breaks of a  block (LF, CRLF, CR) as , which the
    literal handler stores as line breaks, and its tabs as 	, which stay tabs. The line break right after the
    opening tag is no content, as in HTML. Input without  is unchanged, and text outside code blocks loses
    its line breaks as before.
    
    Tests without a database: lines and indentation, empty lines, tabs, leading spaces, CRLF and CR,  from
    the editor, entities, the block's class, text outside code blocks, and a block opened in the editor and
    saved again unchanged.
    6bb303b456
  2. Updated: cond gives its last parameter as given without template comp… (opens in a new window) ·
    Message
    Updated: cond gives its last parameter as given without template compilation, also an empty array, hash, 0, '' or false
    
    The processing interpreter took the value for "no condition holds" only when it was true, so cond( ..., array() )
    gave no value with TemplateCompile=disabled, while a compiled template gave the empty list. The missing value
    contains everything, which put every link of the admin4 left menu and the Setup overview into the first group
    without GroupLinks_[] (pull request #357). The same form is used in about 45 places of the admin, admin4
    and standard designs; they now get the empty value in both modes.
    
    - The parity test renders cond with an empty array, empty hash, 0, false, an empty string and later clauses,
      processed and compiled, with literal and variable input (12 of its new cases failed processed before).
    - The template language page (English and German) describes cond's last parameter; the 6.0.15 changelog names
      the menu fix and the engine change.
    f845c2ca02
  3. 98d4a81d94
  4. Updated: The translation wave pages count the German example descript… (opens in a new window) ·
    Message
    Updated: The translation wave pages count the German example descriptions added today
    
    The German description catalogue of the generated examples grew by 131
    entries, so the help tables now hold 117233 words instead of 112725; the
    English and German translation wave pages are regenerated with
    ./console exp:i18n waves, as their test asks.
    7666a06bd7
  5. Renamed: The help pages' script lives in design/standard, so the doc … (opens in a new window) ·
    Message
    Renamed: The help pages' script lives in design/standard, so the doc site's filter and search work again
    
    The contents page's filter box, the dashboard's instant search, the lazy
    folders of the viewer's tree, the copy and print buttons and the reading
    position all come from exphelp.js, which the help templates load with
    ezscript_require. The script existed only in design/admin and
    design/admin4, so on a front-end siteaccess such as the doc site
    (designs doc/doc2025, then standard) the packer found nothing and left
    it out without a word: the filter stayed hidden and typing in a search
    field did nothing. Signed in to the admin, where the file was found,
    everything worked.
    
    The two identical copies become one, design/standard/javascript/exphelp.js,
    which every design finds through the standard fallback. The tests read
    that copy and now fail if a design or an extension gets its own again;
    the test map and the file manifest follow the move.
    2a7ee17b6e
  6. Updated: German design pattern pages link to the German area pages (opens in a new window) ·
    Message
    Updated: German design pattern pages link to the German area pages
    
    The German pattern catalogue linked 104 times to area-*.md, chain.md and
    fetch-function.md, the English file names, which do not exist below
    doc/ger-de/standards/muster/ (the German pages are bereich-*.md, kette.md
    and fetch-funktion.md). Each link now names the German file the path map
    gives for that page, so the German link check no longer reports them.
    de911a1fd3
  7. Updated: The German generated examples translate every source descrip… (opens in a new window) ·
    Message
    Updated: The German generated examples translate every source description again
    
    The German example pages quoted 131 descriptions from the sources in English:
    newer INI comments (the SQLite busy wait and PRAGMA settings, the search
    suggestions, Smarty security, preview links, the review hold, migrations,
    static publishing, Verify it's you groups), new command options and the
    code_file migration step. They now have German translations in the
    description catalogue; 23 older translations whose English source had
    changed are updated in place, and the pages are regenerated with
    exp:help:examples --language=ger-de (no text left in English).
    
    The German directory name map is written sorted, one entry per line, as
    exp:help maps expects (content unchanged).
    d0a4987476
  8. Updated: The generated help examples show the help's reading_key and … (opens in a new window) ·
    Message
    Updated: The generated help examples show the help's reading_key and report_links fetch functions and its ReportSecurityAnchor setting
    
    The reference examples below doc/eng-us/examples/ and their German pages below
    doc/ger-de/beispiele/ are generated again from the current sources with
    exp:help:examples, so they match what has landed:
    
    - the fetch functions exphelp/reading_key and exphelp/report_links get their
      pages, and the exphelp index counts seven functions;
    - exphelp.ini [ContextHelp] lists ReportSecurityAnchor, and the path rules of
      [AudienceSettings] and [CategorySettings] and the [TreeSettings] and
      [TypeSettings] entries follow the shipped file;
    - the German site.ini [DatabaseSettings] page lists the SQLite busy-wait and
      transaction-wait settings;
    - count_chars, extract_right, html_entity_decode and simplify quote their first
      use in a shipped template, now the help menu and the text part of form mail.
    
    doc/ger-de/.paths.json maps the two new German pages. exp:help:examples --check
    reports no difference for either language.
    ff3d9701b2
  9. Merge remote-tracking branch 'origin/main' into wip-xmltext-literal-l… (opens in a new window) ·
    Message
    Merge remote-tracking branch 'origin/main' into wip-xmltext-literal-links
    780411c42e
  10. Updated: A subtree copy re-points every link and embed of its XML tex… (opens in a new window) ·
    Message
    Updated: A subtree copy re-points every link and embed of its XML text at the copies, also those before a literal block
    
    The string scan of step 5 jumped past the next literal block before it looked for links, so every link and embed
    that came before a literal (code) block in the same text kept pointing at the original; it also took the next
    link before an earlier embed or object. A copy of 2,714 nodes left 730 node ids in 189 XML texts pointing at the
    originals.
    
    The XML text is now parsed as XML by expContentJobCopySubtree::remapXMLText(): node_id and object_id of link,
    embed, embed-inline and a, id of object, and href values eznode:// and ezobject:// are re-pointed wherever
    they are. Nothing inside a literal block is changed, ids outside the copied subtree stay, and a text with nothing
    to change is kept byte for byte. The content job "copy", content/copysubtree,
    eZContentObjectTreeNodeOperations::copySubtree() and bin/php/ezsubtreecopy.php all use it.
    
    Tests with an XML fixture cover links before, between and after literal blocks, several literal blocks, embeds,
    eznode:// and ezobject:// hrefs and ids outside the copy (no database).
    3c24718c25

Showing 31–40 of 49 commits

Recently updated

Free documentation: use it to help yourself and others

This help is free documentation, licensed under the GNU Free Documentation License 1.3 or later. You may use it, share it and improve it:

  • Study it Read any page as often as you like, for any purpose.
  • Copy it and share it Give pages to other users, on paper or as files. Keep the copyright notice, the license notice and a copy of the license with every copy.
  • Translate, adapt and improve it Share your version under the same license, with the original notices and a note of what you changed.
  • Cite it Refer to a page by its title and its address in the help, or its file in the doc directory.
  • Contribute fixes back Use "Edit on GitHub" on any page. Changes are accepted under the same license, so they stay free for everyone.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x