Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7dfda1f99 | ||
|
|
93c81d0fa6 | ||
|
|
e9b55bb0e1 | ||
|
|
426d60b692 | ||
|
|
60db82e459 | ||
|
|
c10866bffd | ||
|
|
c127a1d065 | ||
|
|
cd5405fe62 | ||
|
|
98fd2fba5a | ||
|
|
5c843dc76f | ||
|
|
37832b72da | ||
|
|
aab39f66af |
@@ -1,13 +1,13 @@
|
||||
# Projects Portfolio
|
||||
|
||||
Create a beautifully structured, developer-first showcase directory for your WordPress® plugins, themes, and patterns - powered by [GitHub](https://git.keithsolomon.net/Solo-Web-Works/Projects-Portfolio).
|
||||
Create a beautifully structured, developer-first showcase directory for your WordPress plugins, themes, and patterns - powered by git.
|
||||
|
||||
## What It Does
|
||||
|
||||
**Projects Portfolio** adds a custom post type (`projects`) and taxonomy (`project-type`) to your WordPress® admin, allowing you to:
|
||||
**Projects Portfolio** adds a custom post type (`projects`) and taxonomy (`project-type`) to your WordPress admin, allowing you to:
|
||||
|
||||
- Add plugins, themes, or patterns as projects.
|
||||
- Connect each project to a GitHub repository.
|
||||
- Connect each project to a git repository.
|
||||
- Automatically fetch and display data like:
|
||||
- Latest version
|
||||
- Stars, forks, issues
|
||||
@@ -27,14 +27,14 @@ Create a beautifully structured, developer-first showcase directory for your Wor
|
||||
### From GitHub
|
||||
|
||||
1. **Download the latest ZIP** from the [GitHub Releases page](https://git.keithsolomon.net/Solo-Web-Works/Projects-Portfolio/releases).
|
||||
2. Go to your WordPress® Dashboard → Plugins → Add New → Upload Plugin.
|
||||
2. Go to your WordPress Dashboard → Plugins → Add New → Upload Plugin.
|
||||
3. Upload the ZIP and activate the plugin.
|
||||
|
||||
### From [keithsolomon.net](https://keithsolomon.net)
|
||||
|
||||
1. Visit the official plugin page: [Projects Portfolio](https://keithsolomon.net/projects/projects-portfolio).
|
||||
2. Download the ZIP.
|
||||
3. Install it via the WordPress® dashboard like above.
|
||||
3. Install it via the WordPress dashboard like above.
|
||||
|
||||
---
|
||||
|
||||
@@ -42,7 +42,7 @@ Create a beautifully structured, developer-first showcase directory for your Wor
|
||||
|
||||
### Add a New Project
|
||||
|
||||
1. In the WordPress® admin, go to **Projects → Add New**.
|
||||
1. In the WordPress admin, go to **Projects → Add New**.
|
||||
2. Add your project title, description, and featured image.
|
||||
3. Select a **Project Type**: Plugin, Theme, or Pattern.
|
||||
4. In the sidebar, choose **Provider** (GitHub or Gitea) and paste the **Repository URL** (e.g., `https://github.com/username/repo` or `https://codeberg.org/username/repo`).
|
||||
@@ -79,7 +79,7 @@ Enable/disable the following GitHub data in your project views:
|
||||
- Language
|
||||
- Downloads
|
||||
- Stars / Forks / Issues
|
||||
- GitHub Owner
|
||||
- Repo Owner
|
||||
|
||||
### Archive Settings
|
||||
|
||||
@@ -94,8 +94,8 @@ Toggle components for the project archive view:
|
||||
|
||||
To connect a project to GitHub:
|
||||
|
||||
1. Paste the full repo URL into the **GitHub URL** field when editing a Project.
|
||||
2. Make sure your GitHub repo has a release with a `.zip` asset or a valid `zipball_url`.
|
||||
1. Paste the full repo URL into the **Repository URL** field when editing a Project.
|
||||
2. Make sure your repo has a release with a `.zip` asset or a valid `zipball_url`.
|
||||
|
||||
### Optional: Add a GitHub API Token
|
||||
|
||||
@@ -194,14 +194,14 @@ Each project includes social sharing links for:
|
||||
|
||||
## Support & Contributions
|
||||
|
||||
Have a feature request or bug report? Open an issue on [GitHub](https://github.com/robertdevore/projects-portfolio/issues) or contribute via pull request.
|
||||
Have a feature request or bug report? Open an issue on [the repo](https://git.keithsolomon.net/Solo-Web-Works/Projects-Portfolio/issues) or contribute via pull request.
|
||||
|
||||
## License
|
||||
|
||||
Projects for WordPress® is licensed under the [GNU GPL v2+](http://www.gnu.org/licenses/gpl-2.0.txt).
|
||||
Projects for WordPress is licensed under the [GNU GPL v2+](http://www.gnu.org/licenses/gpl-2.0.txt).
|
||||
|
||||
## Author
|
||||
|
||||
Built and maintained by [Robert DeVore](https://www.robertdevore.com).
|
||||
Built and maintained by [Keith Solomon](https://keithsolomon.net).
|
||||
|
||||
Follow on [Twitter](https://twitter.com/deviorobert) or sponsor development on [GitHub Sponsors](https://github.com/sponsors/robertdevore).
|
||||
Follow on [Twitter](https://twitter.com/KeithInWPG).
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
border-radius: 50%;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.project-social-sharing a:hover {
|
||||
@@ -35,6 +36,14 @@
|
||||
transition: stroke 0.3s;
|
||||
}
|
||||
|
||||
/* Tabler-style icons include a viewport <rect> with no fill; without
|
||||
`stroke="none"` it inherits the parent's stroke color and renders as
|
||||
a square outline inside the round button. Suppress that stroke on
|
||||
the rect alone. */
|
||||
.project-social-sharing svg rect {
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
.project-social-sharing a:hover svg {
|
||||
stroke: #ffffff;
|
||||
}
|
||||
@@ -82,16 +91,28 @@
|
||||
|
||||
.project-owner img {
|
||||
display: block;
|
||||
margin: 0 auto 0;
|
||||
max-width: 50px;
|
||||
margin: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.project-owner span:last-of-type {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
align-items: end;
|
||||
.project-owner-avatar {
|
||||
flex: 0 0 auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.project-owner-name {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.project-owner-follow {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.project-meta-table th {
|
||||
@@ -119,7 +140,7 @@
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.project-buttons a.button.project-github-button {
|
||||
.project-buttons a.button.project-repo-button {
|
||||
display: block;
|
||||
background-color: #e0e0e0;
|
||||
color: #333;
|
||||
@@ -128,9 +149,10 @@
|
||||
margin: 12px 0;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
border: 1px solid #c9c9c9;
|
||||
}
|
||||
|
||||
.project-buttons a.button.project-github-button:hover {
|
||||
.project-buttons a.button.project-repo-button:hover {
|
||||
background-color: #c9c9c9;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-facebook"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 369 B |
@@ -0,0 +1,17 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-linkedin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" />
|
||||
<rect width="4" height="12" x="2" y="9" />
|
||||
<circle cx="4" cy="4" r="2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 460 B |
@@ -0,0 +1,16 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-mail"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect width="20" height="16" x="2" y="4" rx="2" />
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 394 B |
@@ -0,0 +1,16 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-pin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 17v5" />
|
||||
<path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 525 B |
@@ -0,0 +1,19 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-share-2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="18" cy="5" r="3" />
|
||||
<circle cx="6" cy="12" r="3" />
|
||||
<circle cx="18" cy="19" r="3" />
|
||||
<line x1="8.59" x2="15.42" y1="13.51" y2="17.49" />
|
||||
<line x1="15.41" x2="8.59" y1="6.51" y2="10.49" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 497 B |
@@ -0,0 +1,15 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-twitter"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 438 B |
@@ -0,0 +1,15 @@
|
||||
<!-- @license lucide-static v0.460.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-message-circle"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 340 B |
@@ -186,7 +186,13 @@ class Gitea_Provider implements Repository_Provider {
|
||||
return null;
|
||||
}
|
||||
|
||||
$release = $body[0];
|
||||
// Gitea's /releases/latest returns a single release OBJECT (associative array),
|
||||
// not a list. Some endpoints / older Gitea versions may return a list; handle both.
|
||||
$release = isset( $body['tag_name'] ) ? $body : ( $body[0] ?? null );
|
||||
if ( ! is_array( $release ) || empty( $release['tag_name'] ?? '' ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
set_transient( $cache_key, $release, HOUR_IN_SECONDS );
|
||||
return $release;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Plugin Name: Projects Portfolio
|
||||
* Description: Create a showcase directory for projects (plugins, themes, patterns) with custom post types, taxonomies, and download functionality.
|
||||
* Plugin URI: https://git.keithsolomon.net/Solo-Web-Works/Projects-Portfolio
|
||||
* Version: 1.1.1
|
||||
* Version: 1.1.9
|
||||
* Author: Keith Solomon
|
||||
* Author URI: https://keithsolomon.net
|
||||
* License: GPL-2.0+
|
||||
@@ -39,7 +39,7 @@ $myUpdateChecker = PucFactory::buildUpdateChecker(
|
||||
// PUC's plain JSON metadata mode, so we skip the call rather than throw.
|
||||
|
||||
// Current plugin version.
|
||||
define( 'PROJECTS_PORTFOLIO_VERSION', '1.1.1' );
|
||||
define( 'PROJECTS_PORTFOLIO_VERSION', '1.1.9' );
|
||||
|
||||
// Add the required files.
|
||||
require 'admin/admin-settings.php';
|
||||
@@ -112,7 +112,10 @@ function projects_portfolio_handle_download_redirect() {
|
||||
update_post_meta( $project_id, '_projects_portfolio_download_count', $download_count );
|
||||
|
||||
// Redirect to the release ZIP on the project's host.
|
||||
wp_safe_redirect( esc_url_raw( $download_url ) );
|
||||
// Use wp_redirect() (not wp_safe_redirect()) because the destination
|
||||
// is an external host the user has explicitly configured — wp_safe_redirect
|
||||
// would reject it and fall back to admin_url().
|
||||
wp_redirect( esc_url_raw( $download_url ), 302 ); // phpcs:ignore
|
||||
exit;
|
||||
} else {
|
||||
wp_die(
|
||||
@@ -270,13 +273,9 @@ function projects_portfolio_enqueue_project_styles() {
|
||||
}
|
||||
|
||||
if ( is_singular( 'projects' ) ) {
|
||||
wp_enqueue_script(
|
||||
'projects-wp-buttons',
|
||||
plugin_dir_url( __FILE__ ) . 'assets/js/buttons.js',
|
||||
array(),
|
||||
PROJECTS_PORTFOLIO_VERSION,
|
||||
true
|
||||
);
|
||||
// assets/js/buttons.js was used to render GitHub-style follow buttons.
|
||||
// The Follow button now uses a plain styled link (works for any provider),
|
||||
// so the script is no longer enqueued.
|
||||
}
|
||||
}
|
||||
add_action( 'wp_enqueue_scripts', 'projects_portfolio_enqueue_project_styles' );
|
||||
@@ -351,39 +350,47 @@ function projects_portfolio_social_sharing_buttons( $project_id ) {
|
||||
|
||||
$html = '<div class="project-social-sharing">';
|
||||
|
||||
$svg_icon = function( string $name, string $file ) use ( &$html ) {
|
||||
// Render each social icon as an <img> referencing a real .svg file
|
||||
// shipped under assets/icons/. This bypasses any kses data: URI stripping
|
||||
// and ensures the icon loads as a normal image via standard img rules.
|
||||
$src = plugins_url( 'assets/icons/' . $file, __FILE__ );
|
||||
$html .= '<img src="' . esc_url( $src ) . '" alt="' . esc_attr( $name ) . '" width="20" height="20" style="width:20px;height:20px;display:inline-block;vertical-align:middle;" />';
|
||||
};
|
||||
|
||||
// Facebook.
|
||||
$html .= '<a href="https://www.facebook.com/sharer/sharer.php?u=' . $url . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-facebook" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><rect x="0" y="0" width="24" height="24" fill="none"/><path d="M7 10v-3a1 1 0 0 1 1 -1h3v-4h4v4h3a1 1 0 0 1 1 1v3h-4v10h-4v-10h-3" /></svg>';
|
||||
$svg_icon( 'Facebook', 'facebook.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
// X (Twitter).
|
||||
$html .= '<a href="https://twitter.com/intent/tweet?text=' . $title . '&url=' . $url . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-x" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 4l10 16m0 -16l-10 16" /></svg>';
|
||||
$svg_icon( 'X', 'x.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
// LinkedIn.
|
||||
$html .= '<a href="https://www.linkedin.com/sharing/share-offsite/?url=' . $url . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-linkedin" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><rect x="4" y="4" width="16" height="16" rx="2" /><line x1="8" y1="11" x2="8" y2="16" /><line x1="8" y1="8" x2="8" y2="8.01" /><line x1="12" y1="16" x2="12" y2="11" /><path d="M16 16v-3a2 2 0 0 0 -4 0" /></svg>';
|
||||
$svg_icon( 'LinkedIn', 'linkedin.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
// Reddit.
|
||||
$html .= '<a href="https://www.reddit.com/submit?url=' . $url . '&title=' . $title . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-reddit" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><circle cx="12" cy="12" r="9" /><path d="M12 12m-6 0a6 6 0 1 0 12 0a6 6 0 1 0 -12 0" /><path d="M12 12h0" /><path d="M8.5 13c.667 .667 1.333 1 2 1s1.333 -.333 2 -1" /></svg>';
|
||||
$svg_icon( 'Reddit', 'reddit.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
// WhatsApp.
|
||||
$html .= '<a href="https://wa.me/?text=' . $title . '%20' . $url . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-whatsapp" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 21l1.65 -4.75a9 9 0 1 1 3.85 3.85z" /><path d="M9 10c1 2 3 3 5 4" /><path d="M9 13c1 1 2 2 4 3" /></svg>';
|
||||
$html .= '<a href="https://www.whatsapp.com/send?text=' . $title . '%20' . $url . '" target="_blank" rel="noopener noreferrer">';
|
||||
$svg_icon( 'WhatsApp', 'whatsapp.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
// Pinterest.
|
||||
$html .= '<a href="https://pinterest.com/pin/create/button/?url=' . $url . '&description=' . $title . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-pinterest" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><circle cx="12" cy="12" r="9" /><path d="M8 17c1 -2 1.5 -4 .5 -6s-.5 -4 .5 -6" /><path d="M15 11c.667 -1 1.667 -2.333 3 -4" /></svg>';
|
||||
$svg_icon( 'Pinterest', 'pinterest.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
// Email.
|
||||
$html .= '<a href="mailto:?subject=' . $title . '&body=' . $url . '" target="_blank" rel="noopener noreferrer">';
|
||||
$html .= '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-mail" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="#0073aa" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 7l9 6l9 -6" /><rect x="3" y="5" width="18" height="14" rx="2" /></svg>';
|
||||
$svg_icon( 'Email', 'mail.svg' );
|
||||
$html .= '</a>';
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
@@ -4,7 +4,7 @@ $is_fse_theme = wp_theme_has_theme_json() && function_exists( 'wp_is_block_theme
|
||||
|
||||
if ( $is_fse_theme ) {
|
||||
wp_head();
|
||||
echo do_blocks( '<!-- wp:template-part {"slug":"header"} /-->' );
|
||||
echo do_blocks( '<!-- wp:template-part {"slug":"header"} /-->' ); // phpcs:ignore
|
||||
} else {
|
||||
get_header();
|
||||
}
|
||||
@@ -69,12 +69,13 @@ if ( $last_updated ) {
|
||||
<?php esc_html_e( 'Download Now', 'projects-wp' ); ?>
|
||||
</a>
|
||||
<?php if ( $repo_url ) : ?>
|
||||
<a href="<?php echo esc_url( $browse_url ); ?>" class="button project-github-button" target="_blank" rel="noopener noreferrer">
|
||||
<a href="<?php echo esc_url( $browse_url ); ?>" class="button project-repo-button" target="_blank" rel="noopener noreferrer">
|
||||
<?php esc_html_e( 'View Repo', 'projects-wp' ); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e( 'Repository:', 'projects-wp' ); ?> <?php esc_html_e( 'No repository linked.', 'projects-wp' ); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php do_action( 'projects_after_download_button', $project_id ); ?>
|
||||
</div>
|
||||
|
||||
<div class="project-meta">
|
||||
@@ -140,18 +141,13 @@ if ( $last_updated ) {
|
||||
</div>
|
||||
|
||||
<?php if ( $settings['templates']['github_owner'] && $owner_avatar && $owner_name ) : ?>
|
||||
<a href="<?php echo esc_url( $browse_url ); ?>">
|
||||
<div class="project-owner">
|
||||
<span>
|
||||
<img src="<?php echo esc_url( $owner_avatar ); ?>" alt="<?php esc_attr_e( $owner_name ); ?>" class="owner-avatar" style="width: 50px; height: 50px; border-radius: 50%;" />
|
||||
<span class="project-owner-avatar" style="display:block !important;width:40px !important;height:40px !important;min-width:40px !important;min-height:40px !important;max-width:40px !important;max-height:40px !important;border-radius:50% !important;background-image:url('<?php echo esc_url( $owner_avatar ); ?>') !important;background-size:40px 40px !important;background-position:center center !important;background-repeat:no-repeat !important;flex-shrink:0 !important;flex-grow:0 !important;" aria-label="<?php echo esc_attr( $owner_name ); ?>" role="img"></span>
|
||||
<span class="project-owner-name">
|
||||
<a href="<?php echo esc_url( $owner_url ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html( $owner_name ); ?></a>
|
||||
</span>
|
||||
<span>
|
||||
<strong>
|
||||
<a href="<?php echo esc_url( $owner_url ); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e( $owner_name ); ?></a>
|
||||
</strong>
|
||||
</span>
|
||||
<span>
|
||||
<a class="github-button" href="https://github.com/<?php esc_html_e( $owner_name ); ?>" data-show-count="true" data-color-scheme="no-preference: light; light: light; dark: dark;" data-size="large" aria-label="Follow @<?php esc_html_e( $owner_name ); ?> on GitHub"><?php esc_attr_e( 'Follow', 'projects-wp' ) ?></a>
|
||||
<span class="project-owner-follow">
|
||||
<a class="button project-follow-button" href="<?php echo esc_url( $owner_url ); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Follow', 'projects-wp' ); ?></a>
|
||||
</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -136,6 +136,29 @@ class Gitea_Provider_Test extends \PHPUnit\Framework\TestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public function test_release_object_shape_picks_first_tag_from_object(): void {
|
||||
// Gitea's /releases/latest returns a single release OBJECT (associative array),
|
||||
// not a list. The implementation must accept either shape.
|
||||
$body = json_encode( [
|
||||
'tag_name' => 'v2.1.0',
|
||||
'name' => 'v2.1.0',
|
||||
'assets' => [
|
||||
[ 'name' => 'release.zip', 'browser_download_url' => 'https://example/release.zip' ],
|
||||
],
|
||||
] );
|
||||
\Brain\Monkey\Functions\expect( 'wp_remote_get' )
|
||||
->twice() // get_release_url and get_latest_version both fetch
|
||||
->andReturn( [
|
||||
'response' => [ 'code' => 200 ],
|
||||
'headers' => [],
|
||||
'body' => $body,
|
||||
] );
|
||||
|
||||
$provider = $this->make();
|
||||
$this->assertSame( 'https://example/release.zip', $provider->get_release_url() );
|
||||
$this->assertSame( 'v2.1.0', $provider->get_latest_version() );
|
||||
}
|
||||
|
||||
public function test_release_url_empty_array_returns_null(): void {
|
||||
\Brain\Monkey\Functions\expect( 'wp_remote_get' )
|
||||
->once()
|
||||
|
||||