本文整理汇总了PHP中phutil_utf8_strlen函数的典型用法代码示例。如果您正苦于以下问题:PHP phutil_utf8_strlen函数的具体用法?PHP phutil_utf8_strlen怎么用?PHP phutil_utf8_strlen使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了phutil_utf8_strlen函数的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。
示例1: processRequest
public function processRequest()
{
$request = $this->getRequest();
$user = $request->getUser();
if ($this->id) {
$question = id(new PonderQuestionQuery())->setViewer($user)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
if (!$question) {
return new Aphront404Response();
}
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs($question->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
} else {
$question = id(new PonderQuestion())->setStatus(PonderQuestionStatus::STATUS_OPEN)->setAuthorPHID($user->getPHID())->setVoteCount(0)->setAnswerCount(0)->setHeat(0.0);
$v_projects = array();
}
$v_title = $question->getTitle();
$v_content = $question->getContent();
$errors = array();
$e_title = true;
if ($request->isFormPost()) {
$v_title = $request->getStr('title');
$v_content = $request->getStr('content');
$v_projects = $request->getArr('projects');
$len = phutil_utf8_strlen($v_title);
if ($len < 1) {
$errors[] = pht('Title must not be empty.');
$e_title = pht('Required');
} else {
if ($len > 255) {
$errors[] = pht('Title is too long.');
$e_title = pht('Too Long');
}
}
if (!$errors) {
$template = id(new PonderQuestionTransaction());
$xactions = array();
$xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_TITLE)->setNewValue($v_title);
$xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_CONTENT)->setNewValue($v_content);
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PonderQuestionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $proj_edge_type)->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new PonderQuestionEditor())->setActor($user)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
$editor->applyTransactions($question, $xactions);
return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID());
}
}
$form = id(new AphrontFormView())->setUser($user)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Question'))->setName('title')->setValue($v_title)->setError($e_title))->appendChild(id(new PhabricatorRemarkupControl())->setUser($user)->setName('content')->setID('content')->setValue($v_content)->setLabel(pht('Description'))->setUser($user));
$form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($v_projects)->setDatasource(new PhabricatorProjectDatasource()));
$form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Ask Away!')));
$preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Question Preview'))->setControlID('content')->setPreviewURI($this->getApplicationURI('preview/'));
$form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Ask New Question'))->setFormErrors($errors)->setForm($form);
$crumbs = $this->buildApplicationCrumbs();
$id = $question->getID();
if ($id) {
$crumbs->addTextCrumb("Q{$id}", "/Q{$id}");
$crumbs->addTextCrumb(pht('Edit'));
} else {
$crumbs->addTextCrumb(pht('Ask Question'));
}
return $this->buildApplicationPage(array($crumbs, $form_box, $preview), array('title' => pht('Ask New Question')));
}
示例2: testUTF8len
public function testUTF8len()
{
$strings = array('' => 0, 'x' => 1, "�" => 1, "x東y" => 3, "xyz" => 3, 'quack' => 5);
foreach ($strings as $str => $expect) {
$this->assertEqual($expect, phutil_utf8_strlen($str), 'Length of ' . $str);
}
}
示例3: markupText
public function markupText($text, $children)
{
$text = trim($text);
$lines = phutil_split_lines($text);
if (count($lines) > 1) {
$level = $lines[1][0] == '=' ? 1 : 2;
$text = trim($lines[0]);
} else {
$level = 0;
for ($ii = 0; $ii < min(5, strlen($text)); $ii++) {
if ($text[$ii] == '=' || $text[$ii] == '#') {
++$level;
} else {
break;
}
}
$text = trim($text, ' =#');
}
$engine = $this->getEngine();
if ($engine->isTextMode()) {
$char = $level == 1 ? '=' : '-';
return $text . "\n" . str_repeat($char, phutil_utf8_strlen($text));
}
$use_anchors = $engine->getConfig('header.generate-toc');
$anchor = null;
if ($use_anchors) {
$anchor = $this->generateAnchor($level, $text);
}
$text = phutil_tag('h' . ($level + 1), array('class' => 'remarkup-header'), array($anchor, $this->applyRules($text)));
return $text;
}
示例4: assertValidPublisherKey
public static function assertValidPublisherKey($value)
{
$length = phutil_utf8_strlen($value);
if (!$length) {
throw new Exception(pht('Publisher key "%s" is not valid: publisher keys are required.', $value));
}
$max_length = 64;
if ($length > $max_length) {
throw new Exception(pht('Publisher key "%s" is not valid: publisher keys must not be ' . 'more than %s characters long.', $value, new PhutilNumber($max_length)));
}
if (!preg_match('/^[a-z]+\\z/', $value)) {
throw new Exception(pht('Publisher key "%s" is not valid: publisher keys may only contain ' . 'lowercase latin letters.', $value));
}
}
示例5: assertValidVersionName
public static function assertValidVersionName($value)
{
$length = phutil_utf8_strlen($value);
if (!$length) {
throw new Exception(pht('Version name "%s" is not valid: version names are required.', $value));
}
$max_length = 64;
if ($length > $max_length) {
throw new Exception(pht('Version name "%s" is not valid: version names must not be ' . 'more than %s characters long.', $value, new PhutilNumber($max_length)));
}
if (!preg_match('/^[A-Za-z0-9.-]+\\z/', $value)) {
throw new Exception(pht('Version name "%s" is not valid: version names may only contain ' . 'latin letters, digits, periods, and hyphens.', $value));
}
if (preg_match('/^[.-]|[.-]$/', $value)) {
throw new Exception(pht('Version name "%s" is not valid: version names may not start or ' . 'end with a period or hyphen.', $value));
}
}
示例6: renderRemarkupTable
protected function renderRemarkupTable(array $out_rows)
{
assert_instances_of($out_rows, 'array');
if ($this->getEngine()->isTextMode()) {
$lengths = array();
foreach ($out_rows as $r => $row) {
foreach ($row['content'] as $c => $cell) {
$text = $this->getEngine()->restoreText($cell['content']);
$lengths[$c][$r] = phutil_utf8_strlen($text);
}
}
$max_lengths = array_map('max', $lengths);
$out = array();
foreach ($out_rows as $r => $row) {
$headings = false;
foreach ($row['content'] as $c => $cell) {
$length = $max_lengths[$c] - $lengths[$c][$r];
$out[] = '| ' . $cell['content'] . str_repeat(' ', $length) . ' ';
if ($cell['type'] == 'th') {
$headings = true;
}
}
$out[] = "|\n";
if ($headings) {
foreach ($row['content'] as $c => $cell) {
$char = $cell['type'] == 'th' ? '-' : ' ';
$out[] = '| ' . str_repeat($char, $max_lengths[$c]) . ' ';
}
$out[] = "|\n";
}
}
return rtrim(implode('', $out), "\n");
}
$out = array();
$out[] = "\n";
foreach ($out_rows as $row) {
$cells = array();
foreach ($row['content'] as $cell) {
$cells[] = phutil_tag($cell['type'], array(), $cell['content']);
}
$out[] = phutil_tag($row['type'], array(), $cells);
$out[] = "\n";
}
return phutil_tag('table', array('class' => 'remarkup-table'), $out);
}
示例7: handlePost
private function handlePost()
{
$request = $this->getRequest();
$user = $request->getUser();
$errors = array();
$title = $request->getStr('title');
$content = $request->getStr('content');
// form validation
if (phutil_utf8_strlen($title) < 1 || phutil_utf8_strlen($title) > 255) {
$errors[] = "Please enter a title (1-255 characters)";
}
if ($errors) {
return $this->showForm($errors, $title, $content);
}
// no validation errors -> save it
$content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr()));
$question = id(new PonderQuestion())->setTitle($title)->setContent($content)->setAuthorPHID($user->getPHID())->setContentSource($content_source)->setVoteCount(0)->setAnswerCount(0)->setHeat(0.0)->save();
PhabricatorSearchPonderIndexer::indexQuestion($question);
return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID());
}
示例8: processRequest
public function processRequest()
{
$request = $this->getRequest();
$user = $request->getUser();
$question = id(new PonderQuestion())->setAuthorPHID($user->getPHID())->setVoteCount(0)->setAnswerCount(0)->setHeat(0.0);
$errors = array();
$e_title = true;
if ($request->isFormPost()) {
$question->setTitle($request->getStr('title'));
$question->setContent($request->getStr('content'));
$len = phutil_utf8_strlen($question->getTitle());
if ($len < 1) {
$errors[] = pht('Title must not be empty.');
$e_title = pht('Required');
} else {
if ($len > 255) {
$errors[] = pht('Title is too long.');
$e_title = pht('Too Long');
}
}
if (!$errors) {
$content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr()));
$question->setContentSource($content_source);
id(new PonderQuestionEditor())->setQuestion($question)->setUser($user)->save();
return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID());
}
}
$error_view = null;
if ($errors) {
$error_view = id(new AphrontErrorView())->setTitle('Form Errors')->setErrors($errors);
}
$header = id(new PhabricatorHeaderView())->setHeader(pht('Ask Question'));
$form = id(new AphrontFormView())->setUser($user)->setFlexible(true)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Question'))->setName('title')->setValue($question->getTitle())->setError($e_title))->appendChild(id(new PhabricatorRemarkupControl())->setName('content')->setID('content')->setValue($question->getContent())->setLabel(pht('Description')))->appendChild(id(new AphrontFormSubmitControl())->setValue('Ask Away!'));
$preview = '<div class="aphront-panel-flush">' . '<div id="question-preview">' . '<span class="aphront-panel-preview-loading-text">' . pht('Loading question preview...') . '</span>' . '</div>' . '</div>';
Javelin::initBehavior('ponder-feedback-preview', array('uri' => '/ponder/question/preview/', 'content' => 'content', 'preview' => 'question-preview', 'question_id' => null));
$nav = $this->buildSideNavView($question);
$nav->selectFilter($question->getID() ? null : 'question/ask');
$nav->appendChild(array($header, $error_view, $form, $preview));
return $this->buildApplicationPage($nav, array('device' => true, 'title' => 'Ask a Question'));
}
示例9: renderRemarkupTable
protected function renderRemarkupTable(array $out_rows)
{
assert_instances_of($out_rows, 'array');
if ($this->getEngine()->isTextMode()) {
$lengths = array();
foreach ($out_rows as $r => $row) {
foreach ($row['content'] as $c => $cell) {
$text = $this->getEngine()->restoreText($cell['content']);
$lengths[$c][$r] = phutil_utf8_strlen($text);
}
}
$max_lengths = array_map('max', $lengths);
$out = array();
foreach ($out_rows as $r => $row) {
$headings = false;
foreach ($row['content'] as $c => $cell) {
$length = $max_lengths[$c] - $lengths[$c][$r];
$out[] = '| ' . $cell['content'] . str_repeat(' ', $length) . ' ';
if ($cell['type'] == 'th') {
$headings = true;
}
}
$out[] = "|\n";
if ($headings) {
foreach ($row['content'] as $c => $cell) {
$char = $cell['type'] == 'th' ? '-' : ' ';
$out[] = '| ' . str_repeat($char, $max_lengths[$c]) . ' ';
}
$out[] = "|\n";
}
}
return rtrim(implode('', $out), "\n");
}
if ($this->getEngine()->isHTMLMailMode()) {
$table_attributes = array('style' => 'border-collapse: separate;
border-spacing: 1px;
background: #d3d3d3;
margin: 12px 0;');
$cell_attributes = array('style' => 'background: #ffffff;
padding: 3px 6px;');
} else {
$table_attributes = array('class' => 'remarkup-table');
$cell_attributes = array();
}
$out = array();
$out[] = "\n";
foreach ($out_rows as $row) {
$cells = array();
foreach ($row['content'] as $cell) {
$cells[] = phutil_tag($cell['type'], $cell_attributes, $cell['content']);
}
$out[] = phutil_tag($row['type'], array(), $cells);
$out[] = "\n";
}
return phutil_tag('table', $table_attributes, $out);
}
示例10: validateIsTextFieldTooLong
/**
* Check that text field input isn't longer than a specified length.
*
* A text field input is invalid if the length of the input is longer than a
* specified length. This length can be determined by the space allotted in
* the database, or given arbitrarily.
* This method is intended to make implementing @{method:validateTransaction}
* more convenient:
*
* $overdrawn = $this->validateIsTextFieldTooLong(
* $object->getName(),
* $xactions,
* $field_length);
*
* This will return `true` if the net effect of the object and transactions
* is a field that is too long.
*
* @param wild Current field value.
* @param list<PhabricatorApplicationTransaction> Transactions editing the
* field.
* @param integer for maximum field length.
* @return bool True if the field will be too long after edits.
*/
protected function validateIsTextFieldTooLong($field_value, array $xactions, $length)
{
if ($xactions) {
$new_value_length = phutil_utf8_strlen(last($xactions)->getNewValue());
if ($new_value_length <= $length) {
return false;
} else {
return true;
}
}
$old_value_length = phutil_utf8_strlen($field_value);
if ($old_value_length <= $length) {
return false;
}
return true;
}
示例11: handleRequest
public function handleRequest(AphrontRequest $request)
{
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if ($id) {
$question = id(new PonderQuestionQuery())->setViewer($viewer)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
if (!$question) {
return new Aphront404Response();
}
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs($question->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
$is_new = false;
} else {
$is_new = true;
$question = PonderQuestion::initializeNewQuestion($viewer);
$v_projects = array();
}
$v_title = $question->getTitle();
$v_content = $question->getContent();
$v_wiki = $question->getAnswerWiki();
$v_view = $question->getViewPolicy();
$v_space = $question->getSpacePHID();
$v_status = $question->getStatus();
$errors = array();
$e_title = true;
if ($request->isFormPost()) {
$v_title = $request->getStr('title');
$v_content = $request->getStr('content');
$v_wiki = $request->getStr('answerWiki');
$v_projects = $request->getArr('projects');
$v_view = $request->getStr('viewPolicy');
$v_space = $request->getStr('spacePHID');
$v_status = $request->getStr('status');
$len = phutil_utf8_strlen($v_title);
if ($len < 1) {
$errors[] = pht('Title must not be empty.');
$e_title = pht('Required');
} else {
if ($len > 255) {
$errors[] = pht('Title is too long.');
$e_title = pht('Too Long');
}
}
if (!$errors) {
$template = id(new PonderQuestionTransaction());
$xactions = array();
$xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_TITLE)->setNewValue($v_title);
$xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_CONTENT)->setNewValue($v_content);
$xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_ANSWERWIKI)->setNewValue($v_wiki);
if (!$is_new) {
$xactions[] = id(clone $template)->setTransactionType(PonderQuestionTransaction::TYPE_STATUS)->setNewValue($v_status);
}
$xactions[] = id(clone $template)->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($v_view);
$xactions[] = id(clone $template)->setTransactionType(PhabricatorTransactions::TYPE_SPACE)->setNewValue($v_space);
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PonderQuestionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $proj_edge_type)->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new PonderQuestionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
$editor->applyTransactions($question, $xactions);
return id(new AphrontRedirectResponse())->setURI('/Q' . $question->getID());
}
}
$policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($question)->execute();
$form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Question'))->setName('title')->setValue($v_title)->setError($e_title))->appendChild(id(new PhabricatorRemarkupControl())->setUser($viewer)->setName('content')->setID('content')->setValue($v_content)->setLabel(pht('Question Details'))->setUser($viewer))->appendChild(id(new PhabricatorRemarkupControl())->setUser($viewer)->setName('answerWiki')->setID('answerWiki')->setValue($v_wiki)->setLabel(pht('Answer Summary'))->setUser($viewer))->appendControl(id(new AphrontFormPolicyControl())->setName('viewPolicy')->setPolicyObject($question)->setSpacePHID($v_space)->setPolicies($policies)->setValue($v_view)->setCapability(PhabricatorPolicyCapability::CAN_VIEW));
if (!$is_new) {
$form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Status'))->setName('status')->setValue($v_status)->setOptions(PonderQuestionStatus::getQuestionStatusMap()));
}
$form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Tags'))->setName('projects')->setValue($v_projects)->setDatasource(new PhabricatorProjectDatasource()));
$form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Submit')));
$preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Question Preview'))->setControlID('content')->setPreviewURI($this->getApplicationURI('preview/'));
$answer_preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Answer Summary Preview'))->setControlID('answerWiki')->setPreviewURI($this->getApplicationURI('preview/'));
$crumbs = $this->buildApplicationCrumbs();
$id = $question->getID();
if ($id) {
$crumbs->addTextCrumb("Q{$id}", "/Q{$id}");
$crumbs->addTextCrumb(pht('Edit'));
$title = pht('Edit Question');
$header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-pencil');
} else {
$crumbs->addTextCrumb(pht('Ask Question'));
$title = pht('Ask New Question');
$header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-plus-square');
}
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())->setHeaderText(pht('Question'))->setFormErrors($errors)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
$view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($box, $preview, $answer_preview));
return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
}
示例12: validateTransaction
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions)
{
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhameBlogTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField($object->getName(), $xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Name is required.'), nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (phutil_utf8_strlen($new) > 64) {
$errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('The selected blog title is too long. The maximum length ' . 'of a blog title is 64 characters.'), $xaction);
}
}
break;
case PhameBlogTransaction::TYPE_SUBTITLE:
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (phutil_utf8_strlen($new) > 64) {
$errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('The selected blog subtitle is too long. The maximum length ' . 'of a blog subtitle is 64 characters.'), $xaction);
}
}
break;
case PhameBlogTransaction::TYPE_PARENTDOMAIN:
if (!$xactions) {
continue;
}
$parent_domain = last($xactions)->getNewValue();
if (empty($parent_domain)) {
continue;
}
try {
PhabricatorEnv::requireValidRemoteURIForLink($parent_domain);
} catch (Exception $ex) {
$error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid URI'), pht('Parent Domain must be set to a valid Remote URI.'), nonempty(last($xactions), null));
$errors[] = $error;
}
break;
case PhameBlogTransaction::TYPE_FULLDOMAIN:
if (!$xactions) {
continue;
}
$custom_domain = last($xactions)->getNewValue();
if (empty($custom_domain)) {
continue;
}
list($error_label, $error_text) = $object->validateCustomDomain($custom_domain);
if ($error_label) {
$error = new PhabricatorApplicationTransactionValidationError($type, $error_label, $error_text, nonempty(last($xactions), null));
$errors[] = $error;
}
if ($object->getViewPolicy() != PhabricatorPolicies::POLICY_PUBLIC) {
$error_text = pht('For custom domains to work, the blog must have a view policy of ' . 'public.');
$error = new PhabricatorApplicationTransactionValidationError(PhabricatorTransactions::TYPE_VIEW_POLICY, pht('Invalid Policy'), $error_text, nonempty(last($xactions), null));
$errors[] = $error;
}
$domain = new PhutilURI($custom_domain);
$domain = $domain->getDomain();
$duplicate_blog = id(new PhameBlogQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withDomain($domain)->executeOne();
if ($duplicate_blog && $duplicate_blog->getID() != $object->getID()) {
$error = new PhabricatorApplicationTransactionValidationError($type, pht('Not Unique'), pht('Domain must be unique; another blog already has this domain.'), nonempty(last($xactions), null));
$errors[] = $error;
}
break;
}
return $errors;
}
示例13: correctSpelling
public function correctSpelling($input, array $options)
{
$matrix = $this->getEditDistanceMatrix();
if (!$matrix) {
throw new PhutilInvalidStateException('setEditDistanceMatrix');
}
$max_distance = $this->getMaximumDistance();
if (!$max_distance) {
throw new PhutilInvalidStateException('setMaximumDistance');
}
$input = $this->normalizeString($input);
foreach ($options as $key => $option) {
$options[$key] = $this->normalizeString($option);
}
$distances = array();
$inputv = phutil_utf8v($input);
foreach ($options as $option) {
$optionv = phutil_utf8v($option);
$matrix->setSequences($optionv, $inputv);
$distances[$option] = $matrix->getEditDistance();
}
asort($distances);
$best = min($max_distance, head($distances));
foreach ($distances as $option => $distance) {
if ($distance > $best) {
unset($distances[$option]);
}
}
// Before filtering, check if we have multiple equidistant matches and
// return them if we do. This prevents us from, e.g., matching "alnd" with
// both "land" and "amend", then dropping "land" for being too short, and
// incorrectly completing to "amend".
if (count($distances) > 1) {
return array_keys($distances);
}
foreach ($distances as $option => $distance) {
if (phutil_utf8_strlen($option) < $distance) {
unset($distances[$option]);
}
}
return array_keys($distances);
}
示例14: phutil_utf8_shorten
/**
* Shorten a string to provide a summary, respecting UTF-8 characters. This
* function attempts to truncate strings at word boundaries.
*
* NOTE: This function makes a best effort to apply some reasonable rules but
* will not work well for the full range of unicode languages. For instance,
* no effort is made to deal with combining characters.
*
* @param string UTF-8 string to shorten.
* @param int Maximum length of the result.
* @param string If the string is shortened, add this at the end. Defaults to
* horizontal ellipsis.
* @return string A string with no more than the specified character length.
*
* @group utf8
*/
function phutil_utf8_shorten($string, $length, $terminal = "…")
{
$terminal_len = phutil_utf8_strlen($terminal);
if ($terminal_len >= $length) {
// If you provide a terminal we still enforce that the result (including
// the terminal) is no longer than $length, but we can't do that if the
// terminal is too long.
throw new Exception("String terminal length must be less than string length!");
}
$string_v = phutil_utf8v($string);
$string_len = count($string_v);
if ($string_len <= $length) {
// If the string is already shorter than the requested length, simply return
// it unmodified.
return $string;
}
// NOTE: This is not complete, and there are many other word boundary
// characters and reasonable places to break words in the UTF-8 character
// space. For now, this gives us reasonable behavior for latin langauges. We
// don't necessarily have access to PCRE+Unicode so there isn't a great way
// for us to look up character attributes.
// If we encounter these, prefer to break on them instead of cutting the
// string off in the middle of a word.
static $break_characters = array(' ' => true, "\n" => true, ';' => true, ':' => true, '[' => true, '(' => true, ',' => true, '-' => true);
// If we encounter these, shorten to this character exactly without appending
// the terminal.
static $stop_characters = array('.' => true, '!' => true, '?' => true);
// Search backward in the string, looking for reasonable places to break it.
$word_boundary = null;
$stop_boundary = null;
// If we do a word break with a terminal, we have to look beyond at least the
// number of characters in the terminal.
$terminal_area = $length - $terminal_len;
for ($ii = $length; $ii >= 0; $ii--) {
$c = $string_v[$ii];
if (isset($break_characters[$c]) && $ii <= $terminal_area) {
$word_boundary = $ii;
} else {
if (isset($stop_characters[$c]) && $ii < $length) {
$stop_boundary = $ii + 1;
break;
} else {
if ($word_boundary !== null) {
break;
}
}
}
}
if ($stop_boundary !== null) {
// We found a character like ".". Cut the string there, without appending
// the terminal.
$string_part = array_slice($string_v, 0, $stop_boundary);
return implode('', $string_part);
}
// If we didn't find any boundary characters or we found ONLY boundary
// characters, just break at the maximum character length.
if ($word_boundary === null || $word_boundary === 0) {
$word_boundary = $length - $terminal_len;
}
$string_part = array_slice($string_v, 0, $word_boundary);
$string_part = implode('', $string_part);
return $string_part . $terminal;
}