18 'feature' =>
'Features',
19 'performance' =>
'Performance',
20 'documentation' =>
'Documentation',
22 'deprecated' =>
'Deprecations',
23 'breaking' =>
'Breaking Changes',
24 'removed' =>
'Removed',
37 'repository' =>
'https://github.com/Elgg/Elgg/',
45 if (!file_exists(
$options[
'changelog']) || !is_writable(
$options[
'changelog'])) {
89 $contents = file_get_contents($this->getOption(
'changelog'));
90 $first_anchor = strpos(
$contents,
'<a name="');
91 if ($first_anchor ===
false) {
92 return trim($this->getOption(
'notes',
''));
95 return trim($this->getOption(
'notes',
'') . substr(
$contents, 0, $first_anchor));
104 return $this->executeCommand(
'git tag') ?: [];
116 'grep' =>
'^[a-z]+(\(.*\))?:|BREAKING',
117 'format' =>
'%H%n%h%n%s%n%b%n==END==',
123 $command = vsprintf(
'git log --grep="%s" -E --format=%s %s %s', [
127 implode(
' ', array_map(
function (
$value) {
128 if (str_contains(PHP_OS,
'WIN')) {
136 $commits = $this->executeCommand($command);
137 if (!isset($commits)) {
146 $subject_pattern =
'/^((Merge )|(Revert )|((\w*)\(([\w]+)\)\: ([^\n]*))$)/';
147 foreach ($commits as $line) {
148 if ($line ===
'==END==') {
170 preg_match($subject_pattern, $line, $matches);
172 $result[
'type'] = $matches[5] ??
'skip';
173 $result[
'component'] = $matches[6] ??
'';
174 $result[
'subject'] = $matches[7] ??
'';
182 $result[
'body'] .= $line . PHP_EOL;
190 $fixes_pattern =
'/(closes|fixes)\s+#(\d+)/i';
192 if (
$result[
'type'] ===
'skip') {
197 if (str_contains(strtolower(
$result[
'body']),
'breaking change:')) {
203 preg_match_all($fixes_pattern,
$result[
'body'], $matches);
204 if (!empty($matches) && !empty($matches[2])) {
230 $command = vsprintf(
'git shortlog -sne %s --no-merges %s', [
232 implode(
' ', array_map(
function (
$value) {
233 if (str_contains(PHP_OS,
'WIN')) {
241 $contributors = $this->executeCommand($command);
242 if (!isset($contributors)) {
246 $contributor_pattern =
'/\s+([0-9]+)\s+(.*)\s<(.*)>/';
248 foreach ($contributors as $contributor) {
250 preg_match($contributor_pattern, $contributor, $matches);
251 if (empty($matches)) {
256 'count' => (int) $matches[1],
257 'name' => $matches[2],
258 'email' => $matches[3],
263 usort(
$result,
function ($a, $b) {
264 return $b[
'count'] - $a[
'count'];
278 if (empty($commits)) {
284 foreach ($commits as $commit) {
285 $type = $commit[
'type'];
286 if (str_starts_with(
$type,
'feat')) {
291 $type =
'performance';
293 $type =
'documentation';
295 $type =
'deprecated';
304 if (!isset($types[
$type])) {
308 $component = $commit[
'component'];
309 if (!isset($types[
$type][$component])) {
310 $types[
$type][$component] = [];
314 $commit_link = $this->makeCommitLink($commit);
316 if (!empty($commit[
'closes'])) {
317 $closes .=
'closes ';
318 foreach ($commit[
'closes'] as $issue_id) {
319 $closes .= $this->makeIssueLink($issue_id) .
', ';
323 $types[
$type][$component][] = trim(vsprintf(
'%s %s %s', [
337 if (!isset($types[
$type])) {
341 $section =
"#### {$label}" . PHP_EOL . PHP_EOL;
343 foreach ($types[
$type] as $component => $commits) {
344 if (count($commits) === 1) {
345 $section .=
"* **{$component}:** {$commits[0]}" . PHP_EOL;
347 $section .=
"* **{$component}:**" . PHP_EOL;
349 foreach ($commits as $commit) {
350 $section .=
' * ' . $commit . PHP_EOL;
358 return trim(implode(PHP_EOL . PHP_EOL,
$sections));
369 if (empty($contributors)) {
373 $section =
'#### Contributors' . PHP_EOL . PHP_EOL;
375 foreach ($contributors as $contributor) {
376 $section .=
"* {$contributor['name']} ({$contributor['count']})" . PHP_EOL;
388 $version = $this->getOption(
'version',
'');
390 $date = date(
'Y-m-d');
393 if ($parts[2] ===
'0') {
395 $section .=
"## {$version} ({$date})";
398 $section .=
"### {$version} ({$date})";
412 if (empty($commit)) {
416 return vsprintf(
'[%s](%s/commit/%s)', [
417 $commit[
'short_hash'],
418 $this->getOption(
'repository'),
431 if (empty($issue_id)) {
435 return vsprintf(
'[#%s](%s/issues/%s)', [
437 $this->getOption(
'repository'),
450 $contents = file_get_contents($this->getOption(
'changelog'));
451 $first_anchor = strpos(
$contents,
'<a name="');
452 if ($first_anchor !==
false) {
458 file_put_contents($this->getOption(
'changelog'),
$contents);
472 exec($command,
$output, $result_code);
474 if ($result_code !== 0) {
return[ 'admin/delete_admin_notices'=>['access'=> 'admin'], 'admin/menu/save'=>['access'=> 'admin'], 'admin/plugins/activate'=>['access'=> 'admin'], 'admin/plugins/activate_all'=>['access'=> 'admin'], 'admin/plugins/deactivate'=>['access'=> 'admin'], 'admin/plugins/deactivate_all'=>['access'=> 'admin'], 'admin/plugins/set_priority'=>['access'=> 'admin'], 'admin/security/security_txt'=>['access'=> 'admin'], 'admin/security/settings'=>['access'=> 'admin'], 'admin/security/regenerate_site_secret'=>['access'=> 'admin'], 'admin/site/cache/invalidate'=>['access'=> 'admin'], 'admin/site/flush_cache'=>['access'=> 'admin'], 'admin/site/icons'=>['access'=> 'admin'], 'admin/site/set_maintenance_mode'=>['access'=> 'admin'], 'admin/site/set_robots'=>['access'=> 'admin'], 'admin/site/theme'=>['access'=> 'admin'], 'admin/site/unlock_upgrade'=>['access'=> 'admin'], 'admin/site/settings'=>['access'=> 'admin'], 'admin/upgrade'=>['access'=> 'admin'], 'admin/upgrade/reset'=>['access'=> 'admin'], 'admin/user/ban'=>['access'=> 'admin'], 'admin/user/bulk/ban'=>['access'=> 'admin'], 'admin/user/bulk/delete'=>['access'=> 'admin'], 'admin/user/bulk/unban'=>['access'=> 'admin'], 'admin/user/bulk/validate'=>['access'=> 'admin'], 'admin/user/change_email'=>['access'=> 'admin'], 'admin/user/delete'=>['access'=> 'admin'], 'admin/user/login_as'=>['access'=> 'admin'], 'admin/user/logout_as'=>[], 'admin/user/makeadmin'=>['access'=> 'admin'], 'admin/user/resetpassword'=>['access'=> 'admin'], 'admin/user/removeadmin'=>['access'=> 'admin'], 'admin/user/unban'=>['access'=> 'admin'], 'admin/user/validate'=>['access'=> 'admin'], 'annotation/delete'=>[], 'avatar/upload'=>[], 'comment/save'=>[], 'diagnostics/download'=>['access'=> 'admin'], 'entity/chooserestoredestination'=>[], 'entity/delete'=>[], 'entity/mute'=>[], 'entity/restore'=>[], 'entity/subscribe'=>[], 'entity/trash'=>[], 'entity/unmute'=>[], 'entity/unsubscribe'=>[], 'login'=>['access'=> 'logged_out'], 'logout'=>[], 'notifications/mute'=>['access'=> 'public'], 'plugins/settings/remove'=>['access'=> 'admin'], 'plugins/settings/save'=>['access'=> 'admin'], 'plugins/usersettings/save'=>[], 'register'=>['access'=> 'logged_out', 'middleware'=>[\Elgg\Router\Middleware\RegistrationAllowedGatekeeper::class,],], 'river/delete'=>[], 'settings/notifications'=>[], 'settings/notifications/subscriptions'=>[], 'user/changepassword'=>['access'=> 'public'], 'user/requestnewpassword'=>['access'=> 'public'], 'useradd'=>['access'=> 'admin'], 'usersettings/save'=>[], 'widgets/add'=>[], 'widgets/delete'=>[], 'widgets/move'=>[], 'widgets/save'=>[],]
Exception thrown if an argument is not of the expected type.
Helper class to write the changelog during release.
formatContributors(array $contributors)
Format the contributors into a section.
getGitContributors(array $options=[])
Get the contributors.
makeIssueLink(int $issue_id)
Generate a link to a GitHub issue.
getGitCommits(array $options)
Get all the commits.
formatHeader()
Format release header.
getGitTags()
Get the current git tags.
formatCommits(array $commits)
Format the different commits into sections.
makeCommitLink(array $commit)
Get a link to a GitHub commit.
writeChangelog(string $release_notes)
Write the release notes to the changelog.
getOption(string $option, mixed $default=null)
Get an option.
__construct(array $options=[])
Constructor.
executeCommand(string $command)
Execute a command.
readNotes()
Read anything in the changelog before the first '' and consider this release notes.
__invoke()
Write the changelog for the current release.
static elgg()
Get the Elgg codebase path with "/".
if($who_can_change_language==='nobody') elseif($who_can_change_language==='admin_only' &&!elgg_is_admin_logged_in()) $options
if($item instanceof \ElggEntity) elseif($item instanceof \ElggRiverItem) elseif($item instanceof \ElggRelationship) elseif(is_callable([ $item, 'getType']))
if(!empty($title) &&!empty($icon_name)) if(!empty($title)) if(!empty($menu)) if(!empty($header)) if(!empty($body)) $contents
if(parse_url(elgg_get_site_url(), PHP_URL_PATH) !=='/') if(file_exists(elgg_get_root_path() . 'robots.txt'))
Set robots.txt.