diff --git a/admin/class-steempress_sp-admin.php b/admin/class-steempress_sp-admin.php
index 57a22da..7ae6430 100755
--- a/admin/class-steempress_sp-admin.php
+++ b/admin/class-steempress_sp-admin.php
@@ -19,6 +19,11 @@
* @package Steempress_sp
* @subpackage Steempress_sp/admin
*/
+
+require('partials/domlettersiterator.php');
+require('partials/DOMWordsIterator.php');
+require('partials/TruncateHTML.php');
+
class Steempress_sp_Admin {
/**
@@ -152,6 +157,7 @@ public function validate($input) {
$valid['twoway'] = ((isset($input['twoway']) && !empty($input['twoway'])) && $input['twoway'] == 'on') ? 'on' : "off";
$valid['twoway-front'] = ((isset($input['twoway-front']) && !empty($input['twoway-front'])) && $input['twoway-front'] == 'on') ? 'on' : "off";
$valid['update'] = ((isset($input['update']) && !empty($input['update'])) && $input['update'] == 'on') ? 'on' : "off";
+ $valid['wordlimit'] = ((isset($input['wordlimit']) && !empty($input['wordlimit']) && is_numeric($input['wordlimit']) && $input['wordlimit'] >= 0)) ? htmlspecialchars($input['wordlimit'], ENT_QUOTES) : "0";
$users = get_users();
@@ -206,7 +212,10 @@ public function Steempress_sp_publish($id)
$options["featured"] = "on";
if (!isset($options["footer"]))
$options["footer"] = "
Posted from my blog with SteemPress : [%original_link%]
";
-
+ if (!isset($options["wordlimit"]))
+ $options["wordlimit"] = "0";
+
+
$post = get_post($id);
@@ -273,6 +282,10 @@ public function Steempress_sp_publish($id)
$version = ((float)$version)*100;
+ if ($options['wordlimit'] != "0") {
+ $limit = intval($options["wordlimit"]);
+ $content = TruncateHTML::truncateWords($content, $limit, '');
+ }
$data = array("body" => array(
"title" => $post->post_title,
@@ -589,6 +602,8 @@ function steempress_sp_update($post_id, $bulk = false)
$options["footer"] = "
Posted from my blog with SteemPress : [%original_link%]
";
if (!isset($options["update"]))
$options["update"] = "on";
+ if (!isset($options["wordlimit"]))
+ $options["wordlimit"] = "0";
if ($options["update"] == "on" || $bulk) {
@@ -644,6 +659,11 @@ function steempress_sp_update($post_id, $bulk = false)
$permlink = get_post_meta($post_id, "steempress_sp_permlink");
+ if ($options['wordlimit'] != "0") {
+ $limit = intval($options["wordlimit"]);
+ $content = TruncateHTML::truncateWords($content, $limit, '');
+ }
+
$data = array("body" => array(
"title" => $post->post_title,
"content" => $content,
diff --git a/admin/partials/DOMWordsIterator.php b/admin/partials/DOMWordsIterator.php
new file mode 100644
index 0000000..70acfcd
--- /dev/null
+++ b/admin/partials/DOMWordsIterator.php
@@ -0,0 +1,117 @@
+load('example.xml');
+ * foreach(new DOMWordsIterator($doc) as $word) echo $word;
+ *
+ * @author pjgalbraith http://www.pjgalbraith.com
+ * @author porneL http://pornel.net (based on DOMLettersIterator available at http://pornel.net/source/domlettersiterator.php)
+ * @license Public Domain
+ *
+ */
+
+final class DOMWordsIterator implements Iterator {
+
+ private $start, $current;
+ private $offset, $key, $words;
+
+ /**
+ * expects DOMElement or DOMDocument (see DOMDocument::load and DOMDocument::loadHTML)
+ */
+ function __construct(DOMNode $el)
+ {
+ if ($el instanceof DOMDocument) $this->start = $el->documentElement;
+ else if ($el instanceof DOMElement) $this->start = $el;
+ else throw new InvalidArgumentException("Invalid arguments, expected DOMElement or DOMDocument");
+ }
+
+ /**
+ * Returns position in text as DOMText node and character offset.
+ * (it's NOT a byte offset, you must use mb_substr() or similar to use this offset properly).
+ * node may be NULL if iterator has finished.
+ *
+ * @return array
+ */
+ function currentWordPosition()
+ {
+ return array($this->current, $this->offset, $this->words);
+ }
+
+ /**
+ * Returns DOMElement that is currently being iterated or NULL if iterator has finished.
+ *
+ * @return DOMElement
+ */
+ function currentElement()
+ {
+ return $this->current ? $this->current->parentNode : NULL;
+ }
+
+ // Implementation of Iterator interface
+ function key()
+ {
+ return $this->key;
+ }
+
+ function next()
+ {
+ if (!$this->current) return;
+
+ if ($this->current->nodeType == XML_TEXT_NODE || $this->current->nodeType == XML_CDATA_SECTION_NODE)
+ {
+ if ($this->offset == -1)
+ {
+ // fastest way to get individual Unicode chars and does not require mb_* functions
+ //preg_match_all('/./us',$this->current->textContent,$m); $this->words = $m[0];
+ $this->words = preg_split("/[\n\r\t ]+/", $this->current->textContent, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_OFFSET_CAPTURE);
+ }
+ $this->offset++;
+
+ if ($this->offset < count($this->words)) {
+ $this->key++;
+ return;
+ }
+ $this->offset = -1;
+ }
+
+ while($this->current->nodeType == XML_ELEMENT_NODE && $this->current->firstChild)
+ {
+ $this->current = $this->current->firstChild;
+ if ($this->current->nodeType == XML_TEXT_NODE || $this->current->nodeType == XML_CDATA_SECTION_NODE) return $this->next();
+ }
+
+ while(!$this->current->nextSibling && $this->current->parentNode)
+ {
+ $this->current = $this->current->parentNode;
+ if ($this->current === $this->start) {$this->current = NULL; return;}
+ }
+
+ $this->current = $this->current->nextSibling;
+
+ return $this->next();
+ }
+
+ function current()
+ {
+ if ($this->current) return $this->words[$this->offset][0];
+ return NULL;
+ }
+
+ function valid()
+ {
+ return !!$this->current;
+ }
+
+ function rewind()
+ {
+ $this->offset = -1; $this->words = array();
+ $this->current = $this->start;
+ $this->next();
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/admin/partials/TruncateHTML.php b/admin/partials/TruncateHTML.php
new file mode 100644
index 0000000..ff644fb
--- /dev/null
+++ b/admin/partials/TruncateHTML.php
@@ -0,0 +1,139 @@
+= strlen(strip_tags($html)))
+ return $html;
+
+ $dom = new DOMDocument();
+ $dom->loadHTML($html);
+
+ $body = $dom->getElementsByTagName("body")->item(0);
+
+ $it = new DOMLettersIterator($body);
+
+ foreach($it as $letter) {
+ if($it->key() >= $limit) {
+ $currentText = $it->currentTextPosition();
+ $currentText[0]->nodeValue = substr($currentText[0]->nodeValue, 0, $currentText[1] + 1);
+ self::removeProceedingNodes($currentText[0], $body);
+ self::insertEllipsis($currentText[0], $ellipsis);
+ break;
+ }
+ }
+
+ return preg_replace('~<(?:!DOCTYPE|/?(?:html|head|body))[^>]*>\s*~i', '', $dom->saveHTML());
+ }
+
+ public static function truncateWords($html, $limit, $ellipsis = '...') {
+
+ if($limit <= 0 || $limit >= self::countWords(strip_tags($html)))
+ return $html;
+
+ $dom = new DOMDocument();
+ $dom->loadHTML($html);
+
+ $body = $dom->getElementsByTagName("body")->item(0);
+
+ $it = new DOMWordsIterator($body);
+
+ foreach($it as $word) {
+ if($it->key() >= $limit) {
+ $currentWordPosition = $it->currentWordPosition();
+ $curNode = $currentWordPosition[0];
+ $offset = $currentWordPosition[1];
+ $words = $currentWordPosition[2];
+
+ $curNode->nodeValue = substr($curNode->nodeValue, 0, $words[$offset][1] + strlen($words[$offset][0]));
+
+ self::removeProceedingNodes($curNode, $body);
+ self::insertEllipsis($curNode, $ellipsis);
+ break;
+ }
+ }
+
+ return preg_replace('~<(?:!DOCTYPE|/?(?:html|head|body))[^>]*>\s*~i', '', $dom->saveHTML());
+ }
+
+ private static function removeProceedingNodes(DOMNode $domNode, DOMNode $topNode) {
+ $nextNode = $domNode->nextSibling;
+
+ if($nextNode !== NULL) {
+ self::removeProceedingNodes($nextNode, $topNode);
+ $domNode->parentNode->removeChild($nextNode);
+ } else {
+ //scan upwards till we find a sibling
+ $curNode = $domNode->parentNode;
+ while($curNode !== $topNode) {
+ if($curNode->nextSibling !== NULL) {
+ $curNode = $curNode->nextSibling;
+ self::removeProceedingNodes($curNode, $topNode);
+ $curNode->parentNode->removeChild($curNode);
+ break;
+ }
+ $curNode = $curNode->parentNode;
+ }
+ }
+ }
+
+ private static function insertEllipsis(DOMNode $domNode, $ellipsis) {
+ $avoid = array('a', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5'); //html tags to avoid appending the ellipsis to
+
+ if( in_array($domNode->parentNode->nodeName, $avoid) && $domNode->parentNode->parentNode !== NULL) {
+ // Append as text node to parent instead
+ $textNode = new DOMText($ellipsis);
+
+ if($domNode->parentNode->parentNode->nextSibling)
+ $domNode->parentNode->parentNode->insertBefore($textNode, $domNode->parentNode->parentNode->nextSibling);
+ else
+ $domNode->parentNode->parentNode->appendChild($textNode);
+ } else {
+ // Append to current node
+ $domNode->nodeValue = rtrim($domNode->nodeValue).$ellipsis;
+ }
+ }
+
+ private static function countWords($text) {
+ $words = preg_split("/[\n\r\t ]+/", $text, -1, PREG_SPLIT_NO_EMPTY);
+ return count($words);
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/admin/partials/domlettersiterator.php b/admin/partials/domlettersiterator.php
new file mode 100644
index 0000000..ae78c15
--- /dev/null
+++ b/admin/partials/domlettersiterator.php
@@ -0,0 +1,114 @@
+load('example.xml');
+ * foreach(new DOMLettersIterator($doc) as $letter) echo $letter;
+ *
+ * NB: If you only need characters without their position
+ * in the document, use DOMNode->textContent instead.
+ *
+ * @author porneL https://kornel.ski
+ * @license Public Domain
+ *
+ */
+final class DOMLettersIterator implements Iterator
+{
+ private $start, $current;
+ private $offset, $key, $letters;
+
+ /**
+ * expects DOMElement or DOMDocument (see DOMDocument::load and DOMDocument::loadHTML)
+ */
+ function __construct(DOMNode $el)
+ {
+ if ($el instanceof DOMDocument) $this->start = $el->documentElement;
+ else if ($el instanceof DOMElement) $this->start = $el;
+ else throw new InvalidArgumentException("Invalid arguments, expected DOMElement or DOMDocument");
+ }
+
+ /**
+ * Returns position in text as DOMText node and character offset.
+ * (it's NOT a byte offset, you must use mb_substr() or similar to use this offset properly).
+ * node may be NULL if iterator has finished.
+ *
+ * @return array
+ */
+ function currentTextPosition()
+ {
+ return array($this->current, $this->offset);
+ }
+
+ /**
+ * Returns DOMElement that is currently being iterated or NULL if iterator has finished.
+ *
+ * @return DOMElement
+ */
+ function currentElement()
+ {
+ return $this->current ? $this->current->parentNode : NULL;
+ }
+
+ // Implementation of Iterator interface
+ function key()
+ {
+ return $this->key;
+ }
+
+ function next()
+ {
+ if (!$this->current) return;
+
+ if ($this->current->nodeType == XML_TEXT_NODE || $this->current->nodeType == XML_CDATA_SECTION_NODE)
+ {
+ if ($this->offset == -1)
+ {
+ // fastest way to get individual Unicode chars and does not require mb_* functions
+ preg_match_all('/./us',$this->current->textContent,$m); $this->letters = $m[0];
+ }
+ $this->offset++; $this->key++;
+ if ($this->offset < count($this->letters)) return;
+ $this->offset = -1;
+ }
+
+ while($this->current->nodeType == XML_ELEMENT_NODE && $this->current->firstChild)
+ {
+ $this->current = $this->current->firstChild;
+ if ($this->current->nodeType == XML_TEXT_NODE || $this->current->nodeType == XML_CDATA_SECTION_NODE) return $this->next();
+ }
+
+ while(!$this->current->nextSibling && $this->current->parentNode)
+ {
+ $this->current = $this->current->parentNode;
+ if ($this->current === $this->start) {$this->current = NULL; return;}
+ }
+
+ $this->current = $this->current->nextSibling;
+
+ return $this->next();
+ }
+
+ function current()
+ {
+ if ($this->current) return $this->letters[$this->offset];
+ return NULL;
+ }
+
+ function valid()
+ {
+ return !!$this->current;
+ }
+
+ function rewind()
+ {
+ $this->offset = -1; $this->letters = array();
+ $this->current = $this->start;
+ $this->next();
+ }
+}
+
diff --git a/admin/partials/steempress_sp-admin-display.php b/admin/partials/steempress_sp-admin-display.php
index e41e742..4ac4950 100755
--- a/admin/partials/steempress_sp-admin-display.php
+++ b/admin/partials/steempress_sp-admin-display.php
@@ -11,6 +11,8 @@
* @package Sp
* @subpackage Sp/admin/partials
*/
+
+
?>
@@ -51,6 +53,8 @@
$options["update"] = "on";
if (!isset($options["twoway-front"]))
$options["twoway-front"] = "off";
+ if (!isset($options["wordlimit"]))
+ $options["wordlimit"] = "0";
$users = get_users();
@@ -161,6 +165,13 @@
echo "
Activate for posts.
";
echo "
Activate for front page (requires two way integration for posts to be active).";
+ ?>
+
+
Word limit : only publish the first x words to the steem blockchain, set to 0 to publish the entire article.
+
"/>
+
+