` as the
17 | [DocBook 5.1](https://tdg.docbook.org/tdg/5.1/classsynopsis) schema does.
18 |
19 | ## Glossary
20 |
21 | This guide uses some terminology that you have to know. Don't worry, it's easy:
22 |
23 | - **author** - person who contributes to the original English manual
24 | - **translator** - person who translates the English manual into another
25 | language
26 | - **{LANG}** - replace it with your two-letter country code, (e.g. when
27 | referring to a mailinglist, `doc-{LANG}@lists.php.net`). Note:
28 | Brazilian Portuguese differs from the rest and it's called *pt_br*
29 | for the Git repo and *pt-br* for the mailing list suffix.
30 |
31 | ## Feedback
32 |
33 | You can report problems or make contributions to this guide by using the
34 | "Edit this page" or "Report a problem" links in the sidebar of each page
35 | of [the online version of this documentation](https://doc.php.net/guide/),
36 | or through [the GitHub repository](https://www.github.com/php/doc-base/).
37 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml-revtag.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | Inspect revision tag usage inside XML files. */
19 |
20 | require_once __DIR__ . '/libqa/all.php';
21 | require_once __DIR__ . '/lib/RevtagParser.php';
22 |
23 | $argv = new ArgvParser( $argv );
24 | $ignore = new OutputIgnore( $argv ); // may exit.
25 | $ignore->appendIgnoreCommands = false;
26 | $argv->complete();
27 |
28 | $list = SyncFileList::load();
29 |
30 | foreach ( $list as $file )
31 | {
32 | $target = $file->targetDir . '/' . $file->file;
33 | $revtag = RevtagParser::parseFile( $target );
34 |
35 | if ( count( $revtag->errors ) == 0 )
36 | continue;
37 |
38 | print "# qaxml.r: $target\n";
39 | foreach( $revtag->errors as $error )
40 | print " $error\n";
41 | print "\n";
42 | }
43 |
--------------------------------------------------------------------------------
/scripts/docgen/class.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 | The {CLASS_NAME} {CLASS_TYPE}
4 | {CLASS_NAME}
5 |
6 |
7 |
8 |
9 |
10 | &reftitle.intro;
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | &reftitle.classsynopsis;
19 |
20 |
21 |
22 |
23 | {CLASS_NAME}
24 |
25 |
26 |
27 |
28 | {CLASS_NAME}
29 |
30 | {EXTENDS}
31 | {IMPLEMENTS}
32 |
33 |
34 | {CONSTANTS_LIST}
35 | {PROPERTIES_LIST}
36 | {METHOD_XINCLUDE}
37 | {INHERITED_XINCLUDE}
38 |
39 |
40 |
41 |
42 |
43 | {PROPERTIES}
44 | {CONSTANTS}
45 |
46 |
47 |
48 | &reference.{EXT_NAME_ID}.entities.{CLASS_NAME_ID};
49 |
50 |
51 |
71 |
--------------------------------------------------------------------------------
/htmlhelp/suppfiles/notes/_notes_script.js:
--------------------------------------------------------------------------------
1 | // RAQ : Tuesday, 15 March 2005 03:20 pm : Allow notes from searches to call the original manual page and get the notes skinned.
2 | // Get the path and name of the CHM file and assign values
3 | function loadWithNotes() {
4 | var a, X, Y, Z;
5 | a = location.href.search(/:/);
6 | Y = location.href.lastIndexOf("::");
7 |
8 | if (a == 4) { // file: or http:
9 | Y = location.href.lastIndexOf("/");
10 | chmfile_page = unescape(location.href.substring(Y+1));
11 | if (location.href.substring(0,4) == "file")
12 | chmfile_path = unescape(location.href.substring(8, Y+1));
13 | } else {
14 | if (a == 2)
15 | X = 14; // mk:@MSITStore:
16 | if (a == 7)
17 | X = 7; // ms-its:
18 |
19 | chmfile_fullname = unescape(location.href.substring(X, Y));
20 | Z = chmfile_fullname.lastIndexOf("\\");
21 | chmfile_path = unescape(chmfile_fullname.substring(0, Z+1));
22 | chmfile_name = unescape(chmfile_fullname.substring(Z+1));
23 | chmfile_page = unescape(location.href.substring(Y+3));
24 | }
25 |
26 | //alert(
27 | // "_notes_script\n\n" +
28 | // "location\n"+
29 | // "location.hash = '" + location.hash + "'\n" +
30 | // "location.host = '" + location.host + "'\n" +
31 | // "location.hostname = '" + location.hostname + "'\n" +
32 | // "location.href = '" + location.href + "'\n" +
33 | // "location.pathname = '" + location.pathname + "'\n" +
34 | // "location.port = '" + location.port + "'\n" +
35 | // "location.protocol = '" + location.protocol + "'\n" +
36 | // "location.search = '" + location.search + "'\n\n" +
37 | // "chmfile\n"+
38 | // "chmfile_name = '" + chmfile_name + "'\n" +
39 | // "chmfile_path = '" + chmfile_path + "'\n" +
40 | // "chmfile_page = '" + chmfile_page + "'\n"
41 | // );
42 |
43 | location = location.protocol + '@MSITStore:' + chmfile_path + 'php_manual_en.chm::/' + chmfile_page + '#userNotes';
44 | }
--------------------------------------------------------------------------------
/scripts/check-underdocumented.php:
--------------------------------------------------------------------------------
1 | getPathname();
36 | $filename = $file->getBasename();
37 |
38 | if (strpos($filepath, '.svn')) {
39 | continue;
40 | }
41 |
42 | if (!$file->isFile() || pathinfo($filepath, PATHINFO_EXTENSION) !== 'xml') {
43 | continue;
44 | }
45 |
46 | $fileid = str_replace($phpdoc_path, '', $filepath);
47 | $ext = strtok($fileid, DIRECTORY_SEPARATOR);
48 |
49 | if (file_exists($phpdoc_path . $fileid)) {
50 | $contents = file_get_contents($phpdoc_path . $fileid);
51 | if (false !== strpos($contents, 'warn.undocumented.func')) {
52 | $undocumented[$ext][] = $fileid;
53 | ++$count;
54 | }
55 | continue;
56 | }
57 | }
58 |
59 | echo 'List of underdocumented functions/methods', PHP_EOL;
60 | print_r($undocumented);
61 | echo "Number underdocumented: ", $count, PHP_EOL;
62 |
63 | function usage() {
64 | echo PHP_EOL, 'USAGE:', PHP_EOL;
65 | echo 'php ', $_SERVER['SCRIPT_FILENAME'], ' -p /path/to/phpdoc/en/reference/', PHP_EOL;
66 | exit;
67 | }
--------------------------------------------------------------------------------
/docbook/JING_LICENSE:
--------------------------------------------------------------------------------
1 |
2 |
3 | Jing Copying Conditions
4 |
5 |
6 |
7 | Jing Copying Conditions
8 |
9 | Copyright (c) 2001-2003 Thai Open Source Software Center Ltd
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are
14 | met:
15 |
16 |
17 | - Redistributions of source code must retain the above copyright
18 | notice, this list of conditions and the following disclaimer.
19 |
20 | - Redistributions in binary form must reproduce the above copyright
21 | notice, this list of conditions and the following disclaimer in
22 | the documentation and/or other materials provided with the
23 | distribution.
24 |
25 | - Neither the name of the Thai Open Source Software Center Ltd nor
26 | the names of its contributors may be used to endorse or promote
27 | products derived from this software without specific prior written
28 | permission.
29 |
30 |
31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
35 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
37 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/htmlhelp/suppfiles/prefs/context.ini:
--------------------------------------------------------------------------------
1 | # =================================================
2 | # PHP Manual CHM version context menu configuration
3 | # =================================================
4 |
5 | # Genaral functions
6 | # -----------------
7 |
8 | [context_item]
9 | display = "Copy selection to clipboard"
10 | implementation = "copySelection()"
11 |
12 | [context_item]
13 | display = "Select all"
14 | implementation = "selectAll()"
15 |
16 | [context_item]
17 | display = "Print page"
18 | implementation = "print()"
19 |
20 | [context_item]
21 | display = "Back"
22 | implementation = "back()"
23 |
24 | [context_item]
25 | display = "Forward"
26 | implementation = "forward()"
27 |
28 | [context_item]
29 | display = "Refresh"
30 | implementation = "refresh()"
31 |
32 | # Page jump options
33 | # -----------------
34 |
35 | [context_item]
36 | display = "Manual TOC"
37 | implementation = "index.html"
38 |
39 | [context_item]
40 | display = "Function Reference"
41 | implementation = "funcref.html"
42 |
43 | [context_item]
44 | display = "HTML Help Edition"
45 | implementation = "chmonly.html"
46 |
47 | [context_item]
48 | display = "Functions Index"
49 | implementation = "indexes.html"
50 |
51 | [context_item]
52 | display = "PHP-GTK home"
53 | implementation = "http://gtk.php.net/"
54 |
55 | [context_item]
56 | display = "PEAR home"
57 | implementation = "http://pear.php.net/"
58 |
59 | # Search engine quickforms and selections
60 | # ---------------------------------------
61 |
62 | [context_item]
63 | display = "Google SearchBox"
64 | implementation = "_GoogleSearch_"
65 |
66 | [context_item]
67 | display = "Google Search Selection"
68 | implementation = "searchSelGoogle()"
69 |
70 | [context_item]
71 | display = "AlltheWeb SearchBox"
72 | implementation = "_ATWSearch_"
73 |
74 | [context_item]
75 | display = "AlltheWeb Search Selection"
76 | implementation = "searchSelATW()"
--------------------------------------------------------------------------------
/scripts/translation/lib/all.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Old style, require all file. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | ini_set( 'display_errors' , 1 );
21 | ini_set( 'display_startup_errors' , 1 );
22 | error_reporting( E_ALL );
23 |
24 | require_once __DIR__ . '/backport.php';
25 | require_once __DIR__ . '/CacheFile.php';
26 | require_once __DIR__ . '/CacheUtil.php';
27 | require_once __DIR__ . '/GitLogParser.php';
28 | require_once __DIR__ . '/GitSlowUtils.php';
29 | require_once __DIR__ . '/OutputIgnoreArgv.php';
30 | require_once __DIR__ . '/OutputIgnoreBuffer.php';
31 | require_once __DIR__ . '/QaFileInfo.php';
32 | require_once __DIR__ . '/RevcheckData.php';
33 | require_once __DIR__ . '/RevcheckFileItem.php';
34 | require_once __DIR__ . '/RevcheckFileList.php';
35 | require_once __DIR__ . '/RevcheckIgnore.php';
36 | require_once __DIR__ . '/RevcheckRun.php';
37 | require_once __DIR__ . '/RevtagParser.php';
38 | require_once __DIR__ . '/XmlUtil.php';
39 |
--------------------------------------------------------------------------------
/scripts/notes_extract.php:
--------------------------------------------------------------------------------
1 | |
15 | +----------------------------------------------------------------------+
16 |
17 | $Id$
18 | */
19 |
20 | /*
21 | * Usage:
22 | * $ php notes_extract.php source.mbox > notes.txt
23 | */
24 |
25 | define('NL', "\n");
26 |
27 | if (!isset($argv[1]) || $argv[1] == '-h' || $argv[1] == '--help') {
28 | echo 'USAGE: ', $argv[0], ' source.mbox > notes.txt', NL;
29 | exit(1);
30 | }
31 |
32 | if (!file_exists($argv[1])) {
33 | echo 'Error: Could not open file.', NL;
34 | exit(2);
35 | }
36 |
37 | define('SOURCE', $argv[1]);
38 |
39 | $pairs = shell_exec(
40 | 'gawk \'BEGIN { RS = "\n\n" } /Date: ([^\n]+).*Subject: \[PHP-NOTES]/ { print $0 }\' '.SOURCE.' | gawk \'/^Date:/ { print $0 } /^Subject:/ { print $0 }\''
41 | );
42 |
43 | $pairs = explode(NL, $pairs);
44 |
45 | //echo 'Processing ', count($pairs) / 2, ' notes...', NL;
46 |
47 | $last = count($pairs);
48 |
49 | for ($i = 0; $i < $last; ++$i) {
50 | if (substr($pairs[$i], 0, 5) != 'Date:') {
51 | continue;
52 | }
53 |
54 | if (substr($pairs[$i + 1], 0, 8) != 'Subject:') {
55 | continue;
56 | }
57 |
58 | echo strtotime(substr($pairs[$i], 6)), ' ', substr($pairs[$i + 1], 9), NL;
59 | }
60 |
--------------------------------------------------------------------------------
/htmlhelp/README.txt:
--------------------------------------------------------------------------------
1 | ****************************************************************
2 | ** This build system is used to generate the extended CHM **
3 | ** file available from php.net (only in English). There is **
4 | ** a different CHM generator system in the 'chm' folder, **
5 | ** which is used to build the simpler CHM files (in multiple **
6 | ** languages). **
7 | ** **
8 | ** Both of the systems are used in paralell. **
9 | ****************************************************************
10 |
11 | Build system of the extended CHMs
12 | =================================
13 |
14 | [See latest "official" output package online at
15 | http://php.net/docs-echm]
16 |
17 | How to build a CHM manual with this system?
18 |
19 | 0. Ensure that you have the latest phpdoc checkout and the
20 | version information in xsl/version.xml is up-to-date,
21 | so you will build the latest function version information
22 | into the CHM.
23 |
24 | 1. run "autoconf" in the phpdoc directory
25 |
26 | 2. run "./configure --with-chm=yes"
27 |
28 | Optionally you may need to specify the
29 | "--with-xsltproc=path" option to explicitly
30 | provide the XSLTProc path.
31 |
32 |
33 | 3. Run "make chm_xsl"
34 |
35 | If xsltproc encounters errors in the XML files,
36 | correct the errors, commit them to phpdoc, and
37 | run "make chm_xsl" again. There is no need to
38 | reconfigure in most cases.
39 |
40 | After this step the HTML files to start are in
41 | phpdoc/htmlhelp/html
42 |
43 | 4. Get the actual mirrors.inc file from
44 | http://ANY_MIRROR.php.net/include/mirrors.inc
45 | and save into the directory where the
46 | make_chm.bat resides (overwrite old one if
47 | one exists).
48 |
49 | 5. Get all the user notes from
50 | http://ANY_MIRROR.php.net/backend/notes/all.bz2,
51 | extract its contents (using bunzip2 all.bz2, for example),
52 | and place the resulting "all" file to the same folder where
53 | the make_chm.bat resides.
54 |
55 | 6. Copy local_vars.php.src to local_vars.php and
56 | adjust settings as needed.
57 |
58 | 7. Now run make_chm.bat
59 |
60 | Well, this is quite manual right now, and there are
61 | some problems need fixing (see the TODO.txt file too).
62 |
--------------------------------------------------------------------------------
/scripts/translation/lib/CacheUtil.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Common functions do load and save to cache files. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class CacheUtil
23 | {
24 | const CACHE_DIR = __DIR__ . '/../.cache';
25 |
26 | public static function load( string $path , string $file )
27 | {
28 | $filename = CacheUtil::prepareFilename( $path , $file , true );
29 | if ( file_exists( $filename ) == false )
30 | return null;
31 | $data = file_get_contents( $filename );
32 | return unserialize( $data );
33 | }
34 |
35 | public static function save( string $path , string $file , $data )
36 | {
37 | $outFile = CacheUtil::prepareFilename( $path , $file , true );
38 | $contents = serialize( $data );
39 | file_put_contents( $outFile , $contents );
40 | }
41 |
42 | public static function prepareFilename( string $path , string $file , bool $createDirs = false )
43 | {
44 | $baseDir = CacheUtil::CACHE_DIR;
45 | $outPath = rtrim( $baseDir , '/' ) . '/' . $path;
46 | $outFile = rtrim( $outPath , '/' ) . '/' . $file;
47 | if ( $createDirs && file_exists( $outPath ) == false )
48 | mkdir( $outPath , 0777 , true );
49 | return $outFile;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/scripts/translation/qarvt.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Check format for revtags and credits on XML comments. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/lib/all.php';
21 |
22 | $langDir = "";
23 |
24 | switch ( count( $argv ) )
25 | {
26 | case 1:
27 | break;
28 | case 2:
29 | $langDir = $argv[1];
30 | break;
31 | default:
32 | print_usage_exit($argv[0]);
33 | return;
34 | }
35 |
36 | if ( $langDir == "" )
37 | {
38 | $qalist = QaFileInfo::cacheLoad();
39 | if ( count( $qalist ) > 0 )
40 | {
41 | foreach( $qalist as $qa )
42 | {
43 | $langDir = $qa->targetDir;
44 | break;
45 | }
46 | }
47 | else
48 | print_usage_exit($argv[0]);
49 | }
50 |
51 | $list = new RevcheckFileList( $langDir );
52 |
53 | foreach( $list->iterator() as $item )
54 | {
55 | $file = $langDir . '/' . $item->file;
56 | $revt = RevtagParser::parseFile( $file );
57 |
58 | if ( count( $revt->errors ) == 0 )
59 | continue;
60 |
61 | print "qarvt: $file\n";
62 | foreach( $revt->errors as $error )
63 | print " $error\n";
64 | print "\n";
65 | }
66 |
67 | function print_usage_exit($cmd)
68 | {
69 | fwrite( STDERR , " Wrong paramater count. Usage:\n" );
70 | fwrite( STDERR , " {$cmd} [lang_dir]:\n" );
71 | exit;
72 | }
73 |
--------------------------------------------------------------------------------
/skeletons/ini.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | &reftitle.runtime;
4 | &extension.runtime;
5 |
6 |
7 |
8 |
9 | Extname &ConfigureOptions;
10 |
11 |
12 |
13 | &Name;
14 | &Default;
15 | &Changeable;
16 | &Changelog;
17 |
18 |
19 |
20 |
21 | theini_option
22 | itsvalue
23 | its INI_* value
24 | version changes information
25 |
26 |
27 | anotherini_option
28 | itsvalue
29 | its INI_* value
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | &ini.php.constants;
38 |
39 |
40 |
41 |
42 | &ini.descriptions.title;
43 |
44 |
45 |
46 | theini_option
47 | thetype
48 |
49 |
50 |
51 | Fill in the description of theini-option.
52 |
53 |
54 |
55 |
56 |
57 |
58 | anotherini_option
59 | thetype
60 |
61 |
62 |
63 | Fill in the description of anotherini-option.
64 |
65 |
66 |
67 |
68 |
69 |
70 |
90 |
--------------------------------------------------------------------------------
/scripts/qa/check-missing-initializers.php:
--------------------------------------------------------------------------------
1 | tag.
5 | - Pass in a path and it'll check it. The path might include all of phpdoc, or a simple extension
6 | TODO:
7 | - Determine what initializer values should be as some cases aren't clear
8 | */
9 |
10 | $opts = getopt('p:oh');
11 |
12 | if (isset($opts['h'])) {
13 | usage();
14 | }
15 | if (empty($opts['p'])) {
16 | echo "\nERROR:\n - A path is required\n";
17 | usage();
18 | }
19 | if (!is_dir($opts['p'])) {
20 | echo "\nERROR:\n - Please pass in a real directory, unlike this mysterious '$opts[p]'\n";
21 | usage();
22 | }
23 |
24 | $empty = [];
25 | $count_total = 0;
26 | $count_empty = 0;
27 |
28 | foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($opts['p'])) as $file) {
29 |
30 | $filepath = $file->getPathname();
31 | $filename = $file->getBasename();
32 |
33 | if (!$file->isFile() || pathinfo($filepath, PATHINFO_EXTENSION) !== 'xml') {
34 | continue;
35 | }
36 |
37 | $contents = file_get_contents($filepath);
38 |
39 | $matches = [];
40 | preg_match_all('@(.*)(.*)(.*)@', $contents, $matches);
41 |
42 | // Check if any optional parameters exist
43 | if (empty($matches)) {
44 | continue;
45 | }
46 |
47 | // Log optional parameters without default values
48 | // We use the DocBook tag for this task.
49 | foreach ($matches[3] as $index => $match) {
50 | $count_total++;
51 | if (empty($match) || (!str_contains($match, ''))) {
52 | $count_empty++;
53 | // index 2 corresponds to the param, index 1 to the type
54 | $empty[$filepath][$matches[2][$index]] = $matches[1][$index];
55 | }
56 | }
57 | }
58 |
59 | // This output could be more useful
60 | if (array_key_exists('o', $opts)) {
61 | foreach ($empty as $file => $issues) {
62 | echo $file, ' has ', count($issues), ' optional parameters without initializers:', "\n";
63 | foreach ($issues as $param => $type) {
64 | echo '- Param "', $param, '" of type "', $type, "\"\n";
65 | }
66 | }
67 | }
68 |
69 | print "Found $count_total optional parameters, and $count_empty are empty.\n";
70 |
71 | function usage() {
72 | echo "\nUSAGE:\n";
73 | echo "$ php {$_SERVER['SCRIPT_FILENAME']} -p /path/to/phpdoc/docs/to/check\n";
74 | echo " Optional: Add -o to output the results.\n";
75 | exit;
76 | }
77 |
--------------------------------------------------------------------------------
/scripts/translation/lib/CacheFile.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Class to handle data persistence. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class CacheFile
23 | {
24 | const CACHE_DIR = __DIR__ . '/../.cache';
25 |
26 | private string $filename;
27 |
28 | function __construct( string $file )
29 | {
30 | $this->filename = CacheFile::prepareFilename( $file , true );
31 | }
32 |
33 | public function load( mixed $init = null )
34 | {
35 | if ( file_exists( $this->filename ) == false )
36 | return $init;
37 | $data = file_get_contents( $this->filename );
38 | return unserialize( gzdecode( $data ) );
39 | }
40 |
41 | public function save( $data )
42 | {
43 | $contents = gzencode( serialize( $data ) );
44 | file_put_contents( $this->filename , $contents );
45 | }
46 |
47 | public static function prepareFilename( string $file , bool $createCacheDirs = false )
48 | {
49 | if ( str_starts_with( $file , '/' ) )
50 | return $file;
51 | $outPath = CacheUtil::CACHE_DIR . '/' . dirname( $file );
52 | $outFile = rtrim( $outPath , '/' ) . '/' . $file;
53 | if ( $createCacheDirs && file_exists( $outPath ) == false )
54 | mkdir( $outPath , 0777 , true );
55 | return $outFile;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml-pi.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | Compare processing instructions usage between two XML files. */
19 |
20 | require_once __DIR__ . '/libqa/all.php';
21 |
22 | $argv = new ArgvParser( $argv );
23 | $ignore = new OutputIgnore( $argv ); // may exit.
24 | $argv->complete();
25 |
26 | $list = SyncFileList::load();
27 |
28 | foreach ( $list as $file )
29 | {
30 | $source = $file->sourceDir . '/' . $file->file;
31 | $target = $file->targetDir . '/' . $file->file;
32 | $output = new OutputBuffer( "# qaxml.p" , $target , $ignore );
33 |
34 | [ $s ] = XmlFrag::loadXmlFragmentFile( $source );
35 | [ $t ] = XmlFrag::loadXmlFragmentFile( $target );
36 |
37 | $s = XmlFrag::listNodes( $s , XML_PI_NODE );
38 | $t = XmlFrag::listNodes( $t , XML_PI_NODE );
39 |
40 | $s = extractPiData( $s );
41 | $t = extractPiData( $t );
42 |
43 | if ( implode( "\n" , $s ) === implode( "\n" , $t ) )
44 | continue;
45 |
46 | $sideCount = [];
47 |
48 | foreach( $s as $v )
49 | $sideCount[$v] = [ 0 , 0 ];
50 | foreach( $t as $v )
51 | $sideCount[$v] = [ 0 , 0 ];
52 |
53 | foreach( $s as $v )
54 | $sideCount[$v][0] += 1;
55 | foreach( $t as $v )
56 | $sideCount[$v][1] += 1;
57 |
58 | foreach( $sideCount as $k => $v )
59 | if ( $v[0] != $v[1] )
60 | $output->addDiff( $k , $v[0] , $v[1] );
61 |
62 | $output->print();
63 | }
64 |
65 | function extractPiData( array $list )
66 | {
67 | $ret = [];
68 | foreach( $list as $elem )
69 | $ret[] = "{$elem->target} {$elem->data}";
70 | return $ret;
71 | }
72 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml.e.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Compare entities usage between XMLs. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | echo "This tool is obsolete and will be REMOVED soon.\n";
21 | echo "See https://github.com/php/doc-base/blob/master/scripts/translation/README.md\n";
22 | echo "for alternatives.\n\n".
23 |
24 | require_once __DIR__ . '/lib/all.php';
25 |
26 | $qalist = QaFileInfo::cacheLoad();
27 | $outarg = new OutputIgnoreArgv( $argv );
28 |
29 | foreach ( $qalist as $qafile )
30 | {
31 | if ( $qafile->sourceHash != $qafile->targetHash )
32 | continue;
33 |
34 | $source = $qafile->sourceDir . '/' . $qafile->file;
35 | $target = $qafile->targetDir . '/' . $qafile->file;
36 |
37 | $s = XmlUtil::extractEntities( $source );
38 | $t = XmlUtil::extractEntities( $target );
39 |
40 | if ( implode( "\n" , $s ) == implode( "\n" , $t ) )
41 | continue;
42 |
43 | $output = new OutputIgnoreBuffer( $outarg , "qaxml.e: {$target}\n\n" , $target );
44 |
45 | $match = [];
46 |
47 | foreach( $s as $v )
48 | $match[$v] = array( 0 , 0 );
49 | foreach( $t as $v )
50 | $match[$v] = array( 0 , 0 );
51 |
52 | foreach( $s as $v )
53 | $match[$v][0] += 1;
54 | foreach( $t as $v )
55 | $match[$v][1] += 1;
56 |
57 | foreach( $match as $k => $v )
58 | {
59 | if ( $v[0] == $v[1] )
60 | continue;
61 |
62 | $output->add( "* &{$k}; -{$v[1]} +{$v[0]}\n" );
63 | }
64 |
65 | $output->addLine();
66 | $output->print();
67 | }
68 |
--------------------------------------------------------------------------------
/scripts/translation/lib/QaFileInfo.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Common data for revcheck and QA tools. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class QaFileInfo
23 | {
24 | public string $sourceHash;
25 | public string $targetHash;
26 | public string $sourceDir;
27 | public string $targetDir;
28 | public string $file;
29 | public int $days;
30 |
31 | function __construct( string $sourceHash , string $targetHash , string $sourceDir , string $targetDir , string $file , int $days )
32 | {
33 | $this->sourceHash = $sourceHash;
34 | $this->targetHash = $targetHash;
35 | $this->sourceDir = $sourceDir;
36 | $this->targetDir = $targetDir;
37 | $this->file = $file;
38 | $this->days = $days;
39 | }
40 |
41 | public static function cacheLoad() :array
42 | {
43 | return CacheUtil::load( "" , "QaFileInfo.phps" );
44 | }
45 |
46 | public static function cacheSave( array $itens )
47 | {
48 | // PHP serialize()
49 | CacheUtil::save( "" , "QaFileInfo.phps" , $itens );
50 |
51 | // CSV
52 | $filename = CacheUtil::prepareFilename( "" , "QaFileInfo.csv" , true );
53 | $fp = fopen( $filename , 'w' );
54 | foreach( $itens as $item )
55 | {
56 | $line = array( $item->sourceHash , $item->targetHash , $item->sourceDir , $item->targetDir , $item->file , $item->days );
57 | fputcsv( $fp , $line, escape: "" );
58 | }
59 | fclose($fp);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/scripts/translation/libqa/SyncFileList.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | Generates (and caches) the list of files with TranslatedOk status. */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class SyncFileList
23 | {
24 | static function load()
25 | {
26 | $file = __DIR__ . "/../../../temp/lang";
27 | if ( ! file_exists( $file ) )
28 | {
29 | fwrite( STDERR , "Language file not found, run 'doc-base/configure.php'.\n" );
30 | exit();
31 | }
32 |
33 | $lang = trim( file_get_contents( $file ) );
34 | $cacheFilename = __DIR__ . "/../../../temp/qaxml.files.$lang";
35 |
36 | if ( file_exists( $cacheFilename ) )
37 | {
38 | return unserialize( gzdecode( file_get_contents( $cacheFilename ) ) );
39 | }
40 |
41 | $sourceDir = 'en';
42 | $targetDir = $lang;
43 |
44 | require_once __DIR__ . '/../lib/all.php';
45 |
46 | $files = new RevcheckFileList( $sourceDir );
47 | $ret = [];
48 |
49 | foreach( $files->iterator() as $file )
50 | {
51 | if ( ! file_exists( "$targetDir/{$file->file}" ) )
52 | continue;
53 |
54 | $item = new SyncFileItem();
55 | $item->sourceDir = $sourceDir;
56 | $item->targetDir = $targetDir;
57 | $item->file = $file->file;
58 | $ret[] = $item;
59 | }
60 |
61 | if ( $ret === [] )
62 | throw new Exception( "No files found. Called from wrong directory?" );
63 |
64 | $contents = gzencode( serialize( $ret ) );
65 | file_put_contents( $cacheFilename , $contents );
66 |
67 | return $ret;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml-ws.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | Inspect white space usage inside some known tags. Spurious whitespace
19 | may break manual linking or generate visible artifacts. */
20 |
21 | require_once __DIR__ . '/libqa/all.php';
22 |
23 | $argv = new ArgvParser( $argv );
24 | $ignore = new OutputIgnore( $argv ); // may exit.
25 | $argv->complete();
26 |
27 | $list = SyncFileList::load();
28 |
29 | foreach ( $list as $file )
30 | {
31 | $source = $file->sourceDir . '/' . $file->file;
32 | $target = $file->targetDir . '/' . $file->file;
33 |
34 | whitespaceCheckFile( $source , $ignore );
35 | whitespaceCheckFile( $target , $ignore );
36 | }
37 |
38 | function whitespaceCheckFile( string $filename , OutputIgnore $ignore )
39 | {
40 | if ( file_exists( $filename ) == false )
41 | return;
42 |
43 | $output = new OutputBuffer( "# qaxml.w" , $filename , $ignore );
44 |
45 | [ $xml , $_ , $_ ] = XmlFrag::loadXmlFragmentFile( $filename );
46 | $nodes = XmlFrag::listNodes( $xml , XML_ELEMENT_NODE );
47 |
48 | foreach( $nodes as $node )
49 | {
50 | switch ( $node->nodeName )
51 | {
52 | case "classname":
53 | case "constant":
54 | case "function":
55 | case "methodname":
56 | case "varname":
57 | $text = $node->nodeValue;
58 | $trim = trim( $text );
59 | if ( $text != $trim )
60 | {
61 | $output->addLine();
62 | $output->add( " {$node->nodeName} {$trim}\n" );
63 | }
64 | break;
65 | }
66 | }
67 |
68 | $output->print();
69 | }
70 |
--------------------------------------------------------------------------------
/scripts/en.pws:
--------------------------------------------------------------------------------
1 | personal_ws-1.1 en 242
2 | ISAPI
3 | plugin
4 | UDM
5 | HTTPS
6 | https
7 | dBase
8 | httpd
9 | UDP
10 | pspell
11 | Borland
12 | Google
13 | mcrypt
14 | zlib
15 | RPC
16 | SQL
17 | Bcc
18 | conf
19 | CMYK
20 | RPN
21 | EZMLM
22 | bzip
23 | iPlanet
24 | GMP
25 | cygwin
26 | ClibPDF
27 | bezier
28 | xml
29 | PostgreSQL
30 | Solaris
31 | XPath
32 | builtin
33 | versioning
34 | GPG
35 | JPEG
36 | jpeg
37 | jpg
38 | ODBC
39 | odbc
40 | iODBC
41 | GPL
42 | mnoGoSearch
43 | mnogosearch
44 | README
45 | prerelease
46 | Zend
47 | FAM
48 | SPX
49 | stdin
50 | TCL
51 | servlet
52 | php
53 | CRC
54 | crc
55 | gdb
56 | stderr
57 | cron
58 | stdout
59 | WDDX
60 | SNMP
61 | Sablotron
62 | towards
63 | gzip
64 | JSP
65 | MCVE
66 | mcve
67 | GTK
68 | Gtk
69 | TLS
70 | CSR
71 | mhash
72 | XSL
73 | SESAM
74 | iconv
75 | msession
76 | gif
77 | MCAL
78 | mcal
79 | SDK
80 | PCNTL
81 | pcntl
82 | EGPCS
83 | Xitami
84 | Informix
85 | LF
86 | gcc
87 | CGI
88 | cgi
89 | DNS
90 | CLI
91 | CCL
92 | MacOS
93 | FI
94 | hw
95 | gz
96 | JS
97 | CSS
98 | gd
99 | GID
100 | MX
101 | Ovrimos
102 | ovrimos
103 | png
104 | NUL
105 | NUM
106 | MSIE
107 | DSSSL
108 | ZZIPlib
109 | dir
110 | LDAP
111 | ldap
112 | Inprise
113 | EOF
114 | NIS
115 | SHA
116 | PEM
117 | openssl
118 | awk
119 | UX
120 | IRC
121 | func
122 | url
123 | EOL
124 | ini
125 | DTD
126 | ip
127 | API
128 | OOP
129 | api
130 | PWS
131 | NULLs
132 | pid
133 | SWF
134 | Mozilla
135 | fbsql
136 | IIS
137 | ascii
138 | OCI
139 | IDE
140 | oid
141 | UID
142 | Verisign
143 | CRLF
144 | binutils
145 | VBScript
146 | unserialized
147 | TTF
148 | fopen
149 | SSL
150 | ssl
151 | RSA
152 | SAPI
153 | XP
154 | DLL
155 | dll
156 | PHP's
157 | xmlrpc
158 | ibase
159 | FDF
160 | fdf
161 | unescaped
162 | undefine
163 | GmbH
164 | NTFS
165 | VC
166 | mbstring
167 | NSAPI
168 | online
169 | inline
170 | unix
171 | XHTML
172 | NNTP
173 | PECL
174 | onload
175 | hmac
176 | PGP
177 | pcre
178 | YAZ
179 | yaz
180 | ActiveX
181 | IRCG
182 | unziped
183 | Postgres
184 | icap
185 | validator
186 | shmop
187 | exe
188 | ncurses
189 | UCD
190 | expat
191 | IMAP
192 | JScript
193 | internet
194 | IPv
195 | PREG
196 | SQLite
197 | sqlite
198 | concatenator
199 | endian
200 | Sybase
201 | sybase
202 | untar
203 | inode
204 | PDF
205 | pdf
206 | html
207 | IPX
208 | IPC
209 | PKCS
210 | symlink
211 | RGB
212 | rgb
213 | XSLT
214 | xslt
215 | http
216 | precompiled
217 | JVM
218 | POSIX
219 | posix
220 | APIs
221 | CVS
222 | CCVS
223 | MySQL
224 | mysql
225 | msql
226 | mSQL
227 | MSSQL
228 | mssql
229 | mysqli
230 | MySQLi
231 | WBMP
232 | BMP
233 | symlinks
234 | uncheck
235 | OSX
236 | UTF
237 | UDF
238 | utf
239 | regex
240 |
--------------------------------------------------------------------------------
/chm/common.php:
--------------------------------------------------------------------------------
1 | |[^a-zA-Z1-9][^>]*>)/Ue", "preg_replace('/[\r\n]{1,2}/U', ' ', \"<\$1 \$2\")", file_get_contents($filename));
15 | } else {
16 | $buf = preg_replace("/[\r|\n]{1,2}/U", " ", file_get_contents($filename));
17 | }
18 | $charset = detectDocumentCharset($buf);
19 |
20 | if ($charset === false) $charset = "UTF-8";
21 |
22 | if ($charset != $INTERNAL_CHARSET) {
23 | if (function_exists("iconv")) {
24 | $buf = iconv($charset, $INTERNAL_CHARSET, $buf);
25 | } elseif (function_exists("mb_convert_encoding")) {
26 | $buf = mb_convert_encoding($buf, $INTERNAL_CHARSET, $charset);
27 | } elseif (preg_match("/^UTF-?8$/i", $INTERNAL_CHARSET) && preg_match("/^(ISO-8859-1|WINDOWS-1252)$/i", $charset)) {
28 | $buf = utf8_encode($buf);
29 | } else {
30 | die("charset conversion function is not available.");
31 | }
32 | }
33 | return $buf;
34 | }
35 |
36 | function fputs_wrapper($fp, $str)
37 | {
38 | fputs($fp, convertCharset($str));
39 | }
40 |
41 | function convertCharset($buf)
42 | {
43 | global $LANGUAGE, $LANGUAGES, $INTERNAL_CHARSET;
44 |
45 | $charset = $LANGUAGES[$LANGUAGE]['preferred_charset'];
46 |
47 | if ($charset != $INTERNAL_CHARSET) {
48 | if (function_exists("iconv")) {
49 | $buf = iconv($INTERNAL_CHARSET, "$charset//TRANSLIT", $buf);
50 | } elseif (function_exists("mb_convert_encoding")) {
51 | $buf = mb_convert_encoding($buf, $charset, $INTERNAL_CHARSET);
52 | } elseif (preg_match("/^UTF-?8$/i", $INTERNAL_CHARSET) && preg_match("/^(ISO-8859-1|WINDOWS-1252)$/i", $charset)) {
53 | $buf = utf8_decode($buf);
54 | } else {
55 | die("$LANGUAGE locale is not supported.");
56 | }
57 | }
58 | return $buf;
59 | } // oneLiner() function end
60 |
61 | // Returns the name of character set in the given document
62 | function detectDocumentCharset($doc)
63 | {
64 | if (preg_match('/]+CHARSET=["\'\s]?([\w\d-]+)["\'\s]?\s*>/iS', $doc, $reg)) {
65 | return $reg[1];
66 | }
67 | return false;
68 | }
69 |
70 | function setDocumentCharset($doc, $charset)
71 | {
72 | return preg_replace("/()/iU", "\$1$charset\$3", $doc);
73 | }
74 | ?>
75 |
76 |
--------------------------------------------------------------------------------
/scripts/translation/lib/RevcheckIgnore.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Files ignored on translation tree. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class RevcheckIgnore
23 | {
24 | public static function ignore( $filename ) : bool
25 | {
26 | // Ignore dot files
27 |
28 | if ( $filename[0] == '.' )
29 | return true;
30 |
31 | // Ignore files other than xml assets
32 |
33 | if ( ( str_ends_with( $filename , '.xml' ) || str_ends_with( $filename , '.ent' ) ) == false )
34 | return true;
35 |
36 | // Ignore autogenerated files
37 |
38 | if ( str_starts_with( $filename , "entities." ) )
39 | return true;
40 | if ( str_contains( $filename , "/entities." ) )
41 | return true;
42 | if ( str_contains( $filename , "/versions.xml" ) )
43 | return true;
44 |
45 | // Only in English, autogenerated, marked not translatable
46 |
47 | if ( $filename == "contributors.ent" )
48 | return true;
49 | if ( $filename == "contributors.xml" )
50 | return true;
51 | if ( $filename == "appendices/license.xml" )
52 | return true;
53 | if ( $filename == "appendices/extensions.xml" )
54 | return true;
55 | if ( $filename == "appendices/reserved.constants.xml" )
56 | return true;
57 | if ( $filename == "reference/datetime/timezones.xml" )
58 | return true;
59 |
60 | // Only in translations
61 |
62 | if ( $filename == "translation.xml" )
63 | return true;
64 |
65 | // At least, do not ignore
66 | return false;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml.w.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Checks for ws that may cause render trouble. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | echo "This tool is obsolete and will be REMOVED soon.\n";
21 | echo "See https://github.com/php/doc-base/blob/master/scripts/translation/README.md\n";
22 | echo "for alternatives.\n\n".
23 |
24 | require_once __DIR__ . '/lib/all.php';
25 |
26 | $qalist = QaFileInfo::cacheLoad();
27 | $outarg = new OutputIgnoreArgv( $argv );
28 |
29 | foreach ( $qalist as $qafile )
30 | {
31 | $source = $qafile->sourceDir . '/' . $qafile->file;
32 | $target = $qafile->targetDir . '/' . $qafile->file;
33 |
34 | whitespaceCheckFile( $source );
35 | whitespaceCheckFile( $target );
36 | }
37 |
38 | function whitespaceCheckFile( string $filename )
39 | {
40 | if ( file_exists( $filename ) == false )
41 | return;
42 |
43 | global $outarg;
44 | $output = new OutputIgnoreBuffer( $outarg , "qaxml.w: {$filename}\n\n" , $filename );
45 |
46 | $xml = XmlUtil::loadFile( $filename );
47 | $tags = XmlUtil::listNodeType( $xml , XML_ELEMENT_NODE );
48 |
49 | foreach( $tags as $node )
50 | {
51 | switch ( $node->nodeName )
52 | {
53 | case "classname":
54 | case "constant":
55 | case "function":
56 | case "methodname":
57 | case "varname":
58 | $text = $node->nodeValue;
59 | $trim = trim( $text );
60 | if ( $text != $trim )
61 | {
62 | $output->addLine();
63 | $output->add( " {$node->nodeName} {$trim}\n" );
64 | }
65 | break;
66 | }
67 | }
68 |
69 | $output->print();
70 | }
71 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml-attributes.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | Compare attributes usage between two XML leaf/fragment files. */
19 |
20 | require_once __DIR__ . '/libqa/all.php';
21 |
22 | $argv = new ArgvParser( $argv );
23 | $ignore = new OutputIgnore( $argv ); // may exit.
24 | $urgent = $argv->consume( "--urgent" ) != null;
25 |
26 | $list = SyncFileList::load();
27 | $argv->complete();
28 |
29 | foreach ( $list as $file )
30 | {
31 | $source = $file->sourceDir . '/' . $file->file;
32 | $target = $file->targetDir . '/' . $file->file;
33 | $output = new OutputBuffer( "# qaxml.a" , $target , $ignore );
34 |
35 | [ $s , $_ , $_ ] = XmlFrag::loadXmlFragmentFile( $source );
36 | [ $t , $_ , $_ ] = XmlFrag::loadXmlFragmentFile( $target );
37 |
38 | $s = XmlFrag::listNodes( $s , XML_ELEMENT_NODE );
39 | $t = XmlFrag::listNodes( $t , XML_ELEMENT_NODE );
40 |
41 | $s = extractTriple( $s );
42 | $t = extractTriple( $t );
43 |
44 | if ( implode( "\n" , $s ) == implode( "\n" , $t ) )
45 | continue;
46 |
47 | $sideCount = [];
48 |
49 | foreach( $s as $v )
50 | $sideCount[$v] = [ 0 , 0 ];
51 | foreach( $t as $v )
52 | $sideCount[$v] = [ 0 , 0 ];
53 |
54 | foreach( $s as $v )
55 | $sideCount[$v][0] += 1;
56 | foreach( $t as $v )
57 | $sideCount[$v][1] += 1;
58 |
59 | foreach( $sideCount as $k => $v )
60 | if ( $v[0] != $v[1] )
61 | $output->addDiff( $k , $v[0] , $v[1] );
62 |
63 | if ( $urgent )
64 | if ( $output->contains( "xml:id" ) == false )
65 | continue;
66 |
67 | $output->print();
68 | }
69 |
70 | function extractTriple( array $list )
71 | {
72 | $ret = [];
73 | foreach( $list as $elem )
74 | foreach( $elem->attributes as $attrib )
75 | $ret[] = "{$elem->nodeName} {$attrib->nodeName} {$attrib->nodeValue}";
76 | return $ret;
77 | }
78 |
--------------------------------------------------------------------------------
/docs/joining.md:
--------------------------------------------------------------------------------
1 | # Joining the team
2 |
3 | Joining the PHP Documentation team is a simple process, but a process nonetheless.
4 | You don't have to the join the team to [contribute](contributing.md),
5 | but joining the team can be a way to get more involved in the process
6 | and help out with larger projects.
7 |
8 | ## Write to a mailing list
9 | Because official communication is done there, you should write to the proper list.
10 | Say "Hi" and what you're interested in doing. You may feel more comfortable lurking
11 | for a while, or reading the archives, but ultimately let the list know who you are.
12 |
13 | ### For authors
14 | You should send your message to the `phpdoc@lists.php.net` mailing list. You
15 | will need to subscribe to the list in order to send email to it. You can find
16 | [archives of the list on news-web.php.net](https://news-web.php.net/php.doc),
17 | and there is also a form to subscribe to the list there.
18 |
19 | You can subscribe the regular version of the list (you get every
20 | message as it is sent), the digest version (you'll get a daily-or-so
21 | mail containing all of the new messages to the list), or the "no mail"
22 | version which allows you to send a message but doesn't send you any emails
23 | (useful if you just read through the web archive or an NNTP client).
24 |
25 | ### For translators
26 | You should send your message to the appropriate `doc-{LANG}@lists.php.net` mailing list.
27 |
28 | ## Informal discussion
29 | The mailing lists above are the primary communication forum. In particular,
30 | decisions and plans should be made on the list so they are recorded in the
31 | archives.
32 |
33 | However for more realtime and/or informal chat, some doc authors hang out in
34 | "Room 11" on Stackoverflow Chat: https://chat.stackoverflow.com/rooms/11/php
35 |
36 | Some authors hang out in the `#php-doc` channel on IRC on the
37 | https://Libera.Chat network, which is also bridged to the Discord server run
38 | by the PHP Community Foundation, available at https://phpc.chat.
39 |
40 | ## Create a doc patch or three
41 | This step is required to show us that you are a real human, you want to do
42 | some work and in general know how to do this.
43 |
44 | The simplest way to get started is by using GitHub, to create and send Pull Requests
45 | to [php/doc-en][doc-en] or php/doc-{LANG} for translations.
46 |
47 | Your Pull Requests will be then reviewed and accepted by someone with Git commit access.
48 |
49 | ## Obtaining Git commit access
50 | If you plan to contribute to the manual regularly and want to help process
51 | contributions from others, you might want to request to be added to the
52 | documentation team (or a translation team) on GitHub, which you can do on the
53 | email lists.
54 |
55 | To be clear: you don't need Git commit access to start contributing to the
56 | documentation! Anyone with a GitHub account (which is free) can submit Pull
57 | Requests to the documentation repositories.
58 |
59 | [doc-en]: https://github.com/php/doc-en
60 |
--------------------------------------------------------------------------------
/scripts/translation/lib/RevcheckFileList.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: General file transversal, ordered file listing. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class RevcheckFileList
23 | {
24 | private $list = [];
25 |
26 | function __construct( $lang )
27 | {
28 | $this->loadTree( $lang );
29 | }
30 |
31 | function get( $file ): RevcheckFileItem|null
32 | {
33 | return $this->list[ $file ] ?? null;
34 | }
35 |
36 | function iterator(): Iterator
37 | {
38 | return new ArrayIterator( $this->list );
39 | }
40 |
41 | function loadTree( $lang )
42 | {
43 | $dir = new \DirectoryIterator( $lang );
44 | if ( $dir === false )
45 | die( "$lang is not a directory.\n" );
46 | $cwd = getcwd();
47 | chdir( $lang );
48 | $this->loadTreeRecurse( $lang , "" );
49 | chdir( $cwd );
50 | }
51 |
52 | function loadTreeRecurse( $lang , $path )
53 | {
54 | $todoDirs = [];
55 | $dir = new DirectoryIterator( $path == "" ? "." : $path );
56 | if ( $dir === false )
57 | die( "$path is not a directory.\n" );
58 |
59 | foreach( $dir as $entry )
60 | {
61 | $name = $entry->getFilename();
62 | $key = ltrim( $path . '/' . $name , '/' );
63 | if ( $name[0] == '.' )
64 | continue;
65 | if ( $entry->isDir() )
66 | {
67 | $todoDirs[] = $key;
68 | continue;
69 | }
70 |
71 | if ( RevcheckIgnore::ignore( $key ) )
72 | continue;
73 | $file = new RevcheckFileItem( $key , $entry->getSize() );
74 | $this->list[ $key ] = $file;
75 | }
76 |
77 | sort( $todoDirs );
78 | foreach( $todoDirs as $path )
79 | $this->loadTreeRecurse( $lang , $path );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/scripts/grep-files.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php -q
2 | |
16 | +----------------------------------------------------------------------+
17 |
18 | $Id$
19 | */
20 |
21 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
22 | echo "This script requires a non-Windows operating system.\n";
23 | exit;
24 | }
25 |
26 | $editor = getenv('EDITOR');
27 |
28 | if ($_SERVER['argc'] == 2 &&
29 | in_array($_SERVER['argv'][1], array('--help', '-help', '-h', '-?'))
30 | ||
31 | $_SERVER['argc'] < 2) {
32 |
33 | echo "\nFind and edit files by grepping for a case insensitive string.\n";
34 | echo "I will open EDITOR if it's set, and the [language directory] is optional.\n\n";
35 | echo "Usage: {$_SERVER['argv'][0]} [langdir]\n";
36 | echo "Example: {$_SERVER['argv'][0]} 'PHP3' en\n";
37 | if ($editor) {
38 | echo "Note: Your EDITOR is set to: {$editor}\n\n";
39 | } else {
40 | echo "Note: You do not have an EDITOR set so I will output a string of files\n\n";
41 | }
42 | exit;
43 | }
44 |
45 | $langdir = '';
46 | if (!empty($_SERVER['argv'][2])) {
47 | $dir = trim($_SERVER['argv'][2]);
48 | if (is_dir($dir)) {
49 | $langdir = rtrim($dir, '/') . '/';
50 | } else {
51 | echo "INFO: The desired language directory ({$dir}) does not exist. Skipping...\n";
52 | }
53 | }
54 |
55 | $search_str = trim($_SERVER['argv'][1]);
56 | $output = trim(shell_exec("egrep --exclude=\*.svn\* -i -r '{$search_str}' {$langdir}* "));
57 |
58 | if (empty($output)) {
59 | echo "INFO: No matches for string '{$search_str}'\n";
60 | exit;
61 | }
62 |
63 | $files = array();
64 | foreach (explode("\n", $output) as $line) {
65 |
66 | $filename = trim(substr($line, 0, strpos($line, ':')));
67 | $ext = pathinfo($filename, PATHINFO_EXTENSION);
68 |
69 | if (($ext === 'xml' || $ext === 'ent') && $filename[0] !== '.') {
70 | $files[$filename] = 'open';
71 | }
72 | }
73 |
74 | if (empty($files)) {
75 | echo "INFO: No matches for string '{$search_str}'\n";
76 | exit;
77 | }
78 |
79 | $files_str = implode(' ', array_keys($files));
80 |
81 | if ($editor) {
82 | shell_exec($editor . ' ' . $files_str);
83 | } else {
84 | echo $files_str;
85 | }
86 |
--------------------------------------------------------------------------------
/scripts/mk_ini_set_table.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | # Quick hack to make a table of PHP options
4 | # and where they can be changed
5 | # Uses GNU grep and GNU awk
6 | # Author: Jesus M. Castagnetto
7 | # Created: Mon Mar 19 04:57:02 PST 2001
8 | # Updated: Thu Apr 25 11:42:26 PDT 2002
9 | # - look through all INI_ containing files
10 | # - save table in the new split dir for the function
11 | # Updated: Wed Nov 20 18:16:12 PST 2002
12 | # - rearrange the order of the tables, put the INI_* definitions first.
13 |
14 | cfiles=`grep -rl INI_ ../php4/*`
15 | ini_set_table="en/reference/info/functions/ini_set_table";
16 |
17 | awk 'BEGIN {
18 | print "";
19 | print " ";
20 | print " The INI_* constants used in the table below are defined as follows:";
21 | print " ";
22 | print " ";
23 | print " ";
24 | print " Constant";
25 | print " Value";
26 | print " Meaning";
27 | print "
";
28 | print " ";
29 | print " ";
30 | print " ";
31 | print " INI_USER";
32 | print " 1";
33 | print " Entry can be set in user scripts";
34 | print "
";
35 | print " ";
36 | print " INI_PERDIR";
37 | print " 2";
38 | print " Entry can be set in .htaccess";
39 | print "
";
40 | print " ";
41 | print " INI_SYSTEM";
42 | print " 4";
43 | print " Entry can be set in php.ini or";
44 | print " httpd.conf";
45 | print "
";
46 | print " ";
47 | print " INI_ALL";
48 | print " 7";
49 | print " Entry can be set anywhere";
50 | print "
";
51 | print " ";
52 | print "
";
53 | print " ";
54 | print "";
55 | print "\n Configuration options"
56 | print " ";
57 | print " ";
58 | print " ";
59 | print " Name";
60 | print " Default";
61 | print " Changeable";
62 | print "
";
63 | print " ";
64 | print " ";
65 | }
66 | $0 ~ /INI_.*\(/ && $0 !~ /^static/ && $0 !~ /INI_(BEGIN|END)/ {
67 | nf = split($0,tmp,",");
68 |
69 | varname = substr(tmp[1], index(tmp[1], "\""));
70 | gsub("\"", "", varname);
71 |
72 | vardef = tmp[2];
73 | gsub("(\t| )+", "", vardef);
74 | #if (index(vardef, "\""))
75 | # gsub("\"", "", vardef);
76 |
77 | varmod = tmp[3];
78 | gsub("(\t| )+", "", varmod);
79 |
80 | print " ";
81 | print " " varname ""
82 | print " " vardef ""
83 | print " " varmod ""
84 | print "
";
85 | };
86 | END {
87 | print " ";
88 | print " ";
89 | print "
";
90 | }' $cfiles > $ini_set_table
91 |
92 | ls -l $ini_set_table
93 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml.p.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Compare PIs usage between XMLs. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | echo "This tool is obsolete and will be REMOVED soon.\n";
21 | echo "See https://github.com/php/doc-base/blob/master/scripts/translation/README.md\n";
22 | echo "for alternatives.\n\n".
23 |
24 | require_once __DIR__ . '/lib/all.php';
25 |
26 | $qalist = QaFileInfo::cacheLoad();
27 |
28 | foreach ( $qalist as $qafile )
29 | {
30 | if ( $qafile->file == "bookinfo.xml" )
31 | continue;
32 | if ( $qafile->sourceHash != $qafile->targetHash )
33 | continue;
34 |
35 | $source = $qafile->sourceDir . '/' . $qafile->file;
36 | $target = $qafile->targetDir . '/' . $qafile->file;
37 |
38 | $s = XmlUtil::loadFile( $source );
39 | $t = XmlUtil::loadFile( $target );
40 |
41 | $s = XmlUtil::listNodeType( $s , XML_PI_NODE );
42 | $t = XmlUtil::listNodeType( $t , XML_PI_NODE );
43 |
44 | $s = extractPiData( $s );
45 | $t = extractPiData( $t );
46 |
47 | if ( implode( "\n" , $s ) == implode( "\n" , $t ) )
48 | continue;
49 |
50 | $header = true;
51 | $match = [];
52 |
53 | foreach( $s as $v )
54 | $match[$v] = array( 0 , 0 );
55 | foreach( $t as $v )
56 | $match[$v] = array( 0 , 0 );
57 |
58 | foreach( $s as $v )
59 | $match[$v][0] += 1;
60 | foreach( $t as $v )
61 | $match[$v][1] += 1;
62 |
63 | foreach( $match as $k => $v )
64 | {
65 | if ( $v[0] == $v[1] )
66 | continue;
67 |
68 | if ( $header )
69 | {
70 | print "qaxml.p: {$target}\n\n";
71 | $header = false;
72 | }
73 |
74 | print "* {$k} -{$v[1]} +{$v[0]}\n";
75 | }
76 |
77 | if ( ! $header )
78 | print "\n";
79 | }
80 |
81 | function extractPiData( array $list )
82 | {
83 | $ret = [];
84 | foreach( $list as $elem )
85 | $ret[] = "{$elem->target} {$elem->data}";
86 | return $ret;
87 | }
88 |
--------------------------------------------------------------------------------
/scripts/xml-check.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | |
16 | +----------------------------------------------------------------------+
17 |
18 | $Id$
19 | */
20 |
21 | if (!isset($_SERVER["argv"][1])) {
22 | echo "Purpose: Check XML syntax of single PHP manual file.\n";
23 | echo "Usage: xml-check.php filename.xml [xmllint-command]\n";
24 | echo "Note: Links are not checked.\n";
25 | exit();
26 | }
27 |
28 | $file = file_get_contents($_SERVER["argv"][1]);
29 | $xmllint = (isset($_SERVER["argv"][2]) ? $_SERVER["argv"][2] : "xmllint");
30 | $root = str_replace('\\', '/', dirname(__FILE__));
31 | $root = substr($root, 0, strrpos($root, '/'));
32 | $realpath = str_replace('\\', '/', realpath($_SERVER["argv"][1]));
33 | $example_filename = "$root/xml-check.xml";
34 | $rootpos = strlen($root) + 1;
35 | $language = substr($realpath, $rootpos, strpos($realpath, '/', $rootpos) - $rootpos);
36 | $header = preg_replace('~.*(]*>)(.*)~s', "\\1$header" . (!preg_match("~Example\\2\n" : "\\2") . "\n\n", $file);
40 | $fp = fopen($example_filename, "wb");
41 | fwrite($fp, $file);
42 | fclose($fp);
43 |
44 | passthru("XMLLINT_INDENT=' ' $xmllint --noent --noout --encode UTF-8 --format --valid $example_filename 2> $example_filename.out"); // xmllint outputs to stderr which is not catched by shell_exec, 2> &1 doesn't work on Windows
45 | $errors = file_get_contents("$example_filename.out");
46 | $errors = preg_replace("~.*validity error : IDREF attribute linkend references an unknown ID.*\n.*\n.*\n~", "", $errors);
47 | $errors = str_replace($example_filename, $_SERVER["argv"][1], $errors);
48 |
49 | if (empty($errors)) {
50 | echo "Success: Your file passed this XML check, do consider running 'make test' as well.\n";
51 | } else {
52 | echo "Errors: The following XML error exist:\n";
53 | echo $errors;
54 | }
55 |
56 | //~ unlink("$example_filename");
57 | unlink("$example_filename.out");
58 | ?>
59 |
--------------------------------------------------------------------------------
/scripts/build-chms-history.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | *
17 | * $Id$
18 | */
19 |
20 |
21 | /**
22 | * This script rebuilds build.log used by build-chms.php ($build_history)
23 | * without actually rebuilding the CHM files
24 | */
25 |
26 | /**
27 | * Configuration
28 | */
29 | include_once __DIR__ .'/build-chms-config.php';
30 |
31 | /**
32 | * The languages to build are retrieved from https://svn.php.net/repository/web/php/trunk/include/languages.inc
33 | */
34 | if (file_exists(__DIR__ . '\\languages.inc'))
35 | {
36 | unlink(__DIR__ . '\\languages.inc');
37 | }
38 |
39 | execute_task('Get list of online languages', PATH_WGET, '--debug --verbose --no-check-certificate https://svn.php.net/repository/web/php/trunk/include/languages.inc --output-document=' . __DIR__ . '\\languages.inc', false);
40 |
41 | if (file_exists(__DIR__ . '\\languages.inc'))
42 | {
43 | include_once __DIR__ . '\\languages.inc';
44 | }
45 |
46 | /**
47 | * Always build English first.
48 | */
49 | unset($ACTIVE_ONLINE_LANGUAGES['en']);
50 | ksort($ACTIVE_ONLINE_LANGUAGES);
51 |
52 | $ACTIVE_ONLINE_LANGUAGES = array('en' => 'English') + $ACTIVE_ONLINE_LANGUAGES;
53 |
54 | /**
55 | * Hold the results of this build
56 | */
57 | $build_history = array();
58 |
59 |
60 | foreach($ACTIVE_ONLINE_LANGUAGES as $lang_code => $language)
61 | {
62 | $chm_filename = PATH_CHM . '\\' . 'php_manual_' . $lang_code . '.chm';
63 | $e_chm_filename = PATH_CHM . '\\' . 'php_enhanced_' . $lang_code . '.chm';
64 |
65 | if(is_file($chm_filename))
66 | {
67 | $build_history[] = array('php_manual_' . $lang_code . '.chm', md5_file($chm_filename), filemtime($chm_filename));
68 | }
69 |
70 | if(is_file($e_chm_filename))
71 | {
72 | $build_history[] = array('php_enhanced_' . $lang_code . '.chm', md5_file($e_chm_filename), filemtime($e_chm_filename));
73 | }
74 | }
75 |
76 | /**
77 | * Save build history
78 | */
79 | file_put_contents(PATH_CHM . '\\build.log', implode(PHP_EOL, array_map(function($single_build)
80 | {
81 | return implode("\t", $single_build);
82 | }, $build_history)));
83 |
84 | echo(date('r') . ' Done!');
85 | ?>
--------------------------------------------------------------------------------
/scripts/translation/libqa/ArgvParser.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | This class coordinates and centrailzes control for $argv command line
19 | parameters, used between vairous classes. */
20 |
21 | class ArgvParser
22 | {
23 | private array $argv;
24 | private array $used;
25 |
26 | public function __construct( array $argv )
27 | {
28 | $this->argv = array_values( array_filter( $argv ) );
29 | $this->used = array_fill( 0 , count( $argv ) , false );
30 | }
31 |
32 | public function use( string $arg ) : void
33 | {
34 | foreach ( $this->argv as $pos => $value )
35 | if ( $arg == $value && $this->used[ $pos ] == false )
36 | {
37 | $this->used[ $pos ] = true;
38 | return;
39 | }
40 | throw new Exception( "Unused '$arg' not found." );
41 | }
42 |
43 | public function consume( string $equals = null , string $prefix = null , int $position = -1 ) : string|null
44 | {
45 | $args = $this->argv;
46 | foreach ( $args as $pos => $arg )
47 | {
48 | if ( $arg == null )
49 | continue;
50 |
51 | $foundByEquals = $equals != null && $arg == $equals;
52 | $foundByPrefix = $prefix != null && str_starts_with( $arg , $prefix );
53 | $foundByPosition = $position == $pos;
54 |
55 | if ( $foundByEquals || $foundByPrefix || $foundByPosition )
56 | {
57 | $this->argv[ $pos ] = null;
58 | $this->used[ $pos ] = true;
59 |
60 | if ( $foundByPrefix )
61 | return substr( $arg , strlen( $prefix ) );
62 |
63 | return $arg;
64 | }
65 | }
66 |
67 | return null;
68 | }
69 |
70 | public function complete() : void
71 | {
72 | foreach ( $this->argv as $pos => $arg )
73 | if ( $this->used[ $pos ] == false )
74 | fwrite( STDERR , "Unknown argument: {$arg}\n\n" );
75 | }
76 |
77 | public function residual() : array
78 | {
79 | return array_filter( $this->argv );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/scripts/translation/lib/RevcheckFileItem.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: General data of a file in a documentation tree. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class RevcheckFileItem
23 | {
24 | public string $file = ""; // from fs
25 | public int $size = 0 ; // from fs
26 | public int $date = 0 ; // from vcs, source only, date of head or diff commit
27 | public string $hashLast = ""; // derived by addGitLogData
28 | public string $hashDiff = ""; // derived by addGitLogData, isSyncHash
29 |
30 | public RevcheckStatus $status; // target only
31 | public RevtagInfo|null $revtag; // target only
32 |
33 | private array $hashList; // source only
34 | private bool $hashStop; // source only
35 |
36 | function __construct( string $file , int $size )
37 | {
38 | $this->file = $file;
39 | $this->size = $size;
40 | $this->date = 0;
41 | $this->status = RevcheckStatus::Untranslated;
42 | $this->revtag = null;
43 | $this->hashList = [];
44 | $this->hashStop = false;
45 | }
46 |
47 | public function addGitLogData( string $hash , string $date , bool $skip ) : void
48 | {
49 | // Accumulates valid hashes for RevcheckStatus::TranslatedOk status.
50 | // This includes topmost runs of [skip-revcheck] tags and one normal,
51 | // unmarked hash. Stop after first normal hash is found.
52 |
53 | if ( $this->hashStop )
54 | return;
55 |
56 | $this->hashList[] = $hash;
57 |
58 | if ( $this->hashLast == "" )
59 | {
60 | $this->date = $date;
61 | $this->hashLast = $hash;
62 | }
63 |
64 | if ( $skip )
65 | $this->hashDiff = $hash;
66 | else
67 | $this->hashStop = true;
68 | }
69 |
70 | public function isSyncHash( $hash ) : bool
71 | {
72 | $sync = in_array( $hash , $this->hashList );
73 | if ( $sync )
74 | $this->hashDiff = $hash;
75 | return $sync;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml.a.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Compare attributes between XMLs. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | echo "This tool is obsolete and will be REMOVED soon.\n";
21 | echo "See https://github.com/php/doc-base/blob/master/scripts/translation/README.md\n";
22 | echo "for alternatives.\n\n".
23 |
24 | require_once __DIR__ . '/lib/all.php';
25 |
26 | $qalist = QaFileInfo::cacheLoad();
27 |
28 | foreach ( $qalist as $qafile )
29 | {
30 | if ( $qafile->file == "bookinfo.xml" )
31 | continue;
32 | if ( $qafile->sourceHash != $qafile->targetHash )
33 | continue;
34 |
35 | $source = $qafile->sourceDir . '/' . $qafile->file;
36 | $target = $qafile->targetDir . '/' . $qafile->file;
37 |
38 | $s = XmlUtil::loadFile( $source );
39 | $t = XmlUtil::loadFile( $target );
40 |
41 | $s = XmlUtil::listNodeType( $s , XML_ELEMENT_NODE );
42 | $t = XmlUtil::listNodeType( $t , XML_ELEMENT_NODE );
43 |
44 | $s = extractTriple( $s );
45 | $t = extractTriple( $t );
46 |
47 | if ( implode( "\n" , $s ) == implode( "\n" , $t ) )
48 | continue;
49 |
50 | $header = true;
51 | $match = [];
52 |
53 | foreach( $s as $v )
54 | $match[$v] = array( 0 , 0 );
55 | foreach( $t as $v )
56 | $match[$v] = array( 0 , 0 );
57 |
58 | foreach( $s as $v )
59 | $match[$v][0] += 1;
60 | foreach( $t as $v )
61 | $match[$v][1] += 1;
62 |
63 | foreach( $match as $k => $v )
64 | {
65 | if ( $v[0] == $v[1] )
66 | continue;
67 |
68 | if ( $header )
69 | {
70 | print "qaxml.a: {$target}\n\n";
71 | $header = false;
72 | }
73 |
74 | print "* {$k} -{$v[1]} +{$v[0]}\n";
75 | }
76 |
77 | if ( ! $header )
78 | print "\n";
79 | }
80 |
81 | function extractTriple( array $list )
82 | {
83 | $ret = [];
84 | foreach( $list as $elem )
85 | foreach( $elem->attributes as $attrib )
86 | $ret[] = "{$elem->nodeName} {$attrib->nodeName} {$attrib->nodeValue}";
87 | return $ret;
88 | }
89 |
--------------------------------------------------------------------------------
/docs/user-notes.md:
--------------------------------------------------------------------------------
1 | # User Note Editing Guidelines
2 | These are some guidelines to follow when editing user notes in the manual.
3 |
4 | To begin editing user notes in the manual, you must have a PHP.net account, and you must either:
5 | - Subscribe to the `php-notes` mailing list or newsgroup. As a user submits a new user note, it will appear
6 | as a message on the mailing list with links in the footer of the email that enable you to delete, edit,
7 | or reject that particular note.
8 | - Log on to the server at https://main.php.net/manage/user-notes.php using your PHP.net account username and password.
9 | The user notes administration interface enables you to search for user notes that match particular strings
10 | and edit or change the status of particular notes directly through the Web interface.
11 |
12 | The thing that seems to confuse the most people is the difference between *rejecting* and *deleting* a note.
13 | Basically, they both remove the note from the manual, but *rejecting* sends the user an email about the rejection
14 | with links to support links and other information. Here are some guidelines of when to use each. You can also view
15 | the exact text of the rejection email [here](https://github.com/php/web-master/blob/master/manage/user-notes.php).
16 | - If the note is asking for help (support request, *Does this work...?*, etc.) or if the person is reporting a bug,
17 | *reject* the note. The email will show them the proper place to report such issues.
18 | - If the note contains useful information appropriate for the manual proper, you may incorporate the information
19 | into the manual and then *delete* the note.
20 | - If the note is in the wrong place, incorrect, a giant block of silly, unnecessary code, poorly written, an answer
21 | to another person's question, or just overall confusing, *delete* it. If it was an answer to a question, hunt down
22 | that note and *reject* it.
23 | - If the note is in a language other than English, *delete* the note.
24 | - If the note submitter's email address is obviously bogus, don't *reject* the note, just *delete* it.
25 | Rejecting the note just gives the mail server more work trying to send an email to a non-existent address,
26 | which doesn't help anything.
27 |
28 | If for some reason you need to add to a note, first ask yourself if it's worth it. Make sure you're not answering
29 | a user's question; if you are, then the note doesn't belong there (see above). If you're clarifying a point, see
30 | if it is appropriate to add the clarification to the manual proper; if it is, add it and *delete* the note (see above).
31 | If you still feel that adding your addition to the note will be the best option, then go ahead and add it. Usually, editors
32 | add their note in a "Editor's Note" block at the top. Unless you are correcting a minor error, make it obvious that you edited the note.
33 |
34 | If you have some free time and commit access to phpdoc, try going through some of the manual pages and adding some of
35 | the better notes into the documentation proper. Be sure to *delete* these notes after they're implemented.
36 |
37 | If you are in doubt about what to do with a note, you may ask for help on the `php-notes` mailing list (or `phpdoc`,
38 | if what you're doing involves the documentation proper).
39 |
--------------------------------------------------------------------------------
/scripts/translation/lib/XmlUtil.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: Misc funcionality dealing with raw XML. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | require_once __DIR__ . '/all.php';
21 |
22 | class XmlUtil
23 | {
24 | public static function extractEntities( $filename )
25 | {
26 | $was = libxml_use_internal_errors( true );
27 |
28 | $doc = new DOMDocument();
29 | $doc->recover = true;
30 | $doc->resolveExternals = false;
31 | $doc->load( $filename );
32 |
33 | $errors = libxml_get_errors();
34 | libxml_clear_errors();
35 | libxml_use_internal_errors( $was );
36 |
37 | $ret = [];
38 | foreach ($errors as $error)
39 | {
40 | if ( preg_match( "/Entity '(\S+)' not defined/" , $error->message , $matches ) )
41 | $ret[] = $matches[1];
42 | }
43 | return $ret;
44 | }
45 |
46 | public static function listNodeType( DOMNode $node , int $type )
47 | {
48 | $ret = [];
49 | XmlUtil::listNodeTypeRecurse( $node , $type , $ret );
50 | return $ret;
51 | }
52 |
53 | public static function listNodeTypeRecurse( DOMNode $node , int $type, array & $ret )
54 | {
55 | if ( $node->nodeType == $type )
56 | $ret[] = $node;
57 | foreach( $node->childNodes as $child )
58 | XmlUtil::listNodeTypeRecurse( $child , $type, $ret );
59 | }
60 |
61 | public static function loadFile( $filename ):DOMDocument
62 | {
63 | $contents = file_get_contents( $filename );
64 | return XmlUtil::loadText( $contents );
65 | }
66 |
67 | public static function loadText( $contents ):DOMDocument
68 | {
69 | $was = libxml_use_internal_errors( true );
70 |
71 | $doc = new DOMDocument();
72 | $doc->preserveWhiteSpace = true;
73 | $doc->recover = true;
74 | $doc->resolveExternals = false;
75 | $doc->substituteEntities = false;
76 |
77 | $doc->loadXML( $contents );
78 |
79 | libxml_clear_errors();
80 | libxml_use_internal_errors( $was );
81 |
82 | return $doc;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/docs/editing.md:
--------------------------------------------------------------------------------
1 | # Editing manual sources
2 |
3 | Before making any changes to the manual - either the English version or a
4 | translation, make sure you have read the [style guidelines](style.md)!
5 |
6 | ## Editing existing documentation
7 | Simply open the files and edit them.
8 |
9 | ## Adding new documentation
10 | When adding new functions or methods, there are a few options:
11 |
12 | ### Option A: Generating stub using `gen_stub.php`
13 | This is the new preferred way to generate files for new extensions, classes, functions
14 | or methods using [`gen_stub.php`][gen_stub]. The script is found in the [php-src][php-src]
15 | repository and uses the stub files to generate documentation (DocBook) files.
16 |
17 | ### Option B: Generating files using docgen
18 | This is the old preferred way to generate files for new extensions, classes, functions
19 | or methods using [`docgen`][docgen]. The script is found in the [doc-base][doc-base]
20 | repository and uses reflection to generate documentation (DocBook) files.
21 |
22 | ### Option C: Copy skeleton files
23 | This involves copying the skeleton files into the correct location:
24 | ```
25 | cp doc-base/skeletons/method.xml classname/methodname.xml #for new methods
26 | cp doc-base/skeletons/function.xml functions/functionname.xml #for new functions
27 | ```
28 |
29 | Note: *classname*, *methodname* and *functionname* are lowercased names of the
30 | class, method, or function, respectively, not a literal file name.
31 |
32 | Remember the extension folder [structure](structure.md) when copying those files.
33 |
34 | ## Translating documentation
35 | The translation process is described in the [translating chapter](translating.md).
36 |
37 | Changes in the English version are eventually picked up by the translators.
38 | If a change doesn't affect translations (e.g. fixing a typo in English) then the
39 | commit message should start with `[skip-revcheck]`.
40 |
41 | ## Validating your changes
42 | Every time you make changes to documentation sources (both English or translation),
43 | you have to validate your changes to ensure that the manual still builds without error.
44 | The necessary [configure.php][configure.php] script is distributed with the
45 | [doc-base][doc-base] repository, so you should already have it. All you have
46 | to do to validate changes is run configure.php:
47 | ```
48 | $ cd phpdoc
49 | $ php configure.php --with-lang={LANG}
50 | ```
51 | If your language is English you can omit the `with-lang` argument. When the above
52 | outputs something like `"All good. Saving .manual.xml… done."` then you know it validates.
53 | You can commit your changes now.
54 |
55 | ## Commit changes
56 | If you have the appropriate access to the repository, you can commit your modified files.
57 | Otherwise, create a Pull Request to have your changes reviewed by the team.
58 |
59 | ## Viewing changes online
60 | The documentation used on the PHP.net website is rebuilt every few hours from
61 | the latest source pushed to the documentation trees.
62 |
63 | Read more details in [the appendix on public builds](public-builds.md).
64 |
65 | [docgen]: https://github.com/php/doc-base/tree/master/scripts/docgen
66 | [doc-base]: https://github.com/php/doc-base/
67 | [gen_stub]: https://github.com/php/php-src/tree/master/build/gen_stub.php
68 | [php-src]: https://github.com/php/php-src/
69 | [configure.php]: https://github.com/php/doc-base/blob/master/configure.php
70 |
--------------------------------------------------------------------------------
/scripts/aspell.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | |
16 | +----------------------------------------------------------------------+
17 | */
18 |
19 | /*
20 | See en.pws for list of ignored words.
21 | */
22 |
23 | if ($_SERVER["argc"] != 3 || ($_SERVER["argv"][1] != "escape" && $_SERVER["argv"][1] != "unescape")) {
24 | exit("Purpose: Escape or unescape all *.xml files for use in aspell.\n"
25 | . "Usage: aspell.php escape|unescape \n"
26 | );
27 | }
28 |
29 | // TODO: &xxx.xx; -> &xxx-xx;
30 | $GOOD_TAGS = "type|parameter|function|refname|literal|methodname|abbrev|acronym|constant|varname|replaceable|filename|userinput|command|structname|structfield";
31 | $MODE = $_SERVER["argv"][1];
32 |
33 | // htmlentities in comments and CDATA
34 | function callback_htmlentities($matches) {
35 | return $matches[1] . ($GLOBALS["MODE"] == "escape" ? htmlentities($matches[2]) : html_entity_decode($matches[2])) . $matches[3];
36 | }
37 |
38 | // make attributes from contents of always-good tags
39 | function callback_make_value($matches) {
40 | return '<' . $matches[1] . $matches[2] . ' aspell="' . htmlentities($matches[3]) . '"/>';
41 | }
42 |
43 | // make contents from attributes of always-good tags
44 | function callback_make_contents($matches) {
45 | return '<' . $matches[1] . $matches[2] . '>' . html_entity_decode($matches[3]) . '' . $matches[1] . '>';
46 | }
47 |
48 | function recurse($dir) {
49 | echo "$dir\n";
50 | foreach (glob("$dir/*") as $filename) {
51 | if (is_dir($filename)) {
52 | recurse($filename);
53 | } elseif (preg_match('/\\.xml$/i', $filename)) {
54 | //~ echo "$filename\n";
55 | $file = file_get_contents($filename);
56 | $file = preg_replace_callback('~()~sU', "callback_htmlentities", $file);
57 | $file = preg_replace_callback('~()~sU', "callback_htmlentities", $file); // isn't in one function as it can match !CDATA[[...-->
58 | if ($GLOBALS["MODE"] == "escape") {
59 | $file = preg_replace_callback('~<(' . $GLOBALS['GOOD_TAGS'] . ')( [^>]*)?>(.*)\\1>~sU', "callback_make_value", $file);
60 | } else { // "unescape"
61 | $file = str_replace("\r", "", $file); // for Windows version of Aspell
62 | $file = preg_replace_callback('~<(' . $GLOBALS['GOOD_TAGS'] . ')( [^>]*)? aspell="(.*)"/>~sU', "callback_make_contents", $file);
63 | }
64 | $fp = fopen($filename, "wb");
65 | fwrite($fp, $file);
66 | fclose($fp);
67 | }
68 | }
69 | }
70 |
71 | recurse($_SERVER["argv"][2]);
72 | ?>
73 |
--------------------------------------------------------------------------------
/scripts/translation/qaxml-entities.php:
--------------------------------------------------------------------------------
1 | |
14 | +----------------------------------------------------------------------+
15 |
16 | # Description
17 |
18 | Compare XML entities usage between two XML leaf/fragment files. */
19 |
20 | require_once __DIR__ . '/libqa/all.php';
21 |
22 | $argv = new ArgvParser( $argv );
23 | $ignore = new OutputIgnore( $argv ); // may exit.
24 | $urgent = $argv->consume( "--urgent" ) != null;
25 |
26 | $ents = [];
27 | foreach( $argv->residual() as $ent )
28 | {
29 | if ( strlen( $ent ) > 2 && $ent[0] == '-' && $ent[1] != '-' )
30 | {
31 | $ents[] = '&' . substr( $ent , 1) . ';';
32 | $argv->use( $ent );
33 | }
34 | }
35 | $argv->complete();
36 |
37 | $list = SyncFileList::load();
38 |
39 | foreach ( $list as $file )
40 | {
41 | $source = $file->sourceDir . '/' . $file->file;
42 | $target = $file->targetDir . '/' . $file->file;
43 | $output = new OutputBuffer( "# qaxml.e" , $target , $ignore );
44 |
45 | [ $_ , $s , $_ ] = XmlFrag::loadXmlFragmentFile( $source );
46 | [ $_ , $t , $_ ] = XmlFrag::loadXmlFragmentFile( $target );
47 |
48 | adornEntities( $s );
49 | adornEntities( $t );
50 |
51 | if ( implode( "\n" , $s ) == implode( "\n" , $t ) )
52 | continue;
53 |
54 | $sideCount = [];
55 |
56 | foreach( $s as $v )
57 | $sideCount[$v] = [ 0 , 0 ];
58 | foreach( $t as $v )
59 | $sideCount[$v] = [ 0 , 0 ];
60 |
61 | foreach( $s as $v )
62 | $sideCount[$v][0] += 1;
63 | foreach( $t as $v )
64 | $sideCount[$v][1] += 1;
65 |
66 | foreach( $sideCount as $ent => $_ )
67 | if ( in_array( $ent , $ents ) )
68 | $sideCount[ $ent ] = [ 0 , 0 ];
69 |
70 | foreach( $sideCount as $k => $v )
71 | if ( $v[0] != $v[1] )
72 | $output->addDiff( $k , $v[0] , $v[1] );
73 |
74 | if ( $urgent )
75 | {
76 | $count = 0;
77 | if ( $output->contains( "&chapters" ) )
78 | $count++;
79 | if ( $output->contains( "&features" ) )
80 | $count++;
81 | if ( $output->contains( "&language" ) )
82 | $count++;
83 | if ( $output->contains( "&reference" ) )
84 | $count++;
85 | if ( $output->contains( "&security" ) )
86 | $count++;
87 | if ( $count == 0 )
88 | continue;
89 | }
90 |
91 | $output->print();
92 | }
93 |
94 | function adornEntities( array & $list )
95 | {
96 | foreach( $list as & $item )
97 | $item = '&' . $item . ';';
98 | }
--------------------------------------------------------------------------------
/skeletons/exceptionname.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The ExceptionName class
4 | ExceptionName
5 |
6 |
7 |
8 |
9 |
10 | &reftitle.intro;
11 |
12 | Description of the exception.
13 |
14 |
15 |
16 |
17 |
18 | &reftitle.classsynopsis;
19 |
20 |
21 |
22 |
23 | ExceptionName
24 |
25 |
26 |
27 |
28 | extends
29 | BaseExceptionName
30 |
31 |
32 |
33 | &Methods;
34 |
35 | &Methods;
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
54 | &InheritedMethods;
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
66 |
67 |
68 |
88 |
--------------------------------------------------------------------------------
/scripts/orphan_notes.php:
--------------------------------------------------------------------------------
1 | |
15 | +----------------------------------------------------------------------+
16 |
17 | $Id$
18 | */
19 |
20 | /*
21 | * This script searches for orphan notes.
22 | * You need a phpweb checkout with, at least,
23 | * manual/en and backend/notes folders
24 | */
25 |
26 |
27 | /* Configuration Options */
28 |
29 | $manual_dir = 'manual/en';
30 | $notes_dir = 'backend/notes';
31 |
32 | /******* END of configurations *****/
33 |
34 |
35 | /* Collect manual IDs */
36 | function recurse_manual($dir) {
37 | global $array;
38 |
39 | if ($dh = opendir($dir)) {
40 | while (($file = readdir($dh)) !== false) {
41 |
42 | if($file != '.' && $file != '..') {
43 | $path = $dir.'/'.$file;
44 |
45 | if(is_dir($path)) {
46 | recurse_manual($path);
47 | } else {
48 | $array[substr(md5(substr($path, $GLOBALS['len'], -4)), 0, 16)] = 1;
49 | }
50 |
51 | }
52 | }
53 | closedir($dh);
54 | }
55 | }
56 |
57 |
58 | /* Search for bogus notes IDs */
59 | function recurse_notes($dir) {
60 | global $array, $files, $notes;
61 |
62 | if ($dh = opendir($dir)) {
63 | while (($file = readdir($dh)) !== false) {
64 |
65 | if($file != '.' && $file != '..' && substr($file, -4) != '.bz2') {
66 | $path = $dir.'/'.$file;
67 |
68 | if(is_dir($path)) {
69 | recurse_notes($path);
70 | } else {
71 | if(!isset($array[$file]) && $file != 'last-updated' && $file != 'sections') {
72 | echo "file: $path\n";
73 |
74 | $fp = fopen($path, "r");
75 | while (!feof($fp)) {
76 | $line = chop(fgets($fp, 12288));
77 | if ($line == "") { continue; }
78 |
79 | list($id, $sect, , , , ) = explode("|", $line);
80 | ++$notes;
81 |
82 | if (!isset($done)) {
83 | $done = 1;
84 | echo "old ID: $sect\nNotes IDs: $id";
85 |
86 | } else {
87 | echo ", $id";
88 | }
89 | }
90 | echo "\n\n";
91 | ++$files;
92 | }
93 |
94 | unset($done);
95 | }
96 | }
97 | }
98 | closedir($dh);
99 | }
100 | }
101 |
102 | $array = array();
103 | $len = strlen("$manual_dir/");
104 | $files = $notes = 0;
105 |
106 | recurse_manual($manual_dir);
107 | recurse_notes($notes_dir);
108 |
109 |
110 | echo "\nTotal files: $files\nTotal notes: $notes";
111 | ?>
112 |
--------------------------------------------------------------------------------
/htmlhelp/local_vars.php.src:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scripts/include/lib-translations.inc.php:
--------------------------------------------------------------------------------
1 | |
15 | | Some code stolen from other phpdoc/scripts/ |
16 | +----------------------------------------------------------------------+
17 |
18 | $Id$
19 |
20 | Introduction:
21 |
22 | This library is used by translation related scripts within
23 | the PHP Documentation repository.
24 |
25 | Usage examples:
26 |
27 | // Should this file be translated?
28 | if (!is_translatable ($filename)) {
29 | exit;
30 | }
31 |
32 | // Is the translation considered current?
33 | if (!is_translation_current ($file_en, $file_lang)) {
34 | exit;
35 | }
36 |
37 | */
38 |
39 | function is_translation_current ($filename_en, $filename_lang) {
40 |
41 | if (!is_readable ($filename_en)) {
42 | trigger_error("File ($filename_en) is not readable", E_USER_WARNING);
43 | return false;
44 | }
45 | if (!is_readable ($filename_lang)) {
46 | trigger_error("File ($filename_lang) is not readable", E_USER_WARNING);
47 | return false;
48 | }
49 |
50 | $en = file_get_contents($filename_en);
51 | $lang = file_get_contents($filename_lang);
52 |
53 | $match_en = $match_lang = array();
54 |
55 | preg_match ("//", $en, $match_en);
56 | preg_match ("/
37 |
38 |
39 |
40 |
41 |
42 |
43 | &date.timezone.intro.title;
44 | &date.timezone.intro;
45 |
48 |
49 |
50 |
51 | &date.timezone.dbversion; .
52 |
53 |
54 | $zones) {
58 | $groupColumns = $columns;
59 | $m = count($zones) > ($groupColumns-1) ? $groupColumns : count($zones); ?>
60 |
61 |
62 |
63 |
64 |
65 | &date.timezone.bc;
66 |
67 |
68 | &date.timezone.posix-signs;
69 |
70 |
71 |
72 |
73 |
74 |
75 | ", PHP_EOL;
80 | }
81 | $c++;
82 | echo " {$zone}", PHP_EOL;
83 | if ($c % $m == 0) {
84 | echo " ", PHP_EOL;
85 | }
86 | }
87 | if ($c % $m != 0) {
88 | while($c++ % $m != 0) {
89 | echo " ", PHP_EOL;
90 | }
91 | echo " ", PHP_EOL;
92 | }
93 | ?>
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
121 |
122 |
--------------------------------------------------------------------------------
/scripts/script-skel.php:
--------------------------------------------------------------------------------
1 | |
15 | +----------------------------------------------------------------------+
16 | */
17 |
18 | if (PHP_SAPI !== 'cli') {
19 | echo "This script is ment to be run under CLI\n";
20 | exit(1);
21 | }
22 |
23 | if ($_SERVER['argc'] == 2 &&
24 | in_array($_SERVER['argv'][1], array('--help', '-help', '-h', '-?'))
25 | ||
26 | $_SERVER['argc'] < 2) {
27 |
28 | echo "\n\n";
29 | echo "Usage: {$_SERVER['argv'][0]} \n";
30 | echo " --help, -help, -h, -? - to get this help\n";
31 | die;
32 |
33 | }
34 |
35 | // Ensure the trailing /
36 | $fullpath_dir = rtrim($_SERVER['argv'][1], '/').'/';
37 |
38 | if (!is_dir($fullpath_dir)) {
39 | echo "ERROR: ($fullpath_dir) is not a directory.\n";
40 | exit(1);
41 | }
42 |
43 |
44 | $log = array('nonfiles' => array(),
45 | 'error' => array(),
46 | 'rewritten' => array());
47 |
48 | // Start the processing
49 | list_files($fullpath_dir, '', $log);
50 |
51 |
52 |
53 | echo count($log['rewritten'])." file(s) have been affected.\n";
54 | if (!empty($log['error'])) {
55 | echo count($log['error'])." error(s) occured:\n";
56 | foreach($log['error'] as $error) {
57 | echo " $error\n";
58 | }
59 | }
60 |
61 |
62 | /**
63 | * List files recursivly and scan them
64 | *
65 | * @return bool
66 | */
67 | function list_files($prefix, $path, &$userdata)
68 | {
69 |
70 | if (is_dir($prefix.$path) && is_resource($handle = @opendir($prefix.$path))) {
71 |
72 | while ($name = readdir($handle)) {
73 | if (strpos($name, ".xml") !== false) {
74 | scan_file($prefix, $path.$name, $userdata);
75 | } else if(is_dir($prefix.$path.$name) && $name !== 'CVS' && $name !== '.' && $name !== '..') {
76 | list_files($prefix, $path.$name.DIRECTORY_SEPARATOR, $userdata);
77 | }
78 |
79 | }
80 |
81 | closedir($handle);
82 | return true;
83 |
84 | } else {
85 | return false;
86 | }
87 |
88 | }
89 |
90 | /**
91 | * Scan files for examples, and insert them
92 | *
93 | * @return null
94 | */
95 | function scan_file($prefix, $path, &$userdata)
96 | {
97 |
98 | if (!is_file($prefix.$path)) {
99 | $userdata['nonfiles'][] = $path;
100 | return false;
101 | }
102 |
103 | $content = file_get_contents($prefix.$path);
104 | echo "scanning $path\n";
105 | if ($number = preg_match_all('/regex/', $content, $matches)) {
106 |
107 | // Process
108 |
109 | $userdata['rewritten'][] = $path;
110 | }
111 |
112 | }
113 |
114 |
--------------------------------------------------------------------------------
/docs/structure.md:
--------------------------------------------------------------------------------
1 | # Documentation structure
2 |
3 | The PHP Manual sources are stored in Git repositories.
4 |
5 | To checkout the PHP Manual sources, follow the steps in [Setting up a documentation environment](local-setup.md)
6 |
7 | ## File structure
8 |
9 | **Note for translators:** if any of the source files don't exist in your translation, the English content will be used
10 | during the building process. This means that you *must not* place untranslated files in your translation tree. Otherwise,
11 | it will lead to a mess, confusion and may break some tools.
12 |
13 | The structure of the manual sources is hopefully rather intuitive. The most
14 | complicated part is the documentation for extensions, which is also the biggest
15 | part of the manual as all functions are grouped into extensions.
16 |
17 | The documentation for extensions is located in `reference/extension_name/`. For example,
18 | the calendar extension documentation exists in `reference/calendar/`. There you'll find several files:
19 | - *book.xml* - acts as the container for the extension and contains the preface. Other files (like examples.xml)
20 | are included from here.
21 | - *setup.xml* - includes setup, install and configuration documentation
22 | - *constants.xml* - lists all constants that the extension declares, if any
23 | - *configure.xml* - usually this information is in setup.xml, but if the file exists it is magically
24 | included into setup.xml
25 | - *examples.xml* - various examples
26 | - *versions.xml* - contains version information for the extension
27 | - *foo.xml* - example, foo can be anything specific to a topic. Just be sure to include via book.xml.
28 |
29 | A procedural extension (like calendar) also has:
30 | - *reference.xml* - container for the functions, rarely contains any info
31 | - *functions/* - folder with one XML file per function that the extension declares
32 |
33 | And OO extensions (such as imagick) contain:
34 | - *classname.xml* - container for the methods defined by the class, contains also basic info about it
35 | - *classname/* - folder with one XML file per method that the class declares
36 |
37 | Note: *classname* is the lowercased name of the class, not a literal file or directory name.
38 |
39 | There are some other important files:
40 | - *language-defs.ent* - contains local entities used by this language. Some common ones are
41 | the main part titles, but you should also put entities used only by this language's files here.
42 | - *language-snippets.ent* - longer often used XML snippets translated to this language.
43 | Including common warnings, notes, etc.
44 | - *translation.xml* - this file is used to store all central translation info, like a small
45 | intro text for translators and the persons list. This file is not present in the English tree.
46 |
47 | ## `xml:id` structure
48 |
49 | The PHP Manual is complex, and uses `xml:id`s extensively, for various
50 | purposes. So some care is necessary to avoid failures.
51 | There are two types of `xml:id`s used in manuals.
52 |
53 | * **Structural IDs:** IDs that are present on structural elements of
54 | DocBook XML (like ``, `` and so on), that are used for
55 | linking and chunking;
56 |
57 | * **XInclude IDs:** IDs that are used as target of XIncludes.
58 |
59 | Structural IDs are in the pattern `id.id` (always one dot as separator),
60 | while XInclude IDs use the pattern `structural.id..local.name`. That is,
61 | for Structural IDs the name parts are separated with a *single* dot, while
62 | XInclude IDs are composed of an Structural ID prefix, a *double* dot separator,
63 | and a named suffix.
64 |
65 | The `configure.php` script will remove any duplicated IDs found. Without
66 | warnings in the case of XInclude IDs, so it is possible to use XInclude
67 | IDs elsewhere, and will warn about duplicate Structural IDs.
68 |
--------------------------------------------------------------------------------
/scripts/fetch-chms.php:
--------------------------------------------------------------------------------
1 | $realfilename)\n");
22 |
23 | $dlsize = fetch("$BUILDDIR/$filename", $tmpfilename);
24 | if (!$dlsize) {
25 | $err = error_get_last();
26 | err($err["message"], $filename);
27 | continue;
28 | }
29 | debug("Fetched $dlsize");
30 |
31 | $realhash = md5_file($tmpfilename);
32 | if ($realhash != $hash) {
33 | err("\nMD5 Failed for $filename ($realhash != $hash)\n");
34 | continue;
35 | }
36 | debug("\nMD5 OK");
37 |
38 | debug("Renaming $tmpfilename to $realfilename");
39 | rename($tmpfilename, $realfilename);
40 | debug("All done with $filename");
41 | }
42 |
43 | $errors = err();
44 | if ($errors) {
45 | mail("phpdoc@lists.php.net", "Errors copying CHM files", var_export($errors, true), "From: phpdoc@lists.php.net\r\n", "-fnoreply@php.net");
46 | return 2;
47 | }
48 |
49 |
50 | function err($error = null) {
51 | static $errors = array();
52 | if ($error) {
53 | $errors[] = $error;
54 | }
55 | return $errors;
56 | }
57 | function debug($msg) {
58 | if (DEBUG) {
59 | echo $msg, "\n";
60 | }
61 | }
62 | function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
63 | static $filesize = null;
64 |
65 | switch($notification_code) {
66 | case STREAM_NOTIFY_RESOLVE:
67 | case STREAM_NOTIFY_AUTH_REQUIRED:
68 | case STREAM_NOTIFY_COMPLETED:
69 | case STREAM_NOTIFY_FAILURE:
70 | case STREAM_NOTIFY_AUTH_RESULT:
71 | /* Ignore */
72 | break;
73 |
74 | case STREAM_NOTIFY_REDIRECTED:
75 | debug("Being redirected to: ". $message);
76 | break;
77 |
78 | case STREAM_NOTIFY_CONNECT:
79 | debug("Connected...");
80 | break;
81 |
82 | case STREAM_NOTIFY_FILE_SIZE_IS:
83 | $filesize = $bytes_max;
84 | debug("Filesize: ". $filesize);
85 | break;
86 |
87 | case STREAM_NOTIFY_MIME_TYPE_IS:
88 | debug("Mime-type: ". $message);
89 | break;
90 |
91 | case STREAM_NOTIFY_PROGRESS:
92 | if ($bytes_transferred > 0) {
93 | if (DEBUG) {
94 | if (!isset($filesize)) {
95 | printf("\rUnknown filesize.. %2d kb done..", $bytes_transferred/1024);
96 | } else {
97 | $length = (int)(($bytes_transferred/$filesize)*100);
98 | printf("\r[%-100s] %d%% (%2d/%2d kb)", str_repeat("=", $length). ">", $length, ($bytes_transferred/1024), $filesize/1024);
99 | }
100 | }
101 | }
102 | break;
103 | }
104 | }
105 |
106 | function fetch($filename, $outputname) {
107 | debug("Fetching $filename");
108 | $ctx = stream_context_create(null, array("notification" => "stream_notification_callback"));
109 |
110 | $fp = fopen($filename, "r", false, $ctx);
111 | if (!is_resource($fp)) {
112 | err("Fetch failed");
113 | return 0;
114 | }
115 | return file_put_contents($outputname, $fp);
116 | }
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/scripts/translation/lib/RevcheckData.php:
--------------------------------------------------------------------------------
1 | |
15 | * +----------------------------------------------------------------------+
16 | * | Description: DTO for serialization of revcheck data. |
17 | * +----------------------------------------------------------------------+
18 | */
19 |
20 | enum RevcheckStatus : string
21 | {
22 | case TranslatedOk = 'TranslatedOk';
23 | case TranslatedOld = 'TranslatedOld';
24 | case TranslatedWip = 'TranslatedWip';
25 | case RevTagProblem = 'RevTagProblem';
26 | case NotInEnTree = 'NotInEnTree';
27 | case Untranslated = 'Untranslated';
28 | }
29 |
30 | class RevcheckData
31 | {
32 | public string $lang = "";
33 | public string $date = "";
34 | public string $intro = "";
35 | public $translators = []; // nick => RevcheckDataTranslator
36 | public $fileSummary = []; // RevcheckStatus => int
37 | public $fileDetail = []; // filename => RevcheckDataFile
38 |
39 | public function __construct()
40 | {
41 | foreach ( RevcheckStatus::cases() as $status )
42 | $this->fileSummary[ $status->value ] = 0;
43 | }
44 |
45 | public function addFile( string $key , RevcheckDataFile $file )
46 | {
47 | $this->fileDetail[ $key ] = $file;
48 | $this->fileSummary[ $file->status->value ]++;
49 | }
50 |
51 | public function getTranslator( string $nick )
52 | {
53 | $translator = $this->translators[ $nick ] ?? null;
54 | if ( $translator == null )
55 | {
56 | $translator = new RevcheckDataTranslator();
57 | $translator->nick = $nick;
58 | $this->translators[ $nick ] = $translator;
59 | }
60 | return $translator;
61 | }
62 |
63 | public function getSummaryLabels() : array
64 | {
65 | $ret[ RevcheckStatus::TranslatedOk->value ] = "Up to date files";
66 | $ret[ RevcheckStatus::TranslatedOld->value ] = "Outdated files";
67 | $ret[ RevcheckStatus::TranslatedWip->value ] = "Work in progress";
68 | $ret[ RevcheckStatus::RevTagProblem->value ] = "Revision tag missing/problem";
69 | $ret[ RevcheckStatus::NotInEnTree->value ] = "Not in EN tree";
70 | $ret[ RevcheckStatus::Untranslated->value ] = "Available for translation";
71 | return $ret;
72 | }
73 | }
74 |
75 | class RevcheckDataTranslator
76 | {
77 | public string $name = "";
78 | public string $email = "";
79 | public string $nick = "";
80 | public string $vcs = "";
81 |
82 | public int $countOk = 0;
83 | public int $countOld = 0;
84 | public int $countOther = 0;
85 | }
86 |
87 | class RevcheckDataFile
88 | {
89 | public string $path;
90 | public string $name;
91 | public int $size;
92 | public int $days;
93 | public int $adds = 0;
94 | public int $dels = 0;
95 |
96 | public RevcheckStatus $status;
97 | public string $maintainer = "";
98 | public string $completion = "";
99 |
100 | public string $hashLast; // The most recent commit hash, skipped or not
101 | public string $hashDiff; // The most recent, non [skip-revcheck] commit hash
102 | public string $hashRvtg = ""; // Revtag hash, if any
103 | }
104 |
--------------------------------------------------------------------------------