diff --git a/package_php.xml b/package_php.xml
index 59c3292..a664581 100644
--- a/package_php.xml
+++ b/package_php.xml
@@ -44,6 +44,7 @@
Prepare CHM rendering to use the new CSS rules (Richard Quadling)
Disply a message when loading an external stylesheet (Richard Quadling)
Incorporate stylesheet names supplied at the command line into the CHM file (Richard Quadling)
+ New output format EnhancedCHM - the same as CHM but with the User Notes (Requires bzip2.exe) (Richard Quadling)
@@ -67,6 +68,7 @@
+
diff --git a/phpdotnet/phd/Package/PHP/CHM.php b/phpdotnet/phd/Package/PHP/CHM.php
index 33b694a..44e9b48 100644
--- a/phpdotnet/phd/Package/PHP/CHM.php
+++ b/phpdotnet/phd/Package/PHP/CHM.php
@@ -199,7 +199,7 @@ class Package_PHP_CHM extends Package_PHP_ChunkedXHTML
public function __construct() {
parent::__construct();
- $this->registerFormatName("PHP-CHM");
+ $this->registerFormatName("PHP-CHM");
}
public function __destruct() {
@@ -247,7 +247,7 @@ class Package_PHP_CHM extends Package_PHP_ChunkedXHTML
$stylesheet = $this->fetchStylesheet() . PHP_EOL;
}
- file_put_contents($this->outputdir . "style.css", $stylesheet . 'body { padding : 3px;}');
+ file_put_contents($this->outputdir . "style.css", $stylesheet . 'body {padding : 3px;}' . PHP_EOL . '#usernotes {margin-left : inherit;}' . PHP_EOL);
self::headerChm();
break;
@@ -402,12 +402,12 @@ res' . DIRECTORY_SEPARATOR . 'style.css
$header = parent::header($id);
$patterns = array(
- '/(.*)(\r|\n|\r\n|\n\r)(.*)<\/head>/', // Add CSS link to
+ '/(.*)(\r|\n|\r\n|\n\r)(.*)<\/head>/', // Add CSS link and to .
'/($2$3',
+ '$1 $2 $2$3',
'$1 class="docs"',
);
diff --git a/phpdotnet/phd/Package/PHP/EnhancedCHM.php b/phpdotnet/phd/Package/PHP/EnhancedCHM.php
new file mode 100644
index 0000000..0ed2e9b
--- /dev/null
+++ b/phpdotnet/phd/Package/PHP/EnhancedCHM.php
@@ -0,0 +1,173 @@
+registerFormatName("PHP-EnhancedCHM");
+ }
+
+ public function update($event, $val = null) {
+ switch($event) {
+ case Render::INIT:
+ parent::update($event, $val);
+
+ // Get http://www.php.net/backend/notes/all.bz2 and save it.
+ v('Downloading usernotes.', VERBOSE_MESSAGES);
+ if (false === ($userNotesArchive = file_get_contents('http://www.php.net/backend/notes/all.bz2'))) {
+ v('Failed to download usernotes.', E_USER_ERROR);
+ break;
+ }
+
+ // Save the usernotes.
+ v('Saving usernotes.', VERBOSE_MESSAGES);
+ if (false === file_put_contents(Config::output_dir() . 'all.bz2', $userNotesArchive)) {
+ v('Failed to save usernotes.', E_USER_ERROR);
+ break;
+ }
+
+ // Decompress the usernotes.
+ v('Decompressing usernotes.', VERBOSE_MESSAGES);
+ if (false === strpos(exec('bzip2.exe -dfkv ' . Config::output_dir() . 'all.bz2 2>&1'), 'all.bz2: done')) {
+ v('Failed to decompress usernotes.' . PHP_EOL . implode(PHP_EOL, $output), E_USER_ERROR);
+ break;
+ }
+
+ // Extract the usernotes and store them by page and date.
+ v('Preparing usernotes.', VERBOSE_MESSAGES);
+
+ // Create usernotes directory.
+ $this->userNotesDir = Config::output_dir() . 'usernotes' . DIRECTORY_SEPARATOR;
+ if(!file_exists($this->userNotesDir) || is_file($this->userNotesDir)) {
+ mkdir($this->userNotesDir) or v("Can't create the usernotes directory", E_USER_ERROR);
+ }
+
+ // Remove any existing files.
+ foreach(glob($this->userNotesDir . '*' . DIRECTORY_SEPARATOR . '*') as $sectionFile) {
+ unlink($sectionFile);
+ }
+
+ // Decompress the 'all' file into single files - one file per sectionid.
+ $userNotesFile = fopen(Config::output_dir() . 'all', 'rt');
+ while($userNotesFile && !feof($userNotesFile) && false !== ($userNote = fgetcsv($userNotesFile, 0, '|'))) {
+ // Usernote index
+ // 0 = Note ID
+ // 1 = Section ID
+ // 2 = Rate
+ // 3 = Timestamp
+ // 4 = User
+ // 5 = Note
+
+ $sectionHash = md5($userNote[1]);
+ $sectionDir = $this->userNotesDir . $sectionHash[0];
+
+ if (!file_exists($sectionDir)) {
+ mkdir($sectionDir);
+ }
+
+ file_put_contents($sectionDir . DIRECTORY_SEPARATOR . $sectionHash, implode('|', $userNote) . PHP_EOL, FILE_APPEND);
+ }
+
+ fclose($userNotesFile);
+
+ $this->haveNotes = true;
+ v('Usernotes prepared.', VERBOSE_MESSAGES);
+
+ // Use classes rather than colors.
+ ini_set('highlight.comment', 'comment');
+ ini_set('highlight.default', 'default');
+ ini_set('highlight.keyword', 'keyword');
+ ini_set('highlight.string', 'string');
+ ini_set('highlight.html', 'html');
+
+ break;
+
+ default:
+ parent::update($event, $val);
+ }
+ }
+
+ public function footer($id) {
+ $footer = parent::footer($id);
+
+ // Find usernotes file.
+ $idHash = md5($id);
+ $userNotesFile = $this->userNotesDir . $idHash[0] . DIRECTORY_SEPARATOR . $idHash;
+
+ if (!file_exists($userNotesFile)) {
+ $notes = '
There are no user contributed notes for this page.
';
+ } else {
+ $notes = '';
+
+ foreach(file($userNotesFile) as $userNote) {
+ list($noteId, $noteSection, $noteRate, $noteTimestamp, $noteUser, $noteText) = explode('|', $userNote);
+
+ if ($noteUser) {
+ $noteUser = '' . htmlspecialchars($noteUser) . '';
+ }
+ $noteDate = '' . date("d-M-Y h:i", $noteTimestamp) . '';
+ $anchor = '';
+
+ $noteText = str_replace(
+ array(
+ ' ',
+ '
',
+ '',
+ "\n ",
+ ' ',
+ ' '
+ ),
+ array(
+ ' ',
+ "
\n",
+ '',
+ "\n ",
+ ' ',
+ ' '
+ ),
+ preg_replace(
+ '!((mailto:|(http|ftp|nntp|news):\/\/).*?)(\s|<|\)|"|\\\\|\'|$)!',
+ '\1\4',
+ highlight_string(trim(base64_decode($noteText)), true))
+ );
+
+ $notes .= <<< END_NOTE
+ {$anchor}
+
+ {$noteUser}
+ {$noteDate}
+
+
+
+
+END_NOTE;
+ }
+
+ $notes = '' . $notes . '
';
+ }
+
+ return <<< USER_NOTES
+
+
+
User Contributed Notes
+
+{$notes}
+
+{$footer}
+USER_NOTES;
+
+ }
+}
diff --git a/phpdotnet/phd/Package/PHP/Factory.php b/phpdotnet/phd/Package/PHP/Factory.php
index 58e2120..67857b6 100644
--- a/phpdotnet/phd/Package/PHP/Factory.php
+++ b/phpdotnet/phd/Package/PHP/Factory.php
@@ -15,6 +15,7 @@ class Package_PHP_Factory extends Format_Factory {
'chm' => 'Package_PHP_CHM',
'tocfeed' => 'Package_PHP_TocFeed',
'epub' => 'Package_PHP_Epub',
+ 'enhancedchm' => 'Package_PHP_EnhancedCHM',
);
public function __construct() {