Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 23 additions & 0 deletions helpers/TextHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,36 @@

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
? mb_substr($fullDescription, mb_strlen($shortDescription, 'UTF-8'), null, 'UTF-8')
: '';

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