Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Yii Framework 2 apidoc extension Change Log
- Bug #294: Make the `yiisoft/yii2-bootstrap` dependency optional (mspirkov)
- Chg #373: Move `BaseDoc::extractFirstSentence()` to `TextHelper::extractFirstSentence()` (mspirkov)
- Bug #283: Fix extracting the first sentence from the text (mspirkov)
- Enh #244: Uniform processing and output of descriptions for methods and properties (mspirkov)


3.0.8 November 24, 2025
Expand Down
21 changes: 21 additions & 0 deletions helpers/TextHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,34 @@

namespace yii\apidoc\helpers;

use yii\helpers\StringHelper;

/**
* An auxiliary class for working with texts.
*
* @author Maksim Spirkov <spirkov.2001@mail.ru>
*/
final class TextHelper
{
/**
* Gets a short and detailed description based on the full description of the tag.
*
* Needed for cases where there is only a full description of the tag (i.e., no summary).
*
* @return array{short: string, detailed: string}
*/
public static function getDescriptionsByFullDescription(string $fullDescription): array
{
$fullDescription = trim($fullDescription);
$shortDescription = self::extractFirstSentence($fullDescription);
$description = $shortDescription ? substr($fullDescription, strlen($shortDescription)) : '';
Comment thread
mspirkov marked this conversation as resolved.
Outdated

return [
'short' => StringHelper::mb_ucfirst($shortDescription),
'detailed' => trim($description),
];
}

/**
* Tries to extract the first sentence from the text.
*
Expand Down
10 changes: 6 additions & 4 deletions models/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ protected function handlePropertyFeature($class)
'message' => "Property $propertyName conflicts with a defined getter {$method->name} in {$class->name}.",
];
} else {
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $method->return);
// Override the setter-defined property if it exists already
$class->properties[$propertyName] = new PropertyDoc($class, null, $this, [
'name' => $propertyName,
Expand All @@ -509,8 +510,8 @@ protected function handlePropertyFeature($class)
'visibility' => 'public',
'isStatic' => false,
'type' => $method->returnType,
'shortDescription' => TextHelper::extractFirstSentence((string) $method->return),
'description' => $method->return,
'shortDescription' => $descriptions['short'],
'description' => $descriptions['detailed'],
'since' => $method->since,
'getter' => $method,
'setter' => isset($property->setter) ? $property->setter : null,
Expand All @@ -534,6 +535,7 @@ protected function handlePropertyFeature($class)
}
} else {
$param = $this->getFirstNotOptionalParameter($method);
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $param->description);
$class->properties[$propertyName] = new PropertyDoc($class, null, $this, [
'name' => $propertyName,
'fullName' => "$class->name::$propertyName",
Expand All @@ -542,8 +544,8 @@ protected function handlePropertyFeature($class)
'visibility' => 'public',
'isStatic' => false,
'type' => $param->type,
'shortDescription' => TextHelper::extractFirstSentence((string) $param->description),
'description' => $param->description,
'shortDescription' => $descriptions['short'],
'description' => $descriptions['detailed'],
'since' => $method->since,
'setter' => $method,
]);
Expand Down
6 changes: 3 additions & 3 deletions models/PropertyDoc.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use phpDocumentor\Reflection\Php\Property;
use phpDocumentor\Reflection\Type;
use yii\apidoc\helpers\TextHelper;
use yii\helpers\StringHelper;

/**
* Represents API documentation information for a `property`.
Expand Down Expand Up @@ -100,8 +99,9 @@ public function __construct($parent, $reflector = null, $context = null, $config
foreach ($this->tags as $tag) {
if ($tag instanceof Var_) {
$this->type = $tag->getType();
$this->description = StringHelper::mb_ucfirst($tag->getDescription());
$this->shortDescription = TextHelper::extractFirstSentence($this->description);
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $tag->getDescription());
$this->shortDescription = $descriptions['short'];
$this->description = $descriptions['detailed'];
} elseif ($this->isInheritdocTag($tag)) {
$hasInheritdoc = true;
}
Expand Down
14 changes: 6 additions & 8 deletions models/TypeDoc.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public function __construct($reflector = null, $context = null, $config = [])
}

if ($tag instanceof Property || $tag instanceof PropertyRead || $tag instanceof PropertyWrite) {
$shortDescription = TextHelper::extractFirstSentence((string) $tag->getDescription());
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $tag->getDescription());
$name = '$' . $tag->getVariableName();

$property = new PropertyDoc($this, null, $context, [
Expand All @@ -230,24 +230,22 @@ public function __construct($reflector = null, $context = null, $config = [])
'visibility' => 'public',
'definedBy' => $this->name,
'type' => $tag->getType(),
'shortDescription' => $shortDescription,
'description' => $tag->getDescription(),
'shortDescription' => $descriptions['short'],
'description' => $descriptions['detailed'],
]);

$this->properties[$property->name] = $property;
}

if ($tag instanceof Method) {
$fullDescription = trim((string) $tag->getDescription());
$shortDescription = TextHelper::extractFirstSentence($fullDescription);
$description = $shortDescription ? substr($fullDescription, strlen($shortDescription)) : '';
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $tag->getDescription());

$method = new MethodDoc($this, null, $context, [
'sourceFile' => $this->sourceFile,
'name' => $tag->getMethodName(),
'fullName' => ltrim((string) $reflector->getFqsen(), '\\') . '::' . $tag->getMethodName(),
'shortDescription' => $shortDescription,
'description' => $description,
'shortDescription' => $descriptions['short'],
'description' => $descriptions['detailed'],
'visibility' => 'public',
'params' => [],
'isStatic' => $tag->isStatic(),
Expand Down
6 changes: 4 additions & 2 deletions templates/html/views/methodDetails.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ class="<?= $method->definedBy !== $type->name ? 'inherited': '' ?>">
</p>
<?php } ?>

<p><strong><?= ApiMarkdown::process($method->shortDescription, $method->definedBy, true) ?></strong></p>
<?= ApiMarkdown::process($method->description, $method->definedBy) ?>
<?php if ($method->shortDescription) : ?>
<p><strong><?= ApiMarkdown::process($method->shortDescription, $method->definedBy, true) ?></strong></p>
<?= ApiMarkdown::process($method->description, $method->definedBy) ?>
<?php endif; ?>
<?= $this->render('seeAlso', ['object' => $method]) ?>
</div>

Expand Down
5 changes: 4 additions & 1 deletion templates/html/views/propertyDetails.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@
</p>
<?php } ?>

<?= ApiMarkdown::process($property->description, $property->definedBy) ?>
<?php if ($property->shortDescription) : ?>
<p><strong><?= ApiMarkdown::process($property->shortDescription, $property->definedBy, true) ?></strong></p>
<?= ApiMarkdown::process($property->description, $property->definedBy) ?>
<?php endif; ?>
<?= $this->render('seeAlso', ['object' => $property]) ?>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,63 +114,63 @@ Array

[16] => Array
(
[line] => 147
[line] => 151
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'asArray'
)

[17] => Array
(
[line] => 158
[line] => 162
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'asStdClass'
)

[18] => Array
(
[line] => 166
[line] => 170
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'setName'
)

[19] => Array
(
[line] => 172
[line] => 176
[file] => tests/data/api/animal/Animal.php
[message] => No docblock for element 'setBirthDate'
)

[20] => Array
(
[line] => 181
[line] => 185
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'getIntMaskProperty'
)

[21] => Array
(
[line] => 190
[line] => 194
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'setIntMaskOfProperty'
)

[22] => Array
(
[line] => 200
[line] => 204
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'setKeyOfProperty'
)

[23] => Array
(
[line] => 209
[line] => 213
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'getStatic'
)

[24] => Array
(
[line] => 219
[line] => 223
[file] => tests/data/api/animal/Animal.php
[message] => No short description for Method 'getSelfWithGenerics'
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ <h2>Property Details</h2>

<div class="doc-description">

<p>The owner of this behavior</p>
</div>
<p><strong>The owner of this behavior</strong></p>
</div>

<div class="signature">
<span class="signature-defs">public</span><span class="signature-type"><a href="yiiunit-apidoc-data-api-base-component.html">yiiunit\apidoc\data\api\base\Component</a>|<a href="https://www.php.net/language.types.null">null</a></span><a href="yiiunit-apidoc-data-api-base-behavior.html#%24owner-detail">$owner</a><span style="color: #0000BB"></span><span style="color: #007700">= </span><span style="color: #0000BB">null</span>
Expand Down Expand Up @@ -215,8 +215,8 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong>Attaches the behavior object to the component.</strong></p>
</div>
<p><strong>Attaches the behavior object to the component.</strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
<tr><td colspan="3" class="signature">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down Expand Up @@ -314,7 +313,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down Expand Up @@ -358,7 +356,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down Expand Up @@ -408,7 +405,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down Expand Up @@ -458,7 +454,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down Expand Up @@ -237,7 +236,6 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong></strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong>See <a href="yiiunit-apidoc-data-api-db-activequeryinterface.html#all()-detail">yiiunit\apidoc\data\api\db\ActiveQueryInterface::all()</a> for more info.</strong></p>
</div>
<p><strong>See <a href="yiiunit-apidoc-data-api-db-activequeryinterface.html#all()-detail">yiiunit\apidoc\data\api\db\ActiveQueryInterface::all()</a> for more info.</strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
<tr><td colspan="3" class="signature">
Expand Down Expand Up @@ -317,8 +317,8 @@ <h2>Method Details</h2>

<div class="doc-description">

<p><strong>See <a href="yiiunit-apidoc-data-api-db-activequeryinterface.html#one()-detail">yiiunit\apidoc\data\api\db\ActiveQueryInterface::one()</a> for more info.</strong></p>
</div>
<p><strong>See <a href="yiiunit-apidoc-data-api-db-activequeryinterface.html#one()-detail">yiiunit\apidoc\data\api\db\ActiveQueryInterface::one()</a> for more info.</strong></p>
</div>

<table class="detail-table table table-striped table-bordered table-hover">
<tr><td colspan="3" class="signature">
Expand Down
Loading
Loading