2007-07-19 12:40:28 +02:00
< ? php
2008-02-25 03:10:37 +01:00
/**
* Represents a long text field .
* @ package sapphire
* @ subpackage model
*/
2009-10-23 03:29:55 +02:00
class Text extends StringField {
2007-07-19 12:40:28 +02:00
static $casting = array (
" AbsoluteLinks " => " HTMLText " ,
);
2009-10-23 03:29:55 +02:00
/**
* ( non - PHPdoc )
* @ see DBField :: requireField ()
*/
2007-07-19 12:40:28 +02:00
function requireField () {
2009-09-30 00:01:51 +02:00
$parts = Array ( 'datatype' => 'mediumtext' , 'character set' => 'utf8' , 'collate' => 'utf8_general_ci' , 'arrayValue' => $this -> arrayValue );
2008-11-23 02:01:03 +01:00
$values = Array ( 'type' => 'text' , 'parts' => $parts );
DB :: requireField ( $this -> tableName , $this -> name , $values , $this -> default );
2007-07-19 12:40:28 +02:00
}
2009-01-05 07:19:48 +01:00
/**
* Limit this field ' s content by a number of words .
* CAUTION : This is not XML safe . Please use
* { @ link LimitWordCountXML ()} instead .
*
* @ param int $numWords Number of words to limit by
* @ param string $add Ellipsis to add to the end of truncated string
* @ return string
*/
function LimitWordCount ( $numWords = 26 , $add = '...' ) {
$this -> value = trim ( Convert :: xml2raw ( $this -> value ));
$ret = explode ( ' ' , $this -> value , $numWords + 1 );
2007-07-19 12:40:28 +02:00
2009-01-05 07:19:48 +01:00
if ( count ( $ret ) <= $numWords - 1 ) {
$ret = $this -> value ;
} else {
2007-07-19 12:40:28 +02:00
array_pop ( $ret );
2009-01-05 07:19:48 +01:00
$ret = implode ( ' ' , $ret ) . $add ;
2007-07-19 12:40:28 +02:00
}
return $ret ;
}
2009-10-23 03:29:55 +02:00
/**
* Return the value of the field stripped of html tags
* @ return string
*/
2007-07-19 12:40:28 +02:00
function NoHTML () {
return strip_tags ( $this -> value );
}
2009-10-23 03:29:55 +02:00
/**
* Return the value of the field with XML tags escaped .
* @ return string
*/
2007-07-19 12:40:28 +02:00
function EscapeXML () {
return str_replace ( array ( '&' , '<' , '>' , '"' ), array ( '&' , '<' , '>' , '"' ), $this -> value );
}
2009-10-23 03:29:55 +02:00
/**
* Return the value of the field with relative links converted to absolute urls .
* @ return string
*/
2007-07-19 12:40:28 +02:00
function AbsoluteLinks () {
return HTTP :: absoluteURLs ( $this -> value );
}
2009-01-05 07:19:48 +01:00
/**
* Limit this field ' s content by a number of characters .
* CAUTION : Does not take into account HTML tags , so it
* has the potential to return malformed HTML .
*
* @ param int $limit Number of characters to limit by
* @ param string $add Ellipsis to add to the end of truncated string
* @ return string
*/
2007-07-19 12:40:28 +02:00
function LimitCharacters ( $limit = 20 , $add = " ... " ) {
$value = trim ( $this -> value );
return ( strlen ( $value ) > $limit ) ? substr ( $value , 0 , $limit ) . $add : $value ;
}
2009-01-05 07:19:48 +01:00
/**
* Limit the number of words of the current field ' s
* content . This is XML safe , so characters like &
* are converted to & amp ;
*
* @ param int $numWords Number of words to limit by
* @ param string $add Ellipsis to add to the end of truncated string
* @ return string
*/
function LimitWordCountXML ( $numWords = 26 , $add = '...' ) {
$ret = $this -> LimitWordCount ( $numWords , $add );
return Convert :: raw2xml ( $ret );
2007-07-19 12:40:28 +02:00
}
2008-02-25 03:10:37 +01:00
/**
* Limit sentences , can be controlled by passing an integer .
* @ param int $sentCount The amount of sentences you want .
*/
function LimitSentences ( $sentCount = 2 ) {
2009-07-09 08:14:04 +02:00
if ( ! is_numeric ( $sentCount )) user_error ( " Text::LimitSentence() expects one numeric argument " , E_USER_NOTICE );
$output = array ();
$data = trim ( Convert :: xml2raw ( $this -> value ));
2008-02-25 03:10:37 +01:00
$sentences = explode ( '.' , $data );
2009-07-09 08:14:04 +02:00
if ( $sentCount == 0 ) return '' ;
for ( $i = 0 ; $i < $sentCount ; $i ++ ) {
if ( isset ( $sentences [ $i ])) {
$sentence = trim ( $sentences [ $i ]);
if ( ! empty ( $sentence )) $output [] .= $sentence ;
2008-02-25 03:10:37 +01:00
}
}
2009-07-09 08:14:04 +02:00
return count ( $output ) == 0 ? '' : implode ( $output , '. ' ) . '.' ;
2008-02-25 03:10:37 +01:00
}
2007-07-19 12:40:28 +02:00
2009-07-09 08:14:04 +02:00
2007-10-07 14:17:33 +02:00
/**
* Caution : Not XML / HTML - safe - does not respect closing tags .
*/
2007-07-19 12:40:28 +02:00
function FirstSentence () {
$data = Convert :: xml2raw ( $this -> value );
2008-11-18 02:48:37 +01:00
if ( ! $data ) return " " ;
2007-07-19 12:40:28 +02:00
$sentences = explode ( '.' , $data );
if ( count ( $sentences ) )
return $sentences [ 0 ] . '.' ;
else
return $this -> Summary ( 20 );
}
2007-10-07 14:17:33 +02:00
/**
* Caution : Not XML / HTML - safe - does not respect closing tags .
*/
2007-07-19 12:40:28 +02:00
function Summary ( $maxWords = 50 ) {
// get first sentence?
// this needs to be more robust
$data = Convert :: xml2raw ( $this -> value /*, true*/ );
if ( ! $data )
return " " ;
// grab the first paragraph, or, failing that, the whole content
if ( strpos ( $data , " \n \n " ) )
$data = substr ( $data , 0 , strpos ( $data , " \n \n " ) );
$sentences = explode ( '.' , $data );
$count = count ( explode ( ' ' , $sentences [ 0 ] ) );
// if the first sentence is too long, show only the first $maxWords words
if ( $count > $maxWords ) {
return implode ( ' ' , array_slice ( explode ( ' ' , $sentences [ 0 ] ), 0 , $maxWords ) ) . '...' ;
}
// add each sentence while there are enough words to do so
$result = '' ;
do {
$result .= trim ( array_shift ( $sentences )) . '.' ;
if ( count ( $sentences ) > 0 ) {
$count += count ( explode ( ' ' , $sentences [ 0 ] ) );
}
// Ensure that we don't trim half way through a tag or a link
$brokenLink = ( substr_count ( $result , '<' ) != substr_count ( $result , '>' )) ||
( substr_count ( $result , '<a' ) != substr_count ( $result , '</a' ));
} while ( ( $count < $maxWords || $brokenLink ) && $sentences && trim ( $sentences [ 0 ] ) );
if ( preg_match ( '/<a[^>]*>/' , $result ) && ! preg_match ( '/<\/a>/' , $result ) )
$result .= '</a>' ;
$result = Convert :: raw2xml ( $result );
return $result ;
}
/**
* Performs the same function as the big summary , but doesnt trim new paragraphs off data .
2007-10-07 14:17:33 +02:00
* Caution : Not XML / HTML - safe - does not respect closing tags .
2007-07-19 12:40:28 +02:00
*/
function BigSummary ( $maxWords = 50 , $plain = 1 ) {
2008-08-12 04:51:33 +02:00
$result = " " ;
2007-07-19 12:40:28 +02:00
// get first sentence?
// this needs to be more robust
if ( $plain ) $data = Convert :: xml2raw ( $this -> value , true );
if ( ! $data )
return " " ;
$sentences = explode ( '.' , $data );
$count = count ( explode ( ' ' , $sentences [ 0 ] ) );
// if the first sentence is too long, show only the first $maxWords words
if ( $count > $maxWords ) {
return implode ( ' ' , array_slice ( explode ( ' ' , $sentences [ 0 ] ), 0 , $maxWords ) ) . '...' ;
}
// add each sentence while there are enough words to do so
do {
2009-08-24 08:16:56 +02:00
$result .= trim ( array_shift ( $sentences ));
if ( $sentences ) {
$result .= '. ' ;
$count += count ( explode ( ' ' , $sentences [ 0 ]));
}
2007-07-19 12:40:28 +02:00
// Ensure that we don't trim half way through a tag or a link
$brokenLink = ( substr_count ( $result , '<' ) != substr_count ( $result , '>' )) ||
( substr_count ( $result , '<a' ) != substr_count ( $result , '</a' ));
} while ( ( $count < $maxWords || $brokenLink ) && $sentences && trim ( $sentences [ 0 ] ) );
if ( preg_match ( '/<a[^>]*>/' , $result ) && ! preg_match ( '/<\/a>/' , $result ) )
$result .= '</a>' ;
return $result ;
}
2007-10-07 14:17:33 +02:00
/**
* Caution : Not XML / HTML - safe - does not respect closing tags .
*/
2007-07-19 12:40:28 +02:00
function FirstParagraph ( $plain = 1 ) {
// get first sentence?
// this needs to be more robust
if ( $plain && $plain != 'html' ) {
$data = Convert :: xml2raw ( $this -> value , true );
if ( ! $data ) return " " ;
// grab the first paragraph, or, failing that, the whole content
if ( strpos ( $data , " \n \n " ) )
$data = substr ( $data , 0 , strpos ( $data , " \n \n " ) );
return $data ;
} else {
if ( strpos ( $this -> value , " </p> " ) === false ) return $this -> value ;
$data = substr ( $this -> value , 0 , strpos ( $this -> value , " </p> " ) + 4 );
if ( strlen ( $data ) < 20 && strpos ( $this -> value , " </p> " , strlen ( $data ) )) $data = substr ( $this -> value , 0 , strpos ( $this -> value , " </p> " , strlen ( $data ) ) + 4 );
return $data ;
}
}
2009-01-05 07:19:48 +01:00
/**
* Perform context searching to give some context to searches , optionally
* highlighting the search term .
*
* @ param int $characters Number of characters in the summary
* @ param boolean $string Supplied string ( " keywords " )
* @ param boolean $striphtml Strip HTML ?
* @ param boolean $highlight Add a highlight < span > element around search query ?
* @ return string
*/
2008-02-25 03:10:37 +01:00
function ContextSummary ( $characters = 500 , $string = false , $striphtml = true , $highlight = true ) {
2009-01-05 07:19:48 +01:00
if ( ! $string ) $string = $_REQUEST [ 'Search' ]; // Use the default "Search" request variable (from SearchForm)
2008-02-25 03:10:37 +01:00
// Remove HTML tags so we don't have to deal with matching tags
$text = $striphtml ? $this -> NoHTML () : $this -> value ;
// Find the search string
$position = ( int ) stripos ( $text , $string );
// We want to search string to be in the middle of our block to give it some context
$position = max ( 0 , $position - ( $characters / 2 ));
if ( $position > 0 ) {
// We don't want to start mid-word
$position = max (( int ) strrpos ( substr ( $text , 0 , $position ), ' ' ), ( int ) strrpos ( substr ( $text , 0 , $position ), " \n " ));
}
$summary = substr ( $text , $position , $characters );
2009-01-05 07:19:48 +01:00
$stringPieces = explode ( ' ' , $string );
2008-02-25 03:10:37 +01:00
if ( $highlight ) {
2009-01-05 07:19:48 +01:00
// Add a span around all key words from the search term as well
2009-09-18 04:53:46 +02:00
if ( $stringPieces ) foreach ( $stringPieces as $stringPiece ) {
$summary = str_ireplace ( $stringPiece , " <span class= \" highlight \" > $stringPiece </span> " , $summary );
2009-01-05 07:19:48 +01:00
}
2008-02-25 03:10:37 +01:00
}
return trim ( $summary );
}
2007-07-19 12:40:28 +02:00
/**
2008-10-02 02:34:16 +02:00
* Allows a sub - class of TextParser to be rendered .
*
* @ see TextParser for implementation details .
* @ return string
2007-07-19 12:40:28 +02:00
*/
function Parse ( $parser = " TextParser " ) {
if ( $parser == " TextParser " || is_subclass_of ( $parser , " TextParser " )) {
$obj = new $parser ( $this -> value );
return $obj -> parse ();
} else {
// Fallback to using raw2xml and show a warning
// TODO Don't kill script execution, we can continue without losing complete control of the app
user_error ( " Couldn't find an appropriate TextParser sub-class to create (Looked for ' $parser '). Make sure it sub-classes TextParser and that you've done ?flush=1. " , E_USER_WARNING );
return Convert :: raw2xml ( $this -> value );
}
}
2008-10-28 01:32:51 +01:00
2009-10-23 03:29:55 +02:00
/**
* ( non - PHPdoc )
* @ see DBField :: scaffoldFormField ()
*/
2008-10-28 01:32:51 +01:00
public function scaffoldFormField ( $title = null , $params = null ) {
2009-11-03 23:27:56 +01:00
if ( ! $this -> nullifyEmpty ) {
// Allow the user to select if it's null instead of automatically assuming empty string is
2009-10-23 03:29:55 +02:00
return new NullableField ( new TextareaField ( $this -> name , $title ));
} else {
2009-11-03 23:27:56 +01:00
// Automatically determine null (empty string)
2009-10-23 03:29:55 +02:00
return new TextareaField ( $this -> name , $title );
}
2008-10-28 01:32:51 +01:00
}
2008-11-02 22:07:09 +01:00
2009-10-23 03:29:55 +02:00
/**
* ( non - PHPdoc )
* @ see DBField :: scaffoldSearchField ()
*/
2008-11-02 22:07:09 +01:00
public function scaffoldSearchField ( $title = null , $params = null ) {
return new TextField ( $this -> name , $title );
}
2007-07-19 12:40:28 +02:00
}
2009-10-23 03:29:55 +02:00
?>