Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c55802343 | |||
| 8930b4b40e | |||
| 3f2903a022 | |||
| eb1e5fe477 | |||
| 14ddae2a25 | |||
| d5652b4e93 | |||
| 249f3f2615 | |||
| 8730a77a69 | |||
| d477884ee4 | |||
| af5765c703 | |||
| d9142c4eab | |||
| 7a1f523f40 | |||
| ff63b8908f | |||
| 767a9d4504 | |||
| 6fd4069b4c | |||
| 062ea86d7f | |||
| d19812e387 | |||
| c120fc5336 | |||
| c8e6a448b2 | |||
| 342477575c | |||
| a4270fc046 | |||
| c6f203b2b0 | |||
| 9bb7345f86 | |||
| 5cb72eb44b | |||
| cc0d26e995 | |||
| b9f971196e |
@@ -1,7 +0,0 @@
|
|||||||
.claude/
|
|
||||||
.mcp.json
|
|
||||||
TODO.md
|
|
||||||
*.min.css
|
|
||||||
*.min.js
|
|
||||||
vendor/
|
|
||||||
node_modules/
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
---
|
|
||||||
name: Architecture Decision Record (ADR)
|
|
||||||
about: Propose or document an architectural decision
|
|
||||||
title: '[ADR] '
|
|
||||||
labels: 'architecture, decision'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## ADR Number
|
|
||||||
ADR-XXXX
|
|
||||||
|
|
||||||
## Status
|
|
||||||
- [ ] Proposed
|
|
||||||
- [ ] Accepted
|
|
||||||
- [ ] Deprecated
|
|
||||||
- [ ] Superseded by ADR-XXXX
|
|
||||||
|
|
||||||
## Context
|
|
||||||
Describe the issue or problem that motivates this decision.
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
State the architecture decision and provide rationale.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
### Positive
|
|
||||||
- List positive consequences
|
|
||||||
|
|
||||||
### Negative
|
|
||||||
- List negative consequences or trade-offs
|
|
||||||
|
|
||||||
### Neutral
|
|
||||||
- List neutral aspects
|
|
||||||
|
|
||||||
## Alternatives Considered
|
|
||||||
### Alternative 1
|
|
||||||
- Description
|
|
||||||
- Pros
|
|
||||||
- Cons
|
|
||||||
- Why not chosen
|
|
||||||
|
|
||||||
### Alternative 2
|
|
||||||
- Description
|
|
||||||
- Pros
|
|
||||||
- Cons
|
|
||||||
- Why not chosen
|
|
||||||
|
|
||||||
## Implementation Plan
|
|
||||||
1. Step 1
|
|
||||||
2. Step 2
|
|
||||||
3. Step 3
|
|
||||||
|
|
||||||
## Stakeholders
|
|
||||||
- **Decision Makers**: @user1, @user2
|
|
||||||
- **Consulted**: @user3, @user4
|
|
||||||
- **Informed**: team-name
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
### Architecture Diagram
|
|
||||||
```
|
|
||||||
[Add diagram or link]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
- Dependency 1
|
|
||||||
- Dependency 2
|
|
||||||
|
|
||||||
### Impact Analysis
|
|
||||||
- **Performance**: [Impact description]
|
|
||||||
- **Security**: [Impact description]
|
|
||||||
- **Scalability**: [Impact description]
|
|
||||||
- **Maintainability**: [Impact description]
|
|
||||||
|
|
||||||
## Testing Strategy
|
|
||||||
- [ ] Unit tests
|
|
||||||
- [ ] Integration tests
|
|
||||||
- [ ] Performance tests
|
|
||||||
- [ ] Security tests
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
- [ ] Architecture documentation updated
|
|
||||||
- [ ] API documentation updated
|
|
||||||
- [ ] Developer guide updated
|
|
||||||
- [ ] Runbook created
|
|
||||||
|
|
||||||
## Migration Path
|
|
||||||
Describe how to migrate from current state to new architecture.
|
|
||||||
|
|
||||||
## Rollback Plan
|
|
||||||
Describe how to rollback if issues occur.
|
|
||||||
|
|
||||||
## Timeline
|
|
||||||
- **Proposal Date**:
|
|
||||||
- **Decision Date**:
|
|
||||||
- **Implementation Start**:
|
|
||||||
- **Expected Completion**:
|
|
||||||
|
|
||||||
## References
|
|
||||||
- Related ADRs:
|
|
||||||
- External resources:
|
|
||||||
- RFCs:
|
|
||||||
|
|
||||||
## Review Checklist
|
|
||||||
- [ ] Aligns with enterprise architecture principles
|
|
||||||
- [ ] Security implications reviewed
|
|
||||||
- [ ] Performance implications reviewed
|
|
||||||
- [ ] Cost implications reviewed
|
|
||||||
- [ ] Compliance requirements met
|
|
||||||
- [ ] Team consensus achieved
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug Report
|
|
||||||
about: Report a bug or issue with the project
|
|
||||||
title: '[BUG] '
|
|
||||||
labels: 'bug'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## Bug Description
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
## Steps to Reproduce
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '...'
|
|
||||||
3. Scroll down to '...'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
## Expected Behavior
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
## Actual Behavior
|
|
||||||
A clear and concise description of what actually happened.
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
## Environment
|
|
||||||
- **Project**: [e.g., MokoDoliTools, moko-cassiopeia]
|
|
||||||
- **Version**: [e.g., 1.2.3]
|
|
||||||
- **Platform**: [e.g., Dolibarr 18.0, Joomla 5.0]
|
|
||||||
- **PHP Version**: [e.g., 8.1]
|
|
||||||
- **Database**: [e.g., MySQL 8.0, PostgreSQL 14]
|
|
||||||
- **Browser** (if applicable): [e.g., Chrome 120, Firefox 121]
|
|
||||||
- **OS**: [e.g., Ubuntu 22.04, Windows 11]
|
|
||||||
|
|
||||||
## Additional Context
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
||||||
## Possible Solution
|
|
||||||
If you have suggestions on how to fix the issue, please describe them here.
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
- [ ] I have searched for similar issues before creating this one
|
|
||||||
- [ ] I have provided all the requested information
|
|
||||||
- [ ] I have tested this on the latest stable version
|
|
||||||
- [ ] I have checked the documentation and couldn't find a solution
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
blank_issues_enabled: true
|
|
||||||
contact_links:
|
|
||||||
- name: 💼 Enterprise Support
|
|
||||||
url: https://mokoconsulting.tech/enterprise
|
|
||||||
about: Enterprise-level support and consultation services
|
|
||||||
- name: 💬 Ask a Question
|
|
||||||
url: https://mokoconsulting.tech/
|
|
||||||
about: Get help or ask questions through our website
|
|
||||||
- name: 📚 MokoStandards Documentation
|
|
||||||
url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
|
||||||
about: View our coding standards and best practices
|
|
||||||
- name: 🔒 Report a Security Vulnerability
|
|
||||||
url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
|
|
||||||
about: Report security vulnerabilities privately (for critical issues)
|
|
||||||
- name: 💡 Community Discussions
|
|
||||||
url: https://github.com/orgs/mokoconsulting-tech/discussions
|
|
||||||
about: Join community discussions and Q&A
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
name: Documentation Issue
|
|
||||||
about: Report an issue with documentation
|
|
||||||
title: '[DOCS] '
|
|
||||||
labels: 'documentation'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## Documentation Issue
|
|
||||||
|
|
||||||
**Location**:
|
|
||||||
<!-- Specify the file, page, or section with the issue -->
|
|
||||||
|
|
||||||
## Issue Type
|
|
||||||
<!-- Mark the relevant option with an "x" -->
|
|
||||||
- [ ] Typo or grammar error
|
|
||||||
- [ ] Outdated information
|
|
||||||
- [ ] Missing documentation
|
|
||||||
- [ ] Unclear explanation
|
|
||||||
- [ ] Broken links
|
|
||||||
- [ ] Missing examples
|
|
||||||
- [ ] Other (specify below)
|
|
||||||
|
|
||||||
## Description
|
|
||||||
<!-- Clearly describe the documentation issue -->
|
|
||||||
|
|
||||||
## Current Content
|
|
||||||
<!-- Quote or describe the current documentation (if applicable) -->
|
|
||||||
```
|
|
||||||
Current text here
|
|
||||||
```
|
|
||||||
|
|
||||||
## Suggested Improvement
|
|
||||||
<!-- Provide your suggestion for how to improve the documentation -->
|
|
||||||
```
|
|
||||||
Suggested text here
|
|
||||||
```
|
|
||||||
|
|
||||||
## Additional Context
|
|
||||||
<!-- Add any other context, screenshots, or references -->
|
|
||||||
|
|
||||||
## Standards Alignment
|
|
||||||
- [ ] Follows MokoStandards documentation guidelines
|
|
||||||
- [ ] Uses en_US/en_GB localization
|
|
||||||
- [ ] Includes proper SPDX headers where applicable
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
- [ ] I have searched for similar documentation issues
|
|
||||||
- [ ] I have provided a clear description
|
|
||||||
- [ ] I have suggested an improvement (if applicable)
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
about: Suggest a new feature or enhancement
|
|
||||||
title: '[FEATURE] '
|
|
||||||
labels: 'enhancement'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## Feature Description
|
|
||||||
A clear and concise description of the feature you'd like to see.
|
|
||||||
|
|
||||||
## Problem or Use Case
|
|
||||||
Describe the problem this feature would solve or the use case it addresses.
|
|
||||||
Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
## Proposed Solution
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
## Alternative Solutions
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
Describe how this feature would benefit users:
|
|
||||||
- Who would use this feature?
|
|
||||||
- What problems does it solve?
|
|
||||||
- What value does it add?
|
|
||||||
|
|
||||||
## Implementation Details (Optional)
|
|
||||||
If you have ideas about how this could be implemented, share them here:
|
|
||||||
- Technical approach
|
|
||||||
- Files/components that might need changes
|
|
||||||
- Any concerns or challenges you foresee
|
|
||||||
|
|
||||||
## Additional Context
|
|
||||||
Add any other context, mockups, or screenshots about the feature request here.
|
|
||||||
|
|
||||||
## Relevant Standards
|
|
||||||
Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
|
|
||||||
- [ ] Accessibility (WCAG 2.1 AA)
|
|
||||||
- [ ] Localization (en_US/en_GB)
|
|
||||||
- [ ] Security best practices
|
|
||||||
- [ ] Code quality standards
|
|
||||||
- [ ] Other: [specify]
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
- [ ] I have searched for similar feature requests before creating this one
|
|
||||||
- [ ] I have clearly described the use case and benefits
|
|
||||||
- [ ] I have considered alternative solutions
|
|
||||||
- [ ] This feature aligns with the project's goals and scope
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
---
|
|
||||||
name: Joomla Extension Issue
|
|
||||||
about: Report an issue with a Joomla extension
|
|
||||||
title: '[JOOMLA] '
|
|
||||||
labels: 'joomla'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## Issue Type
|
|
||||||
- [ ] Component Issue
|
|
||||||
- [ ] Module Issue
|
|
||||||
- [ ] Plugin Issue
|
|
||||||
- [ ] Template Issue
|
|
||||||
|
|
||||||
## Extension Details
|
|
||||||
- **Extension Name**: [e.g., moko-cassiopeia]
|
|
||||||
- **Extension Version**: [e.g., 1.2.3]
|
|
||||||
- **Extension Type**: [Component / Module / Plugin / Template]
|
|
||||||
|
|
||||||
## Joomla Environment
|
|
||||||
- **Joomla Version**: [e.g., 4.4.0, 5.0.0]
|
|
||||||
- **PHP Version**: [e.g., 8.1.0]
|
|
||||||
- **Database**: [MySQL / PostgreSQL / MariaDB]
|
|
||||||
- **Database Version**: [e.g., 8.0]
|
|
||||||
- **Server**: [Apache / Nginx / IIS]
|
|
||||||
- **Hosting**: [Shared / VPS / Dedicated / Cloud]
|
|
||||||
|
|
||||||
## Issue Description
|
|
||||||
Provide a clear and detailed description of the issue.
|
|
||||||
|
|
||||||
## Steps to Reproduce
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '...'
|
|
||||||
3. Configure '...'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
## Expected Behavior
|
|
||||||
What you expected to happen.
|
|
||||||
|
|
||||||
## Actual Behavior
|
|
||||||
What actually happened.
|
|
||||||
|
|
||||||
## Error Messages
|
|
||||||
```
|
|
||||||
# Paste any error messages from Joomla error logs
|
|
||||||
# Location: administrator/logs/error.php
|
|
||||||
```
|
|
||||||
|
|
||||||
## Browser Console Errors
|
|
||||||
```javascript
|
|
||||||
// Paste any JavaScript console errors (F12 in browser)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
Add screenshots to help explain the issue.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
```ini
|
|
||||||
# Paste extension configuration (sanitize sensitive data)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installed Extensions
|
|
||||||
List other installed extensions that might conflict:
|
|
||||||
- Extension 1 (version)
|
|
||||||
- Extension 2 (version)
|
|
||||||
|
|
||||||
## Template Overrides
|
|
||||||
- [ ] Using template overrides
|
|
||||||
- [ ] Custom CSS
|
|
||||||
- [ ] Custom JavaScript
|
|
||||||
|
|
||||||
## Additional Context
|
|
||||||
- **Multilingual Site**: [Yes / No]
|
|
||||||
- **Cache Enabled**: [Yes / No]
|
|
||||||
- **Debug Mode**: [Yes / No]
|
|
||||||
- **SEF URLs**: [Yes / No]
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
- [ ] I have cleared Joomla cache
|
|
||||||
- [ ] I have disabled other extensions to test for conflicts
|
|
||||||
- [ ] I have checked Joomla error logs
|
|
||||||
- [ ] I have tested with a default Joomla template
|
|
||||||
- [ ] I have checked browser console for JavaScript errors
|
|
||||||
- [ ] I have searched for similar issues
|
|
||||||
- [ ] I am using a supported Joomla version
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
---
|
|
||||||
name: Question
|
|
||||||
about: Ask a question about usage, features, or best practices
|
|
||||||
title: '[QUESTION] '
|
|
||||||
labels: ['question']
|
|
||||||
assignees: ['jmiller']
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## Question
|
|
||||||
|
|
||||||
**Your question:**
|
|
||||||
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
**What are you trying to accomplish?**
|
|
||||||
|
|
||||||
|
|
||||||
**What have you already tried?**
|
|
||||||
|
|
||||||
|
|
||||||
**Category**:
|
|
||||||
- [ ] Script usage
|
|
||||||
- [ ] Configuration
|
|
||||||
- [ ] Workflow setup
|
|
||||||
- [ ] Documentation interpretation
|
|
||||||
- [ ] Best practices
|
|
||||||
- [ ] Integration
|
|
||||||
- [ ] Other: __________
|
|
||||||
|
|
||||||
## Environment (if relevant)
|
|
||||||
|
|
||||||
**Your setup**:
|
|
||||||
- Operating System:
|
|
||||||
- Version:
|
|
||||||
|
|
||||||
## What You've Researched
|
|
||||||
|
|
||||||
**Documentation reviewed**:
|
|
||||||
- [ ] README.md
|
|
||||||
- [ ] Project documentation
|
|
||||||
- [ ] Other (specify): __________
|
|
||||||
|
|
||||||
**Similar issues/questions found**:
|
|
||||||
- #
|
|
||||||
- #
|
|
||||||
|
|
||||||
## Expected Outcome
|
|
||||||
|
|
||||||
**What result are you hoping for?**
|
|
||||||
|
|
||||||
|
|
||||||
## Code/Configuration Samples
|
|
||||||
|
|
||||||
**Relevant code or configuration** (if applicable):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Your code here
|
|
||||||
```
|
|
||||||
|
|
||||||
## Additional Context
|
|
||||||
|
|
||||||
**Any other relevant information:**
|
|
||||||
|
|
||||||
|
|
||||||
**Screenshots** (if helpful):
|
|
||||||
|
|
||||||
|
|
||||||
## Urgency
|
|
||||||
|
|
||||||
- [ ] Urgent (blocking work)
|
|
||||||
- [ ] Normal (can work on other things meanwhile)
|
|
||||||
- [ ] Low priority (just curious)
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
|
|
||||||
- [ ] I have searched existing issues and discussions
|
|
||||||
- [ ] I have reviewed relevant documentation
|
|
||||||
- [ ] I have provided sufficient context
|
|
||||||
- [ ] I have included code/configuration samples if relevant
|
|
||||||
- [ ] This is a genuine question (not a bug report or feature request)
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
---
|
|
||||||
name: Request for Comments (RFC)
|
|
||||||
about: Propose a significant change for community discussion
|
|
||||||
title: '[RFC] '
|
|
||||||
labels: 'rfc, discussion'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## RFC Summary
|
|
||||||
One-paragraph summary of the proposal.
|
|
||||||
|
|
||||||
## Motivation
|
|
||||||
Why are we doing this? What use cases does it support? What is the expected outcome?
|
|
||||||
|
|
||||||
## Detailed Design
|
|
||||||
### Overview
|
|
||||||
Provide a detailed explanation of the proposed change.
|
|
||||||
|
|
||||||
### API Changes (if applicable)
|
|
||||||
```php
|
|
||||||
// Before
|
|
||||||
function oldApi($param1) { }
|
|
||||||
|
|
||||||
// After
|
|
||||||
function newApi($param1, $param2) { }
|
|
||||||
```
|
|
||||||
|
|
||||||
### User Experience Changes
|
|
||||||
Describe how users will interact with this change.
|
|
||||||
|
|
||||||
### Implementation Approach
|
|
||||||
High-level implementation strategy.
|
|
||||||
|
|
||||||
## Drawbacks
|
|
||||||
Why should we *not* do this?
|
|
||||||
|
|
||||||
## Alternatives
|
|
||||||
What other designs have been considered? What is the impact of not doing this?
|
|
||||||
|
|
||||||
### Alternative 1
|
|
||||||
- Description
|
|
||||||
- Trade-offs
|
|
||||||
|
|
||||||
### Alternative 2
|
|
||||||
- Description
|
|
||||||
- Trade-offs
|
|
||||||
|
|
||||||
## Adoption Strategy
|
|
||||||
How will existing users adopt this? Is this a breaking change?
|
|
||||||
|
|
||||||
### Migration Guide
|
|
||||||
```bash
|
|
||||||
# Steps to migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deprecation Timeline
|
|
||||||
- **Announcement**:
|
|
||||||
- **Deprecation**:
|
|
||||||
- **Removal**:
|
|
||||||
|
|
||||||
## Unresolved Questions
|
|
||||||
- Question 1
|
|
||||||
- Question 2
|
|
||||||
|
|
||||||
## Future Possibilities
|
|
||||||
What future work does this enable?
|
|
||||||
|
|
||||||
## Impact Assessment
|
|
||||||
### Performance
|
|
||||||
Expected performance impact.
|
|
||||||
|
|
||||||
### Security
|
|
||||||
Security considerations and implications.
|
|
||||||
|
|
||||||
### Compatibility
|
|
||||||
- **Backward Compatible**: [Yes / No]
|
|
||||||
- **Breaking Changes**: [List]
|
|
||||||
|
|
||||||
### Maintenance
|
|
||||||
Long-term maintenance considerations.
|
|
||||||
|
|
||||||
## Community Input
|
|
||||||
### Stakeholders
|
|
||||||
- [ ] Core team
|
|
||||||
- [ ] Module developers
|
|
||||||
- [ ] End users
|
|
||||||
- [ ] Enterprise customers
|
|
||||||
|
|
||||||
### Feedback Period
|
|
||||||
**Duration**: [e.g., 2 weeks]
|
|
||||||
**Deadline**: [date]
|
|
||||||
|
|
||||||
## Implementation Timeline
|
|
||||||
### Phase 1: Design
|
|
||||||
- [ ] RFC discussion
|
|
||||||
- [ ] Design finalization
|
|
||||||
- [ ] Approval
|
|
||||||
|
|
||||||
### Phase 2: Implementation
|
|
||||||
- [ ] Core implementation
|
|
||||||
- [ ] Tests
|
|
||||||
- [ ] Documentation
|
|
||||||
|
|
||||||
### Phase 3: Release
|
|
||||||
- [ ] Beta release
|
|
||||||
- [ ] Feedback collection
|
|
||||||
- [ ] Stable release
|
|
||||||
|
|
||||||
## Success Metrics
|
|
||||||
How will we measure success?
|
|
||||||
- Metric 1
|
|
||||||
- Metric 2
|
|
||||||
|
|
||||||
## References
|
|
||||||
- Related RFCs:
|
|
||||||
- External documentation:
|
|
||||||
- Prior art:
|
|
||||||
|
|
||||||
## Open Questions for Community
|
|
||||||
1. Question 1?
|
|
||||||
2. Question 2?
|
|
||||||
|
|
||||||
---
|
|
||||||
**Note**: This RFC is open for community discussion. Please provide feedback in the comments below.
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
---
|
|
||||||
name: Security Vulnerability Report
|
|
||||||
about: Report a security vulnerability (use only for non-critical issues)
|
|
||||||
title: '[SECURITY] '
|
|
||||||
labels: 'security'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## ⚠️ IMPORTANT: Private Disclosure Required
|
|
||||||
|
|
||||||
**For critical security vulnerabilities, DO NOT use this template.**
|
|
||||||
Follow the process in [SECURITY.md](../SECURITY.md) for responsible disclosure.
|
|
||||||
|
|
||||||
Use this template only for:
|
|
||||||
- Security improvements
|
|
||||||
- Non-critical security suggestions
|
|
||||||
- Security documentation updates
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security Issue
|
|
||||||
|
|
||||||
**Severity**:
|
|
||||||
<!-- Low, Medium, or informational only -->
|
|
||||||
|
|
||||||
## Description
|
|
||||||
<!-- Describe the security concern or improvement suggestion -->
|
|
||||||
|
|
||||||
## Affected Components
|
|
||||||
<!-- List the affected files, features, or components -->
|
|
||||||
|
|
||||||
## Suggested Mitigation
|
|
||||||
<!-- Describe how this could be addressed -->
|
|
||||||
|
|
||||||
## Standards Reference
|
|
||||||
Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
|
|
||||||
- [ ] SPDX license identifiers
|
|
||||||
- [ ] Secret management
|
|
||||||
- [ ] Dependency security
|
|
||||||
- [ ] Access control
|
|
||||||
- [ ] Other: [specify]
|
|
||||||
|
|
||||||
## Additional Context
|
|
||||||
<!-- Add any other context about the security concern -->
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
- [ ] This is NOT a critical vulnerability requiring private disclosure
|
|
||||||
- [ ] I have reviewed the SECURITY.md policy
|
|
||||||
- [ ] I have provided sufficient detail for evaluation
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
name: Version Bump
|
|
||||||
about: Request or track a version change
|
|
||||||
title: '[VERSION] '
|
|
||||||
labels: 'version, type: version'
|
|
||||||
assignees: 'jmiller'
|
|
||||||
---
|
|
||||||
|
|
||||||
## Version Change
|
|
||||||
|
|
||||||
**Current version**: <!-- e.g., 01.02.03 -->
|
|
||||||
**Requested version**: <!-- e.g., 01.03.00 -->
|
|
||||||
**Change type**: <!-- patch / minor / major -->
|
|
||||||
|
|
||||||
## Reason
|
|
||||||
|
|
||||||
<!-- Why is this version bump needed? -->
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
|
|
||||||
- [ ] README.md `VERSION:` field updated
|
|
||||||
- [ ] CHANGELOG.md entry added
|
|
||||||
- [ ] Module descriptor version updated (Dolibarr: `$this->version`, Joomla: `<version>`)
|
|
||||||
- [ ] All file headers will be auto-propagated by `sync-version-on-merge` workflow
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
# FILE INFORMATION
|
|
||||||
# DEFGROUP: Gitea.Workflow
|
|
||||||
# INGROUP: moko-platform.Automation
|
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
|
||||||
# PATH: /.gitea/workflows/branch-protection.yml
|
|
||||||
# BRIEF: Apply standardised branch protection rules to all governed repositories
|
|
||||||
#
|
|
||||||
# +========================================================================+
|
|
||||||
# | BRANCH PROTECTION SETUP |
|
|
||||||
# +========================================================================+
|
|
||||||
# | |
|
|
||||||
# | Applies protection rules for: main, dev, rc, beta, alpha |
|
|
||||||
# | |
|
|
||||||
# | main — Require PR, block rejected reviews, no force push |
|
|
||||||
# | dev — Allow push, no force push, no delete |
|
|
||||||
# | rc — Allow push, no force push, no delete |
|
|
||||||
# | beta — Allow push, no force push, no delete |
|
|
||||||
# | alpha — Allow push, no force push, no delete |
|
|
||||||
# | |
|
|
||||||
# | jmiller has override authority on all branches. |
|
|
||||||
# | |
|
|
||||||
# +========================================================================+
|
|
||||||
|
|
||||||
name: Branch Protection Setup
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 2 * * 1' # Weekly Monday 02:00 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
dry_run:
|
|
||||||
description: 'Preview mode (no changes)'
|
|
||||||
required: false
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
repos:
|
|
||||||
description: 'Comma-separated repo names (empty = all governed repos)'
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
|
|
||||||
env:
|
|
||||||
GITEA_URL: https://git.mokoconsulting.tech
|
|
||||||
GITEA_ORG: MokoConsulting
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
protect:
|
|
||||||
name: Apply Branch Protection Rules
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Determine target repos
|
|
||||||
id: repos
|
|
||||||
env:
|
|
||||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
|
||||||
run: |
|
|
||||||
API="${GITEA_URL}/api/v1"
|
|
||||||
|
|
||||||
# Platform/standards/infra repos to exclude
|
|
||||||
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards moko-platform MokoTesting"
|
|
||||||
EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate"
|
|
||||||
|
|
||||||
if [ -n "${{ inputs.repos }}" ]; then
|
|
||||||
# User-specified repos
|
|
||||||
REPOS=$(echo "${{ inputs.repos }}" | tr ',' ' ')
|
|
||||||
else
|
|
||||||
# Fetch all org repos
|
|
||||||
PAGE=1
|
|
||||||
REPOS=""
|
|
||||||
while true; do
|
|
||||||
BATCH=$(curl -sS \
|
|
||||||
-H "Authorization: token ${GA_TOKEN}" \
|
|
||||||
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
|
|
||||||
| jq -r '.[].name // empty')
|
|
||||||
[ -z "$BATCH" ] && break
|
|
||||||
REPOS="$REPOS $BATCH"
|
|
||||||
PAGE=$((PAGE + 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
# Filter out excluded repos
|
|
||||||
FILTERED=""
|
|
||||||
for REPO in $REPOS; do
|
|
||||||
SKIP=false
|
|
||||||
for EX in $EXCLUDE; do
|
|
||||||
if [ "$REPO" = "$EX" ]; then
|
|
||||||
SKIP=true
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [ "$SKIP" = "false" ]; then
|
|
||||||
FILTERED="$FILTERED $REPO"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
REPOS="$FILTERED"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "repos=$REPOS" >> "$GITHUB_OUTPUT"
|
|
||||||
COUNT=$(echo "$REPOS" | wc -w)
|
|
||||||
echo "📋 Target repos (${COUNT}): $REPOS"
|
|
||||||
|
|
||||||
- name: Apply protection rules
|
|
||||||
env:
|
|
||||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
|
||||||
DRY_RUN: ${{ inputs.dry_run || 'false' }}
|
|
||||||
run: |
|
|
||||||
API="${GITEA_URL}/api/v1"
|
|
||||||
REPOS="${{ steps.repos.outputs.repos }}"
|
|
||||||
|
|
||||||
SUCCESS=0
|
|
||||||
FAILED=0
|
|
||||||
SKIPPED=0
|
|
||||||
|
|
||||||
# ── Rule definitions ──────────────────────────────────────
|
|
||||||
# Only the CI bot (jmiller token) can push directly.
|
|
||||||
# All human contributors must use PRs.
|
|
||||||
# Force push disabled on all branches.
|
|
||||||
|
|
||||||
RULE_MAIN='{
|
|
||||||
"rule_name": "main",
|
|
||||||
"enable_push": true,
|
|
||||||
"enable_push_whitelist": true,
|
|
||||||
"push_whitelist_usernames": ["jmiller"],
|
|
||||||
"enable_force_push": false,
|
|
||||||
"enable_force_push_allowlist": false,
|
|
||||||
"force_push_allowlist_usernames": [],
|
|
||||||
"enable_merge_whitelist": false,
|
|
||||||
"required_approvals": 0,
|
|
||||||
"dismiss_stale_approvals": true,
|
|
||||||
"block_on_rejected_reviews": true,
|
|
||||||
"block_on_outdated_branch": false,
|
|
||||||
"priority": 1
|
|
||||||
}'
|
|
||||||
|
|
||||||
RULE_DEV='{
|
|
||||||
"rule_name": "dev",
|
|
||||||
"enable_push": true,
|
|
||||||
"enable_push_whitelist": true,
|
|
||||||
"push_whitelist_usernames": ["jmiller"],
|
|
||||||
"enable_force_push": false,
|
|
||||||
"enable_force_push_allowlist": false,
|
|
||||||
"force_push_allowlist_usernames": [],
|
|
||||||
"enable_merge_whitelist": false,
|
|
||||||
"required_approvals": 0,
|
|
||||||
"block_on_rejected_reviews": false,
|
|
||||||
"priority": 2
|
|
||||||
}'
|
|
||||||
|
|
||||||
RULE_RC='{
|
|
||||||
"rule_name": "rc",
|
|
||||||
"enable_push": true,
|
|
||||||
"enable_push_whitelist": true,
|
|
||||||
"push_whitelist_usernames": ["jmiller"],
|
|
||||||
"enable_force_push": false,
|
|
||||||
"enable_force_push_allowlist": false,
|
|
||||||
"force_push_allowlist_usernames": [],
|
|
||||||
"enable_merge_whitelist": false,
|
|
||||||
"required_approvals": 0,
|
|
||||||
"block_on_rejected_reviews": false,
|
|
||||||
"priority": 3
|
|
||||||
}'
|
|
||||||
|
|
||||||
RULE_BETA='{
|
|
||||||
"rule_name": "beta",
|
|
||||||
"enable_push": true,
|
|
||||||
"enable_push_whitelist": true,
|
|
||||||
"push_whitelist_usernames": ["jmiller"],
|
|
||||||
"enable_force_push": false,
|
|
||||||
"enable_force_push_allowlist": false,
|
|
||||||
"force_push_allowlist_usernames": [],
|
|
||||||
"enable_merge_whitelist": false,
|
|
||||||
"required_approvals": 0,
|
|
||||||
"block_on_rejected_reviews": false,
|
|
||||||
"priority": 4
|
|
||||||
}'
|
|
||||||
|
|
||||||
RULE_ALPHA='{
|
|
||||||
"rule_name": "alpha",
|
|
||||||
"enable_push": true,
|
|
||||||
"enable_push_whitelist": true,
|
|
||||||
"push_whitelist_usernames": ["jmiller"],
|
|
||||||
"enable_force_push": false,
|
|
||||||
"enable_force_push_allowlist": false,
|
|
||||||
"force_push_allowlist_usernames": [],
|
|
||||||
"enable_merge_whitelist": false,
|
|
||||||
"required_approvals": 0,
|
|
||||||
"block_on_rejected_reviews": false,
|
|
||||||
"priority": 5
|
|
||||||
}'
|
|
||||||
|
|
||||||
RULES=("$RULE_MAIN" "$RULE_DEV" "$RULE_RC" "$RULE_BETA" "$RULE_ALPHA")
|
|
||||||
RULE_NAMES=("main" "dev" "rc" "beta" "alpha")
|
|
||||||
|
|
||||||
# ── Apply rules to each repo ──────────────────────────────
|
|
||||||
for REPO in $REPOS; do
|
|
||||||
echo ""
|
|
||||||
echo "═══ ${REPO} ═══"
|
|
||||||
|
|
||||||
for i in "${!RULES[@]}"; do
|
|
||||||
RULE="${RULES[$i]}"
|
|
||||||
NAME="${RULE_NAMES[$i]}"
|
|
||||||
|
|
||||||
if [ "$DRY_RUN" = "true" ]; then
|
|
||||||
echo " [DRY RUN] Would apply rule: ${NAME}"
|
|
||||||
SKIPPED=$((SKIPPED + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Delete existing rule if present (idempotent recreate)
|
|
||||||
ENCODED_NAME=$(echo "$NAME" | sed 's|/|%2F|g')
|
|
||||||
curl -sS -o /dev/null -w "" \
|
|
||||||
-X DELETE \
|
|
||||||
-H "Authorization: token ${GA_TOKEN}" \
|
|
||||||
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
|
|
||||||
|
|
||||||
# Create rule
|
|
||||||
RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
|
||||||
-X POST \
|
|
||||||
-H "Authorization: token ${GA_TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "$RULE" \
|
|
||||||
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections")
|
|
||||||
|
|
||||||
HTTP=$(echo "$RESPONSE" | tail -1)
|
|
||||||
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
||||||
|
|
||||||
if [ "$HTTP" = "201" ]; then
|
|
||||||
echo " ✅ ${NAME}"
|
|
||||||
SUCCESS=$((SUCCESS + 1))
|
|
||||||
else
|
|
||||||
echo " ❌ ${NAME} (HTTP ${HTTP}): $(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)"
|
|
||||||
FAILED=$((FAILED + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# ── Summary ───────────────────────────────────────────────
|
|
||||||
echo ""
|
|
||||||
echo "════════════════════════════════════════"
|
|
||||||
echo " ✅ Success: ${SUCCESS}"
|
|
||||||
echo " ❌ Failed: ${FAILED}"
|
|
||||||
echo " ⏭️ Skipped: ${SKIPPED}"
|
|
||||||
echo "════════════════════════════════════════"
|
|
||||||
|
|
||||||
if [ "$FAILED" -gt 0 ]; then
|
|
||||||
echo "::warning::${FAILED} rule(s) failed to apply"
|
|
||||||
fi
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
# INGROUP: mokocli.Release
|
# INGROUP: mokocli.Release
|
||||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
|
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
|
||||||
# PATH: /templates/workflows/universal/auto-release.yml.template
|
# PATH: /templates/workflows/universal/auto-release.yml.template
|
||||||
# VERSION: 05.00.00
|
# VERSION: 05.01.00
|
||||||
# BRIEF: Universal build & release � detects platform from manifest.xml
|
# BRIEF: Universal build & release � detects platform from manifest.xml
|
||||||
#
|
#
|
||||||
# +=======================================================================+
|
# +=======================================================================+
|
||||||
@@ -75,6 +75,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Setup mokocli tools
|
- name: Setup mokocli tools
|
||||||
env:
|
env:
|
||||||
@@ -173,6 +174,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Configure git for bot pushes
|
- name: Configure git for bot pushes
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: Gitea.Workflow
|
# DEFGROUP: Gitea.Workflow
|
||||||
# INGROUP: mokocli.Automation
|
# INGROUP: mokocli.Automation
|
||||||
# VERSION: 06.00.33
|
# VERSION: 01.00.00
|
||||||
# BRIEF: Auto-create feature branch when an issue is opened
|
# BRIEF: Auto-create feature branch when an issue is opened
|
||||||
|
|
||||||
name: "Universal: Issue Branch"
|
name: "Universal: Issue Branch"
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
<!--
|
|
||||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
-->
|
|
||||||
|
|
||||||
# Changelog
|
|
||||||
|
|
||||||
## [Unreleased]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- **Repository** -- initial scaffold
|
|
||||||
- **System Plugin** -- Extension class, service provider
|
|
||||||
- **SQL Schema** -- 9 tables
|
|
||||||
- **Admin Component** -- 6 views
|
|
||||||
- **Webservices Plugin** -- API routes
|
|
||||||
- **Configuration** -- plugin settings
|
|
||||||
- **Access Control** -- granular permissions
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# MokoSuiteGym
|
|
||||||
|
|
||||||
Fitness and gym membership management for Joomla 6.
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
| Field | Value |
|
|
||||||
|---|---|
|
|
||||||
| **Package** | `pkg_mokosuitegym` |
|
|
||||||
| **Layer** | 2 (requires: Client, CRM) |
|
|
||||||
| **Language** | PHP 8.3+ |
|
|
||||||
| **Branch** | develop on `dev`, merge to `main` (protected) |
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
|
|
||||||
- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, `*.min.css`/`*.min.js`
|
|
||||||
- **Attribution**: `Authored-by: Moko Consulting`
|
|
||||||
- **Changelog**: `[Unreleased]` only
|
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
DEFGROUP: Template-Joomla
|
DEFGROUP: Template-Joomla
|
||||||
INGROUP: Template-Joomla.Documentation
|
INGROUP: Template-Joomla.Documentation
|
||||||
REPO: https://github.com/mokoconsulting-tech/Template-Joomla/
|
REPO: https://github.com/mokoconsulting-tech/Template-Joomla/
|
||||||
VERSION: 06.00.33
|
VERSION: 01.01.00
|
||||||
PATH: ./CODE_OF_CONDUCT.md
|
PATH: ./CODE_OF_CONDUCT.md
|
||||||
BRIEF: Community expectations and enforcement guidelines
|
BRIEF: Community expectations and enforcement guidelines
|
||||||
NOTE: Adapted with attribution from the Contributor Covenant v2.1
|
NOTE: Adapted with attribution from the Contributor Covenant v2.1
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@
|
|||||||
DEFGROUP: mokoconsulting-tech.Template-Joomla
|
DEFGROUP: mokoconsulting-tech.Template-Joomla
|
||||||
INGROUP: MokoStandards.Governance
|
INGROUP: MokoStandards.Governance
|
||||||
REPO: https://github.com/mokoconsulting-tech/Template-Joomla
|
REPO: https://github.com/mokoconsulting-tech/Template-Joomla
|
||||||
VERSION: 06.00.33
|
VERSION: 01.01.00
|
||||||
PATH: /GOVERNANCE.md
|
PATH: /GOVERNANCE.md
|
||||||
BRIEF: Project governance rules, roles, and decision process for Template-Joomla
|
BRIEF: Project governance rules, roles, and decision process for Template-Joomla
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -1,23 +1,3 @@
|
|||||||
<!--
|
# MokoSuiteGym
|
||||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
-->
|
|
||||||
|
|
||||||
# MokoSuite Gym
|
MokoSuite Gym — fitness center memberships, class scheduling, check-ins, personal training, progress tracking for Joomla 6
|
||||||
|
|
||||||
Fitness and gym membership management for MokoSuite on Joomla 6.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
MokoSuiteGym is a **Layer 2** extension in the MokoSuite platform.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- Joomla 6.x
|
|
||||||
- PHP 8.3+
|
|
||||||
- MokoSuiteClient (Layer 0)
|
|
||||||
- MokoSuiteCRM (Layer 1)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
GNU General Public License v3.0 or later.
|
|
||||||
+4
-4
@@ -23,7 +23,7 @@ DEFGROUP: Template-Joomla
|
|||||||
INGROUP: Template-Joomla.Documentation
|
INGROUP: Template-Joomla.Documentation
|
||||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
|
REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
|
||||||
PATH: /SECURITY.md
|
PATH: /SECURITY.md
|
||||||
VERSION: 06.00.33
|
VERSION: 01.01.00
|
||||||
BRIEF: Security vulnerability reporting and handling policy
|
BRIEF: Security vulnerability reporting and handling policy
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@@ -224,10 +224,10 @@ The following are explicitly out of scope:
|
|||||||
|
|
||||||
## Metadata
|
## Metadata
|
||||||
|
|
||||||
| Field | Value |
|
| Field | Value |
|
||||||
| ------------ | ------------------------------------------------------------------------------------------------------------ |
|
| ------------ | ------------------------------------------------------------------------------------------------------------ |
|
||||||
| Document | Security Policy |
|
| Document | Security Policy |
|
||||||
| Path | /SECURITY.md |
|
| Path | /SECURITY.md |
|
||||||
| Repository | [https://github.com/mokoconsulting-tech/Template-Joomla](https://github.com/mokoconsulting-tech/Template-Joomla) |
|
| Repository | [https://github.com/mokoconsulting-tech/Template-Joomla](https://github.com/mokoconsulting-tech/Template-Joomla) |
|
||||||
| Owner | Moko Consulting |
|
| Owner | Moko Consulting |
|
||||||
| Scope | Security vulnerability handling |
|
| Scope | Security vulnerability handling |
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<access component="com_mokosuitegym">
|
|
||||||
<section name="component">
|
|
||||||
<action name="core.admin" title="JACTION_ADMIN" />
|
|
||||||
<action name="core.options" title="JACTION_OPTIONS" />
|
|
||||||
<action name="core.manage" title="JACTION_MANAGE" />
|
|
||||||
<action name="core.create" title="JACTION_CREATE" />
|
|
||||||
<action name="core.delete" title="JACTION_DELETE" />
|
|
||||||
<action name="core.edit" title="JACTION_EDIT" />
|
|
||||||
<action name="core.edit.state" title="JACTION_EDITSTATE" />
|
|
||||||
<action name="core.edit.own" title="JACTION_EDITOWN" />
|
|
||||||
<action name="gym.manage.members" title="Manage Members" />
|
|
||||||
<action name="gym.manage.classes" title="Manage Classes" />
|
|
||||||
<action name="gym.manage.trainers" title="Manage Trainers" />
|
|
||||||
<action name="gym.manage.equipment" title="Manage Equipment" />
|
|
||||||
<action name="gym.view.reports" title="View Reports" />
|
|
||||||
</section>
|
|
||||||
</access>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<config>
|
|
||||||
<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL" description="JCONFIG_PERMISSIONS_DESC">
|
|
||||||
<field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL" validate="rules" filter="rules" component="com_mokosuitegym" section="component" />
|
|
||||||
</fieldset>
|
|
||||||
</config>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
COM_MOKOSUITEGYM="MokoSuite Gym"
|
|
||||||
COM_MOKOSUITEGYM_DASHBOARD="Dashboard"
|
|
||||||
COM_MOKOSUITEGYM_MEMBERS="Members"
|
|
||||||
COM_MOKOSUITEGYM_MEMBERSHIPS="Memberships"
|
|
||||||
COM_MOKOSUITEGYM_CLASSES="Classes"
|
|
||||||
COM_MOKOSUITEGYM_TRAINERS="Trainers"
|
|
||||||
COM_MOKOSUITEGYM_EQUIPMENT="Equipment"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
COM_MOKOSUITEGYM="MokoSuite Gym"
|
|
||||||
COM_MOKOSUITEGYM_XML_DESCRIPTION="Fitness and gym membership management"
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\Extension\ComponentInterface;
|
|
||||||
use Joomla\CMS\Extension\MVCComponent;
|
|
||||||
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
|
|
||||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
|
||||||
use Joomla\CMS\Component\Router\RouterFactoryInterface;
|
|
||||||
use Joomla\DI\Container;
|
|
||||||
use Joomla\DI\ServiceProviderInterface;
|
|
||||||
|
|
||||||
return new class implements ServiceProviderInterface {
|
|
||||||
public function register(Container $container): void {
|
|
||||||
$container->set(ComponentInterface::class, function (Container $container) {
|
|
||||||
$c = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class));
|
|
||||||
$c->setMVCFactory($container->get(MVCFactoryInterface::class));
|
|
||||||
$c->setRouterFactory($container->get(RouterFactoryInterface::class));
|
|
||||||
return $c;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\Controller;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\Controller\BaseController;
|
|
||||||
|
|
||||||
class DisplayController extends BaseController
|
|
||||||
{
|
|
||||||
protected $default_view = 'gymdashboard';
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\Model;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
|
||||||
|
|
||||||
class GymDashboardModel extends BaseDatabaseModel
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\View\GymClasses;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
||||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
|
||||||
{
|
|
||||||
public function display($tpl = null): void
|
|
||||||
{
|
|
||||||
ToolbarHelper::title('MokoSuite Gym - Classes');
|
|
||||||
parent::display($tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\View\GymDashboard;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
||||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
|
||||||
{
|
|
||||||
public function display($tpl = null): void
|
|
||||||
{
|
|
||||||
ToolbarHelper::title('MokoSuite Gym - Dashboard');
|
|
||||||
parent::display($tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\View\GymEquipment;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
||||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
|
||||||
{
|
|
||||||
public function display($tpl = null): void
|
|
||||||
{
|
|
||||||
ToolbarHelper::title('MokoSuite Gym - Equipment');
|
|
||||||
parent::display($tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\View\GymMembers;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
||||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
|
||||||
{
|
|
||||||
public function display($tpl = null): void
|
|
||||||
{
|
|
||||||
ToolbarHelper::title('MokoSuite Gym - Members');
|
|
||||||
parent::display($tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\View\GymMemberships;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
||||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
|
||||||
{
|
|
||||||
public function display($tpl = null): void
|
|
||||||
{
|
|
||||||
ToolbarHelper::title('MokoSuite Gym - Memberships');
|
|
||||||
parent::display($tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Component\MokoSuiteGym\Administrator\View\GymTrainers;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
||||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
|
||||||
{
|
|
||||||
public function display($tpl = null): void
|
|
||||||
{
|
|
||||||
ToolbarHelper::title('MokoSuite Gym - Trainers');
|
|
||||||
parent::display($tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
?>
|
|
||||||
<div class="container">
|
|
||||||
<h2>Classes</h2>
|
|
||||||
<p>Coming soon.</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
?>
|
|
||||||
<div class="container">
|
|
||||||
<h2>Dashboard</h2>
|
|
||||||
<p>Coming soon.</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
?>
|
|
||||||
<div class="container">
|
|
||||||
<h2>Equipment</h2>
|
|
||||||
<p>Coming soon.</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
?>
|
|
||||||
<div class="container">
|
|
||||||
<h2>Members</h2>
|
|
||||||
<p>Coming soon.</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
?>
|
|
||||||
<div class="container">
|
|
||||||
<h2>Memberships</h2>
|
|
||||||
<p>Coming soon.</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
?>
|
|
||||||
<div class="container">
|
|
||||||
<h2>Trainers</h2>
|
|
||||||
<p>Coming soon.</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<extension type="component" method="upgrade">
|
|
||||||
<name>MokoSuite Gym</name>
|
|
||||||
<author>Moko Consulting</author>
|
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
|
||||||
<creationDate>2026-06-27</creationDate>
|
|
||||||
<copyright>Copyright (C) 2026 Moko Consulting.</copyright>
|
|
||||||
<license>GPL-3.0-or-later</license>
|
|
||||||
<version>06.00.33</version>
|
|
||||||
<description>Fitness and gym membership management</description>
|
|
||||||
<namespace path="src">Moko\Component\MokoSuiteGym</namespace>
|
|
||||||
<administration>
|
|
||||||
<files folder="admin">
|
|
||||||
<filename>access.xml</filename>
|
|
||||||
<filename>config.xml</filename>
|
|
||||||
<folder>language</folder>
|
|
||||||
<folder>services</folder>
|
|
||||||
<folder>src</folder>
|
|
||||||
<folder>tmpl</folder>
|
|
||||||
</files>
|
|
||||||
<languages folder="admin/language">
|
|
||||||
<language tag="en-GB">en-GB/com_mokosuitegym.ini</language>
|
|
||||||
<language tag="en-GB">en-GB/com_mokosuitegym.sys.ini</language>
|
|
||||||
</languages>
|
|
||||||
<menu>COM_MOKOSUITEGYM</menu>
|
|
||||||
<submenu>
|
|
||||||
<menu link="option=com_mokosuitegym&view=gymdashboard">COM_MOKOSUITEGYM_DASHBOARD</menu>
|
|
||||||
<menu link="option=com_mokosuitegym&view=gymmembers">COM_MOKOSUITEGYM_MEMBERS</menu>
|
|
||||||
<menu link="option=com_mokosuitegym&view=gymmemberships">COM_MOKOSUITEGYM_MEMBERSHIPS</menu>
|
|
||||||
<menu link="option=com_mokosuitegym&view=gymclasses">COM_MOKOSUITEGYM_CLASSES</menu>
|
|
||||||
<menu link="option=com_mokosuitegym&view=gymtrainers">COM_MOKOSUITEGYM_TRAINERS</menu>
|
|
||||||
<menu link="option=com_mokosuitegym&view=gymequipment">COM_MOKOSUITEGYM_EQUIPMENT</menu>
|
|
||||||
</submenu>
|
|
||||||
</administration>
|
|
||||||
</extension>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
PLG_SYSTEM_MOKOSUITEGYM="System - MokoSuite Gym"
|
|
||||||
PLG_SYSTEM_MOKOSUITEGYM_DESC="Fitness and gym membership management helpers and schema"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
PLG_SYSTEM_MOKOSUITEGYM="System - MokoSuite Gym"
|
|
||||||
PLG_SYSTEM_MOKOSUITEGYM_DESC="Fitness and gym membership management helpers and schema"
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<extension type="plugin" group="system" method="upgrade">
|
|
||||||
<name>System - MokoSuite Gym</name>
|
|
||||||
<element>mokosuitegym</element>
|
|
||||||
<author>Moko Consulting</author>
|
|
||||||
<creationDate>2026-06-27</creationDate>
|
|
||||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
|
||||||
<license>GPL-3.0-or-later</license>
|
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
|
||||||
<version>06.00.33</version>
|
|
||||||
<php_minimum>8.3</php_minimum>
|
|
||||||
<description>PLG_SYSTEM_MOKOSUITEGYM_DESC</description>
|
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteGym</namespace>
|
|
||||||
<files><folder>src</folder><folder>services</folder><folder>language</folder><folder>sql</folder></files>
|
|
||||||
<languages folder="language">
|
|
||||||
<language tag="en-GB">en-GB/plg_system_mokosuitegym.ini</language>
|
|
||||||
<language tag="en-GB">en-GB/plg_system_mokosuitegym.sys.ini</language>
|
|
||||||
</languages>
|
|
||||||
<install><sql><file driver="mysql" charset="utf8">sql/install.mysql.sql</file></sql></install>
|
|
||||||
<uninstall><sql><file driver="mysql" charset="utf8">sql/uninstall.mysql.sql</file></sql></uninstall>
|
|
||||||
<config><fields name="params"><fieldset name="basic" label="Gym Defaults"><field name="default_currency" type="text" default="USD" label="Default Currency" /><field name="timezone" type="timezone" default="America/New_York" label="Default Timezone" /></fieldset><fieldset name="membership" label="Membership"><field name="trial_days" type="number" default="7" label="Trial Period (days)" /><field name="grace_period_days" type="number" default="5" label="Grace Period (days)" /><field name="auto_renew" type="radio" default="1" label="Auto-Renew Default" class="btn-group btn-group-yesno"><option value="1">JYES</option><option value="0">JNO</option></field></fieldset><fieldset name="notifications" label="Notifications"><field name="expiry_warning_days" type="number" default="14" label="Expiry Warning (days before)" /></fieldset><fieldset name="display" label="Display"><field name="dashboard_default_view" type="list" default="overview" label="Default Dashboard View"><option value="overview">Overview</option><option value="calendar">Calendar</option><option value="check_ins">Check-Ins</option></field></fieldset></fields></config>
|
|
||||||
</extension>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\Extension\PluginInterface;
|
|
||||||
use Joomla\CMS\Plugin\PluginHelper;
|
|
||||||
use Joomla\DI\Container;
|
|
||||||
use Joomla\DI\ServiceProviderInterface;
|
|
||||||
use Joomla\Event\DispatcherInterface;
|
|
||||||
use Moko\Plugin\System\MokoSuiteGym\Extension\Gym;
|
|
||||||
|
|
||||||
return new class implements ServiceProviderInterface {
|
|
||||||
public function register(Container $container): void {
|
|
||||||
$container->set(PluginInterface::class, function (Container $container) {
|
|
||||||
$dispatcher = $container->get(DispatcherInterface::class);
|
|
||||||
$plugin = new Gym($dispatcher, (array) PluginHelper::getPlugin('system', 'mokosuitegym'));
|
|
||||||
$plugin->setApplication(\Joomla\CMS\Factory::getApplication());
|
|
||||||
return $plugin;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
--
|
|
||||||
-- MokoSuite Gym Tables
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_members` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`contact_id` INT DEFAULT NULL,
|
|
||||||
`user_id` INT DEFAULT NULL,
|
|
||||||
`member_number` VARCHAR(20) NOT NULL DEFAULT '',
|
|
||||||
`first_name` VARCHAR(100) NOT NULL,
|
|
||||||
`last_name` VARCHAR(100) NOT NULL,
|
|
||||||
`email` VARCHAR(255) NOT NULL DEFAULT '',
|
|
||||||
`phone` VARCHAR(50) NOT NULL DEFAULT '',
|
|
||||||
`date_of_birth` DATE DEFAULT NULL,
|
|
||||||
`gender` ENUM('male','female','other','prefer_not_to_say') DEFAULT NULL,
|
|
||||||
`emergency_contact` VARCHAR(255) NOT NULL DEFAULT '',
|
|
||||||
`emergency_phone` VARCHAR(50) NOT NULL DEFAULT '',
|
|
||||||
`health_notes` TEXT,
|
|
||||||
`photo` VARCHAR(500) NOT NULL DEFAULT '',
|
|
||||||
`status` ENUM('active','inactive','suspended','cancelled') NOT NULL DEFAULT 'active',
|
|
||||||
`joined_date` DATE NOT NULL,
|
|
||||||
`notes` TEXT,
|
|
||||||
`published` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
`created_by` INT NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_contact` (`contact_id`),
|
|
||||||
KEY `idx_user` (`user_id`),
|
|
||||||
KEY `idx_status` (`status`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_membership_plans` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` VARCHAR(255) NOT NULL,
|
|
||||||
`description` TEXT,
|
|
||||||
`duration_months` TINYINT UNSIGNED NOT NULL DEFAULT 1,
|
|
||||||
`price` DECIMAL(10,2) NOT NULL,
|
|
||||||
`currency` VARCHAR(3) NOT NULL DEFAULT 'USD',
|
|
||||||
`signup_fee` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
|
||||||
`billing_cycle` ENUM('monthly','quarterly','semi_annual','annual','one_time') NOT NULL DEFAULT 'monthly',
|
|
||||||
`max_classes_per_month` INT DEFAULT NULL,
|
|
||||||
`guest_passes_per_month` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
`features_json` JSON DEFAULT NULL,
|
|
||||||
`published` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`ordering` INT NOT NULL DEFAULT 0,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_memberships` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`member_id` INT UNSIGNED NOT NULL,
|
|
||||||
`plan_id` INT UNSIGNED NOT NULL,
|
|
||||||
`status` ENUM('trial','active','frozen','expired','cancelled') NOT NULL DEFAULT 'active',
|
|
||||||
`start_date` DATE NOT NULL,
|
|
||||||
`end_date` DATE DEFAULT NULL,
|
|
||||||
`renewal_date` DATE DEFAULT NULL,
|
|
||||||
`auto_renew` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`amount_paid` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
|
||||||
`payment_method` ENUM('cash','card','bank_transfer','online') NOT NULL DEFAULT 'card',
|
|
||||||
`frozen_at` DATE DEFAULT NULL,
|
|
||||||
`frozen_until` DATE DEFAULT NULL,
|
|
||||||
`cancellation_reason` VARCHAR(500) NOT NULL DEFAULT '',
|
|
||||||
`notes` TEXT,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_member` (`member_id`),
|
|
||||||
KEY `idx_plan` (`plan_id`),
|
|
||||||
KEY `idx_status` (`status`),
|
|
||||||
KEY `idx_dates` (`start_date`, `end_date`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_classes` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` VARCHAR(255) NOT NULL,
|
|
||||||
`description` TEXT,
|
|
||||||
`category` ENUM('cardio','strength','flexibility','martial_arts','dance','cycling','swimming','yoga','pilates','group_fitness','other') NOT NULL DEFAULT 'group_fitness',
|
|
||||||
`difficulty` ENUM('beginner','intermediate','advanced','all_levels') NOT NULL DEFAULT 'all_levels',
|
|
||||||
`duration_minutes` SMALLINT UNSIGNED NOT NULL DEFAULT 60,
|
|
||||||
`max_capacity` SMALLINT UNSIGNED NOT NULL DEFAULT 20,
|
|
||||||
`requires_booking` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`color` VARCHAR(7) NOT NULL DEFAULT '#3788d8',
|
|
||||||
`photo` VARCHAR(500) NOT NULL DEFAULT '',
|
|
||||||
`published` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`ordering` INT NOT NULL DEFAULT 0,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_category` (`category`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_class_schedules` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`class_id` INT UNSIGNED NOT NULL,
|
|
||||||
`trainer_id` INT UNSIGNED DEFAULT NULL,
|
|
||||||
`day_of_week` TINYINT UNSIGNED NOT NULL,
|
|
||||||
`start_time` TIME NOT NULL,
|
|
||||||
`end_time` TIME NOT NULL,
|
|
||||||
`room` VARCHAR(100) NOT NULL DEFAULT '',
|
|
||||||
`effective_from` DATE DEFAULT NULL,
|
|
||||||
`effective_until` DATE DEFAULT NULL,
|
|
||||||
`published` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_class` (`class_id`),
|
|
||||||
KEY `idx_trainer` (`trainer_id`),
|
|
||||||
KEY `idx_day` (`day_of_week`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_class_enrollments` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`schedule_id` INT UNSIGNED NOT NULL,
|
|
||||||
`member_id` INT UNSIGNED NOT NULL,
|
|
||||||
`enrollment_date` DATE NOT NULL,
|
|
||||||
`status` ENUM('enrolled','attended','cancelled','no_show') NOT NULL DEFAULT 'enrolled',
|
|
||||||
`cancelled_at` DATETIME DEFAULT NULL,
|
|
||||||
`notes` TEXT,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_schedule` (`schedule_id`),
|
|
||||||
KEY `idx_member` (`member_id`),
|
|
||||||
KEY `idx_date` (`enrollment_date`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_trainers` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`contact_id` INT DEFAULT NULL,
|
|
||||||
`user_id` INT DEFAULT NULL,
|
|
||||||
`display_name` VARCHAR(255) NOT NULL,
|
|
||||||
`title` VARCHAR(100) NOT NULL DEFAULT '',
|
|
||||||
`specialties` VARCHAR(500) NOT NULL DEFAULT '',
|
|
||||||
`certifications` TEXT,
|
|
||||||
`bio` TEXT,
|
|
||||||
`email` VARCHAR(255) NOT NULL DEFAULT '',
|
|
||||||
`phone` VARCHAR(50) NOT NULL DEFAULT '',
|
|
||||||
`photo` VARCHAR(500) NOT NULL DEFAULT '',
|
|
||||||
`hourly_rate` DECIMAL(10,2) DEFAULT NULL,
|
|
||||||
`published` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`ordering` INT NOT NULL DEFAULT 0,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_contact` (`contact_id`),
|
|
||||||
KEY `idx_user` (`user_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_equipment` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` VARCHAR(255) NOT NULL,
|
|
||||||
`category` ENUM('cardio','strength','free_weights','machines','flexibility','functional','other') NOT NULL DEFAULT 'machines',
|
|
||||||
`brand` VARCHAR(100) NOT NULL DEFAULT '',
|
|
||||||
`model` VARCHAR(100) NOT NULL DEFAULT '',
|
|
||||||
`serial_number` VARCHAR(100) NOT NULL DEFAULT '',
|
|
||||||
`location` VARCHAR(100) NOT NULL DEFAULT '',
|
|
||||||
`purchase_date` DATE DEFAULT NULL,
|
|
||||||
`warranty_until` DATE DEFAULT NULL,
|
|
||||||
`status` ENUM('active','maintenance','out_of_order','retired') NOT NULL DEFAULT 'active',
|
|
||||||
`last_maintenance` DATE DEFAULT NULL,
|
|
||||||
`next_maintenance` DATE DEFAULT NULL,
|
|
||||||
`maintenance_notes` TEXT,
|
|
||||||
`photo` VARCHAR(500) NOT NULL DEFAULT '',
|
|
||||||
`published` TINYINT NOT NULL DEFAULT 1,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_category` (`category`),
|
|
||||||
KEY `idx_status` (`status`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `#__mokosuitegym_check_ins` (
|
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`member_id` INT UNSIGNED NOT NULL,
|
|
||||||
`check_in_time` DATETIME NOT NULL,
|
|
||||||
`check_out_time` DATETIME DEFAULT NULL,
|
|
||||||
`check_in_method` ENUM('scan','manual','app','kiosk') NOT NULL DEFAULT 'scan',
|
|
||||||
`notes` TEXT,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_member` (`member_id`),
|
|
||||||
KEY `idx_time` (`check_in_time`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
--
|
|
||||||
-- MokoSuite Gym — Uninstall
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_check_ins`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_equipment`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_trainers`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_class_enrollments`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_class_schedules`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_classes`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_memberships`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_membership_plans`;
|
|
||||||
DROP TABLE IF EXISTS `#__mokosuitegym_members`;
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Plugin\System\MokoSuiteGym\Extension;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\Plugin\CMSPlugin;
|
|
||||||
use Joomla\Event\SubscriberInterface;
|
|
||||||
|
|
||||||
class Gym extends CMSPlugin implements SubscriberInterface
|
|
||||||
{
|
|
||||||
public static function getSubscribedEvents(): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<extension type="plugin" group="webservices" method="upgrade">
|
|
||||||
<name>Web Services - MokoSuite Gym</name>
|
|
||||||
<element>mokosuitegym</element>
|
|
||||||
<author>Moko Consulting</author>
|
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
|
||||||
<creationDate>2026-06-27</creationDate>
|
|
||||||
<copyright>Copyright (C) 2026 Moko Consulting.</copyright>
|
|
||||||
<version>06.00.33</version>
|
|
||||||
<license>GPL-3.0-or-later</license>
|
|
||||||
<description>REST API routes for MokoSuite Gym operations</description>
|
|
||||||
<namespace path="src">Moko\Plugin\WebServices\MokoSuiteGym</namespace>
|
|
||||||
<files><folder>src</folder><folder>services</folder></files>
|
|
||||||
</extension>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\Extension\PluginInterface;
|
|
||||||
use Joomla\CMS\Plugin\PluginHelper;
|
|
||||||
use Joomla\DI\Container;
|
|
||||||
use Joomla\DI\ServiceProviderInterface;
|
|
||||||
use Joomla\Event\DispatcherInterface;
|
|
||||||
use Moko\Plugin\WebServices\MokoSuiteGym\Extension\MokoSuiteGym;
|
|
||||||
|
|
||||||
return new class implements ServiceProviderInterface {
|
|
||||||
public function register(Container $container): void {
|
|
||||||
$container->set(PluginInterface::class, function (Container $container) {
|
|
||||||
$dispatcher = $container->get(DispatcherInterface::class);
|
|
||||||
return new MokoSuiteGym($dispatcher, (array) PluginHelper::getPlugin('webservices', 'mokosuitegym'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* Authored-by: Moko Consulting
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Moko\Plugin\WebServices\MokoSuiteGym\Extension;
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\Plugin\CMSPlugin;
|
|
||||||
use Joomla\CMS\Router\ApiRouter;
|
|
||||||
use Joomla\Event\SubscriberInterface;
|
|
||||||
|
|
||||||
class MokoSuiteGym extends CMSPlugin implements SubscriberInterface
|
|
||||||
{
|
|
||||||
public static function getSubscribedEvents(): array
|
|
||||||
{
|
|
||||||
return ['onBeforeApiRoute' => 'onBeforeApiRoute'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onBeforeApiRoute($event): void
|
|
||||||
{
|
|
||||||
$router = $event->getArgument('router');
|
|
||||||
foreach (['members', 'memberships', 'plans', 'classes', 'schedules', 'trainers', 'equipment', 'check-ins'] as $route) {
|
|
||||||
$router->createCRUDRoutes("v1/gym/{$route}", $route, ['component' => 'com_mokosuitegym']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<extension type="package" method="upgrade">
|
|
||||||
<name>Package - MokoSuite Gym</name>
|
|
||||||
<packagename>mokosuitegym</packagename>
|
|
||||||
<version>06.00.33</version>
|
|
||||||
<creationDate>2026-06-27</creationDate>
|
|
||||||
<author>Moko Consulting</author>
|
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
|
||||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
|
||||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
|
||||||
<description>Fitness and gym membership management</description>
|
|
||||||
<php_minimum>8.3</php_minimum>
|
|
||||||
<dlid prefix="dlid=" suffix=""/>
|
|
||||||
<blockChildUninstall>true</blockChildUninstall>
|
|
||||||
<scriptfile>script.php</scriptfile>
|
|
||||||
<files folder="packages">
|
|
||||||
<file type="plugin" id="plg_system_mokosuitegym" group="system">plg_system_mokosuitegym.zip</file>
|
|
||||||
<file type="component" id="com_mokosuitegym">com_mokosuitegym.zip</file>
|
|
||||||
<file type="plugin" id="plg_webservices_mokosuitegym" group="webservices">plg_webservices_mokosuitegym.zip</file>
|
|
||||||
</files>
|
|
||||||
<updateservers>
|
|
||||||
<server type="extension" priority="1" name="Package - MokoSuite Gym">https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteGym/updates.xml</server>
|
|
||||||
</updateservers>
|
|
||||||
</extension>
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @package MokoSuiteGym
|
|
||||||
* @subpackage pkg_mokosuitegym
|
|
||||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
|
||||||
* @license GNU General Public License version 3 or later; see LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
|
||||||
|
|
||||||
use Joomla\CMS\Factory;
|
|
||||||
use Joomla\CMS\Installer\InstallerAdapter;
|
|
||||||
use Joomla\CMS\Log\Log;
|
|
||||||
|
|
||||||
class Pkg_MokoSuiteGymInstallerScript
|
|
||||||
{
|
|
||||||
public function postflight(string $type, InstallerAdapter $adapter): void
|
|
||||||
{
|
|
||||||
$this->warnMissingLicenseKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function warnMissingLicenseKey(): void
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$db = Factory::getDbo();
|
|
||||||
$app = Factory::getApplication();
|
|
||||||
|
|
||||||
$query = $db->getQuery(true)
|
|
||||||
->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query')])
|
|
||||||
->from($db->quoteName('#__update_sites'))
|
|
||||||
->where('(' . $db->quoteName('name') . ' LIKE ' . $db->quote('%MokoSuiteGym%')
|
|
||||||
. ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoSuiteGym%') . ')')
|
|
||||||
->setLimit(1);
|
|
||||||
$db->setQuery($query);
|
|
||||||
$site = $db->loadObject();
|
|
||||||
|
|
||||||
if ($site)
|
|
||||||
{
|
|
||||||
$extraQuery = (string) ($site->extra_query ?? '');
|
|
||||||
|
|
||||||
if (!empty($extraQuery) && strpos($extraQuery, 'dlid=') !== false)
|
|
||||||
{
|
|
||||||
parse_str($extraQuery, $parsed);
|
|
||||||
|
|
||||||
if (!empty($parsed['dlid']))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$editUrl = 'index.php?option=com_installer&task=updatesite.edit&update_site_id=' . (int) $site->update_site_id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$editUrl = 'index.php?option=com_installer&view=updatesites';
|
|
||||||
}
|
|
||||||
|
|
||||||
$app->enqueueMessage(
|
|
||||||
'<strong>Moko Consulting License Key Required</strong> — '
|
|
||||||
. 'No download key is configured. Updates will not be available until a valid license key is entered. '
|
|
||||||
. '<a href="' . $editUrl . '" class="btn btn-sm btn-warning ms-2">Enter License Key</a>',
|
|
||||||
'warning'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (\Throwable $e)
|
|
||||||
{
|
|
||||||
// Silent — avoid breaking install if update_sites query fails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user