diff --git a/ai/cs/@home.texy b/ai/cs/@home.texy new file mode 100644 index 0000000000..e2385cdf80 --- /dev/null +++ b/ai/cs/@home.texy @@ -0,0 +1,11 @@ +Nette AI +******** + +- [Introduction |guide] +- [Getting Started |getting-started] +- [MCP Inspector |mcp-inspector] +- [Claude Code |claude-code] +- [Tips & Best Practices |tips] + +{{maintitle: Nette AI – Vibe Coding with Nette Framework}} +{{description: Build Nette applications with AI assistance. MCP Inspector gives any AI tool deep knowledge of your application's DI container, database, routing, and errors. No hallucinations, just clean code.}} diff --git a/ai/cs/@meta.texy b/ai/cs/@meta.texy new file mode 100644 index 0000000000..e06cc9886c --- /dev/null +++ b/ai/cs/@meta.texy @@ -0,0 +1 @@ +{{sitename: Nette AI}} diff --git a/ai/en/@home.texy b/ai/en/@home.texy new file mode 100644 index 0000000000..e2385cdf80 --- /dev/null +++ b/ai/en/@home.texy @@ -0,0 +1,11 @@ +Nette AI +******** + +- [Introduction |guide] +- [Getting Started |getting-started] +- [MCP Inspector |mcp-inspector] +- [Claude Code |claude-code] +- [Tips & Best Practices |tips] + +{{maintitle: Nette AI – Vibe Coding with Nette Framework}} +{{description: Build Nette applications with AI assistance. MCP Inspector gives any AI tool deep knowledge of your application's DI container, database, routing, and errors. No hallucinations, just clean code.}} diff --git a/ai/en/@left-menu.texy b/ai/en/@left-menu.texy new file mode 100644 index 0000000000..54132f474a --- /dev/null +++ b/ai/en/@left-menu.texy @@ -0,0 +1,5 @@ +- [Introduction |guide] +- [Getting Started |getting-started] +- [MCP Inspector |mcp-inspector] +- [Claude Code |claude-code] +- [Tips & Best Practices |tips] diff --git a/ai/en/@meta.texy b/ai/en/@meta.texy new file mode 100644 index 0000000000..e06cc9886c --- /dev/null +++ b/ai/en/@meta.texy @@ -0,0 +1 @@ +{{sitename: Nette AI}} diff --git a/ai/en/claude-code.texy b/ai/en/claude-code.texy new file mode 100644 index 0000000000..6d9e63e82e --- /dev/null +++ b/ai/en/claude-code.texy @@ -0,0 +1,269 @@ +Claude Code Plugin +****************** + +
+ +The Nette plugin gives Claude deep knowledge of the framework. Instead of generic PHP advice, you get recommendations that follow Nette conventions – from presenters and forms to Latte templates and database queries. + +The plugin includes: +- A **broad set of skills** covering all major areas of Nette development +- **Automatic validation** that catches errors in Latte, NEON and JavaScript files +- **MCP Inspector integration** for real-time application introspection + +
+ + +Installation +============ + +If you haven't installed Claude Code yet, see the [complete setup guide |getting-started]. Once Claude Code is running, install the Nette plugin: + +```shell +/plugin marketplace add nette/claude-code +/plugin install nette@nette +``` + + +How Skills Work +=============== + +You don't need to activate skills manually. They turn on automatically based on what you're talking about. + +- Ask about "presenter structure" → the `nette-architecture` skill activates +- Ask about "form validation" → the `nette-forms` skill activates +- Ask about "Latte filters" → the `latte-templates` skill activates +- Ask about a "BlueScreen error" → the `tracy-debugging` skill activates + +This means you get relevant, context-aware help without having to think about which skill you need. + + +Available Skills +================ + +Here's what each skill covers: + + +nette-architecture +------------------ + +When you're designing your application structure, this skill guides you through: + +- **Directory organization** – Where to put presenters, services, entities, and components +- **Module design** – How to split your application into logical modules (Admin, Front, Api) +- **Presenter patterns** – When to use base presenters, how to handle authentication +- **Evolution strategy** – Start minimal, grow organically, refactor when needed + +The key principle: Don't over-engineer. Create subdirectories when you have 5+ related files, not before. + + +nette-configuration +------------------- + +Everything about the DI container and NEON configuration: + +- **Service registration** – How to define services in `services.neon` +- **Autowiring** – When it works automatically and when you need explicit configuration +- **Parameters** – How to use configuration parameters across your application +- **Extensions** – Working with DI extensions from Nette and third parties + + +nette-database +-------------- + +Covers both the raw SQL approach and the Database Explorer: + +- **Database Explorer** – Using `Selection` for queries, `ActiveRow` for entities +- **Entity conventions** – The `Row` suffix pattern, type hints with `@property-read` +- **Relationships** – Navigating foreign keys with colon notation +- **When to use what** – Explorer for CRUD, raw SQL for complex analytics + +Example: Claude knows that `->where('category.slug', $slug)` automatically joins the category table. + + +nette-forms +----------- + +Creating and handling forms the Nette way: + +- **Controls** – All built-in controls from text inputs to file uploads +- **Validation** – Built-in rules, custom validators, conditional validation +- **Rendering** – Manual rendering, Bootstrap integration, custom renderers +- **Patterns** – Create/edit forms, form components, AJAX submissions + + +nette-schema +------------ + +Data validation and normalization with the Schema component: + +- **Expect class** – Building validation schemas for arrays and objects +- **Configuration schemas** – Validating NEON configuration in DI extensions +- **Type coercion** – Automatic conversion of strings to integers, dates, etc. +- **Custom validators** – Adding your own validation rules + +Example: Claude knows how to create schemas like: + +```php +$schema = Expect::structure([ + 'name' => Expect::string()->required(), + 'age' => Expect::int()->min(0)->max(120), + 'email' => Expect::string(), + 'roles' => Expect::listOf('string')->default([]), +]); +``` + + +nette-tester +------------ + +Writing tests with Nette Tester: + +- **Test structure** – The `.phpt` format, `@testCase` annotation, file organization +- **Assertions** – All `Assert::*` methods: `same()`, `equal()`, `exception()`, `match()`, and more +- **Fixtures** – Setting up test data, mocking dependencies, database transactions +- **Running tests** – Command-line options, parallel execution, code coverage + +Example: Claude can generate proper test files: + +```php +/** @testCase */ +class UserServiceTest extends TestCase +{ + public function testCreateUser(): void + { + $service = new UserService($this->mockDatabase()); + $user = $service->create(['name' => 'John']); + Assert::same('John', $user->name); + } +} +``` + + +tracy-debugging +--------------- + +Working with the Tracy debugger: + +- **BlueScreen** – Reading exception details, stack traces, source highlights +- **Tracy Bar** – Interpreting embedded SQL query logs, timing, and memory usage at the bottom of every page +- **`dump()` workflow** – Inserting `dump($variable)` calls and reading the output back through curl or the browser +- **Production logs** – Investigating `log/exception-*.html` snapshots and `log/error.log` +- **Chrome MCP integration** – Pulling Tracy errors out of the browser console with `list_console_messages()` instead of taking screenshots + +Especially useful for 500 errors, blank pages, N+1 query issues, or whenever Claude fetches a local PHP URL and needs to interpret what came back. + + +nette-utils +----------- + +The utility classes that make PHP development easier: + +- **Arrays** – `Nette\Utils\Arrays` with `get()`, `getRef()`, `map()`, `flatten()`, and more +- **Strings** – Unicode-safe operations: `webalize()`, `truncate()`, `contains()`, `startsWith()` +- **Finder** – File system traversal with filtering by name, size, date +- **Image** – Resize, crop, sharpen with automatic format detection +- **Json** – Safe JSON encoding/decoding with proper error handling +- **Validators** – Email, URL, numeric validation helpers +- **DateTime** – Immutable date/time with Czech locale support + + +frontend-development +-------------------- + +Integrating frontend tools with Nette: + +- **Vite** – Setting up Vite for modern JavaScript/TypeScript development, HMR configuration +- **Nette Assets** – Using the asset system for cache-busted URLs in production +- **Tailwind CSS** – Configuration for Tailwind with Latte templates, purging unused styles +- **ESLint & Prettier** – Code quality tools integration +- **Build scripts** – npm/package.json scripts for development and production builds + +Claude can help configure `vite.config.js` to work with Nette's directory structure and generate proper asset references in Latte templates. + + +latte-templates +--------------- + +Everything about the Latte templating engine: + +- **Syntax** – Tags, filters, blocks, and inheritance +- **Security** – Auto-escaping, content-aware output +- **Custom filters** – Creating and registering your own filters +- **Template classes** – Using typed templates for better IDE support + + +neon-format +----------- + +The NEON configuration format: + +- **Syntax** – Mappings, sequences, entities, and multiline strings +- **Common patterns** – Service definitions, parameter references +- **Debugging** – Finding and fixing syntax errors + + +Automatic Validation +==================== + +One of the most useful features is automatic validation. After every file edit, the plugin checks for errors: + +| What | How It Works | +|------|--------------| +| **Latte templates** | Runs `latte-lint` to check syntax after every `.latte` edit | +| **NEON files** | Validates NEON syntax after every `.neon` edit | +| **JavaScript / TypeScript** | Runs `eslint --fix` after every `.js`, `.ts`, `.mjs` or `.mts` edit (only if the project has an ESLint config) | + +If there's a syntax error in your Latte template, Claude knows about it immediately and can suggest a fix. No more discovering errors in the browser. + + +Plugin for Framework Contributors +================================= + +If you're contributing to Nette itself, there's an additional plugin with coding standards: + +```shell +/plugin install nette-dev@nette +``` + +| Skill | What It Covers | +|-------|----------------| +| `php-coding-standards` | Nette's PHP coding style – indentation, naming, structure | +| `php-doc` | PHPDoc conventions – when to document, what format to use | +| `commit-messages` | How to write commit messages for Nette repositories | +| `phpstan-analysis` | How to resolve PHPStan errors – prefer refactoring over phpDoc annotations over ignoring – plus common Nette patterns and baseline management | + + +Automatic PHP Style Fixing +========================== + +For automatic code style fixing after every PHP file edit, install the optional php-fixer plugin: + +```shell +/plugin install php-fixer@nette +/install-php-fixer +``` + +The second command installs `nette/coding-standard` globally. After that, every PHP file you edit will be automatically formatted according to Nette coding standards. + +The plugin also comes with the `php-auto-fixer` skill, which teaches Claude about one subtle pitfall: the fixer removes unused `use` statements, so a `use` added in a separate edit before the code that references it gets stripped. Claude knows to add imports together with the code that uses them. + + +MCP Inspector Integration +========================= + +The plugin works even better with [MCP Inspector |mcp-inspector] – a tool that lets Claude see your actual application state. With MCP Inspector, Claude can: + +- Query your real database schema instead of guessing +- List your registered DI services and their configuration +- Read Tracy error logs for debugging +- Match URLs to presenters using your actual routes + +Install it with a single command: + +```shell +/install-mcp-inspector +``` + +Then restart Claude Code. See the [MCP Inspector documentation |mcp-inspector] for all 20 available tools. + +{{composer: nette/claude-code}} diff --git a/ai/en/getting-started.texy b/ai/en/getting-started.texy new file mode 100644 index 0000000000..fa20b5da1f --- /dev/null +++ b/ai/en/getting-started.texy @@ -0,0 +1,260 @@ +Getting Started +*************** + +
+ +Ready to try [vibe coding |guide] with Nette? This guide walks you through the complete setup: + +- Choosing and installing an AI tool +- Setting up MCP Inspector so AI can see your application +- Making your first AI-assisted changes + +The whole process takes about 10 minutes. Let's get started! + +
+ + +Choosing Your AI Tool +===================== + +Nette AI tools work with any MCP-compatible AI assistant. We recommend **Claude Code** for the best experience – it has a dedicated Nette plugin with deep framework knowledge and automatic code validation. + +Other options include **Cursor**, **VS Code with Continue**, and other MCP-compatible tools. See [Other AI Tools |#other-ai-tools] at the end of this guide. + + +What You'll Need +================ + +Before we begin, make sure you have: + +- **A Nette project** – existing or new (`composer create-project nette/web-project`) +- **PHP 8.2+** – required for MCP Inspector +- **An AI tool** – we'll install Claude Code below (Claude Pro costs $20/month) + + +Installation on macOS and Linux +=============================== + +```shell +curl -fsSL https://claude.ai/install.sh | bash +``` + +On macOS, you can alternatively use Homebrew: + +```shell +brew install --cask claude-code +``` + +After installation, skip to [Starting Claude Code |#starting-claude-code]. + + +Installation on Windows via WSL +=============================== + +Claude Code requires a Unix environment. On Windows, use WSL: + +```shell +wsl --install +``` + +This installs Ubuntu. **Restart your computer** after installation. + +After restart, launch Ubuntu: + +```shell +ubuntu +``` + +First launch will ask for a username and password – you'll need it for `sudo` later. + +Installing Claude Code in WSL in the Ubuntu terminal: + +```shell +curl -fsSL https://claude.ai/install.sh | bash +``` + +Your Windows drives are mounted under `/mnt/`: +- `C:\Users\Jan\Projects` → `/mnt/c/Users/Jan/Projects` +- `D:\Work` → `/mnt/d/Work` + +From Windows, access Linux files via `\\wsl$\Ubuntu\home\username` in Explorer. + + +Starting Claude Code +==================== + +Great, you have Claude Code installed! Let's start it up. + +Navigate to your project directory: + +```shell +# Windows (WSL) +cd /mnt/c/Users/Jan/Projects/my-app + +# macOS/Linux +cd ~/projects/my-app +``` + +Start Claude Code: + +```shell +claude +``` + +The first time you run it, Claude Code will ask you to authenticate. It will open a browser window where you can log in to your Anthropic account. After successful authentication, you'll see the `claude>` prompt and you're ready to go. + +You can also use Claude Code "on the web":https://claude.ai/code or via the "desktop app":https://claude.com/download, but local installation provides the best experience with direct file access. + + +Adding the Nette Plugin +======================= + +Now let's give Claude deep knowledge of Nette. First, add the Nette marketplace and enable auto-updating: + +```shell +/plugin marketplace add nette/claude-code +``` + +Then install the plugin: + +```shell +/plugin install nette@nette +``` + +That's it! The plugin is now active. It includes 10 specialized skills that automatically activate based on what you're working on. When you ask about forms, it knows about Nette Forms. When you ask about templates, it knows about Latte. + + +Setting Up MCP Inspector +======================== + +The final piece is MCP Inspector, which lets Claude see your actual application – your services, database schema, routes, and error logs. + +The easiest way to install it is through Claude Code: + +```shell +/install-mcp-inspector +``` + +This command adds the `nette/mcp-inspector` package to your project and configures everything automatically. + +Alternatively, you can install it manually with Composer: + +```shell +composer require nette/mcp-inspector +``` + +**Important:** After installing MCP Inspector, restart Claude Code (type `/exit` and run `claude` again) to activate the connection. + + +Testing Your Setup +================== + +Let's verify everything works. Try these prompts: + + +Test the Plugin Knowledge +------------------------- + +Type: + +``` +What's the recommended directory structure for a Nette application? +``` + +Claude should respond with detailed information about presenters, models, templates, and configuration – knowledge that comes from the `nette-architecture` skill. + + +Test MCP Inspector +------------------ + +Type: + +``` +What services do I have registered in my DI container? +``` + +If MCP Inspector is working, Claude will call `di_get_services()` and show you the actual services from your application. If you see a list of your real services, congratulations – everything is set up correctly! + + +Test Database Introspection +--------------------------- + +If your application uses a database, try: + +``` +What tables do I have? Show me the columns in the user table. +``` + + +Your First Real Task +==================== + +Now that everything is set up, let's do something useful. Try this prompt: + +``` +I need a simple ArticlePresenter with list and detail actions. +Generate the presenter, templates, and tell me what routes I need. +``` + +Watch as Claude generates a complete, working presenter following Nette conventions. It will: +- Create the presenter class with proper type hints +- Generate Latte templates for both actions +- Suggest the appropriate route configuration + +If you have MCP Inspector set up and an `article` table in your database, try: + +``` +Look at my article table and generate an ArticleRow entity with proper type hints. +``` + + +Other AI Tools +============== + +While we recommend Claude Code for the best Nette experience, MCP Inspector works with any MCP-compatible tool. + + +Cursor +------ + +Cursor is a popular AI-first code editor. To use MCP Inspector with Cursor: + +1. Install MCP Inspector: `composer require nette/mcp-inspector` +2. Create `.cursor/mcp.json` in your project: + +```json +{ + "mcpServers": { + "nette-inspector": { + "command": "php", + "args": ["vendor/bin/mcp-inspector"] + } + } +} +``` + +3. Restart Cursor + +Note: Cursor doesn't have the Nette-specific skills that the Claude Code plugin provides, but MCP Inspector will still give it access to your application's services, database, routes, and logs. + + +VS Code + Continue +------------------ + +Continue is an open-source AI coding assistant for VS Code. Configure MCP Inspector in Continue's settings following their MCP documentation. + + +Other MCP Tools +--------------- + +Any tool supporting the Model Context Protocol can use MCP Inspector. See the [MCP Inspector manual configuration |mcp-inspector#manual-mcp-configuration] for setup instructions. + + +What's Next +=========== + +You're now ready for AI-assisted Nette development! Here's where to go from here: + +- [MCP Inspector |mcp-inspector] – Learn about all 20 introspection tools +- [Claude Code Plugin |claude-code] – Explore all 13 skills (Claude Code users) +- [Tips & Best Practices |tips] – Get the most out of your AI assistant diff --git a/ai/en/guide.texy b/ai/en/guide.texy new file mode 100644 index 0000000000..b0d98486c5 --- /dev/null +++ b/ai/en/guide.texy @@ -0,0 +1,128 @@ +Vibe Coding +*********** + +
+ +Vibe coding is a new way of programming where you describe what you want in plain language and AI writes the code for you. Nette is ideal for this style of development – strict dependency injection, strong typing, and clear conventions allow AI to generate precise, working code. + +- **MCP Inspector** – Gives any AI tool real-time access to your application +- **Claude Code Plugin** – Deep Nette knowledge for Claude Code users +- **Best Practices** – Proven patterns for effective AI collaboration + +
+ + +What is Vibe Coding? +==================== + +"The hottest new programming language is English." + +That's the core idea behind vibe coding – instead of writing every line yourself, you describe your intent and let AI handle the implementation. Want a presenter for managing products? Just say so. Need a form with validation? Describe the fields and rules. + +But here's the important part: **AI doesn't replace programmers**. It's a powerful assistant that accelerates routine work: + +- Generate boilerplate code (presenters, forms, entities) in seconds +- Understand existing code and explain how it works +- Find bugs and suggest fixes +- Write tests based on your implementation + +The catch? AI doesn't truly know your application. It sees only what you show it and guesses the rest based on patterns it learned during training. That's where Nette AI tools come in. + + +Why Nette is Perfect for AI +=========================== + +Not all frameworks work equally well with AI. Nette has properties that make it exceptionally suited for AI-assisted development: + +**Strict Dependency Injection** + +In Nette, all services are registered in the DI container. AI can inspect exactly what services exist and how they're configured – no guessing required. + +**Strong Typing** + +Type hints on methods and properties mean AI generates code that actually works. Fewer runtime errors, less debugging. + +**Clear Conventions** + +Presenters, components, templates – everything has its place. AI can follow these patterns and produce code that looks like it was written by an experienced Nette developer. + +The key principle: + +.**"Without MCP, AI guesses. With MCP, AI knows."** + + +How It Works +============ + +The magic happens through **MCP (Model Context Protocol)** – an open standard for connecting AI assistants to external data sources. Instead of guessing based on training data, AI can query your actual application state. + +Here's the flow: + +1. **You** describe what you want: "Create an entity for the product table" +2. **AI tool** (Claude, Cursor, etc.) needs to know your database schema +3. **MCP Inspector** queries your application and returns the actual schema +4. **AI** generates code that matches your real database + +No hallucinations. No guessing. Just accurate code. + + +Nette AI Tools +============== + + +MCP Inspector +------------- + +The core of Nette's AI integration. MCP Inspector is an MCP server that gives **any compatible AI tool** real-time access to your application: + +| What AI Can See | Examples | +|-----------------|----------| +| **DI Container** | Services, parameters, extensions | +| **Database** | Tables, columns, relationships | +| **Router** | Routes, URL matching, generation | +| **Tracy** | Exceptions, warnings, logs | + +MCP Inspector works with Claude Code, Cursor, VS Code with Continue, and any other tool that supports the MCP protocol. + +[Learn more about MCP Inspector |mcp-inspector] + + +Claude Code Plugin +------------------ + +For users of Claude Code, there's an additional plugin that gives Claude deep knowledge of Nette conventions. It includes 10 specialized "skills" that activate automatically: + +| Skill | What It Covers | +|-------|----------------| +| nette-architecture | Presenters, modules, directory structure | +| nette-database | Database Explorer, entities, queries | +| nette-forms | Controls, validation, rendering | +| latte-templates | Syntax, filters, security | +| + 6 more... | [See complete list |claude-code] | + +The plugin also automatically validates Latte templates and NEON files after every edit. + +[Learn more about Claude Code Plugin |claude-code] + + +Other AI Tools +-------------- + +MCP Inspector works with any MCP-compatible tool. Setup guides for additional tools are coming soon: + +- **Cursor** – Popular AI-first code editor +- **VS Code + Continue** – Open-source AI coding assistant +- **Gemini CLI** – Google's command-line AI tool + + +Getting Started +=============== + +Ready to try vibe coding with Nette? The setup takes about 10 minutes: + +1. **Choose your AI tool** – We recommend Claude Code for the best Nette experience +2. **Install MCP Inspector** – The core that gives AI access to your application +3. **Start coding** – Describe what you want and let AI help + +[Complete setup guide |getting-started] + diff --git a/ai/en/mcp-inspector.texy b/ai/en/mcp-inspector.texy new file mode 100644 index 0000000000..5965a94677 --- /dev/null +++ b/ai/en/mcp-inspector.texy @@ -0,0 +1,448 @@ +MCP Inspector +************* + +
+ +MCP Inspector is the bridge between **any AI tool** and your Nette application. It allows AI assistants to look directly at your running app – to see what services you have registered, what your database schema looks like, which routes are defined, and what errors have occurred. + +This is what makes the difference between AI that guesses and AI that knows. + +
+ + +Supported AI Tools +================== + +MCP Inspector works with any tool that supports the **Model Context Protocol (MCP)**: + +- **[Claude Code |claude-code]** – Full support with dedicated Nette plugin +- **Cursor** – Configure via `.cursor/mcp.json` +- **VS Code + Continue** – Configure via Continue settings +- **Any MCP-compatible tool** – See [manual configuration |#manual-mcp-configuration] + + +Why MCP Matters +=============== + +Imagine you ask your AI: "Generate an entity for the product table." + +Without MCP Inspector, the AI has to guess what columns your table has. It might assume common patterns like `id`, `name`, `price` – but what if your table has different columns? What if `price` is called `unit_price`? What if you have a `currency_id` foreign key? + +With MCP Inspector, the AI doesn't guess. It calls `db_get_columns("product")` and sees your actual schema: + +The result is code that actually works with your database, not code you have to fix. + + +Installation +============ + +If you're using the [Nette plugin for Claude Code |claude-code], installation is simple: + +```shell +/install-mcp-inspector +``` + +This command adds `nette/mcp-inspector` to your project and configures everything automatically. + +For other AI tools or manual installation: + +```shell +composer require nette/mcp-inspector +``` + +Then configure your AI tool to use the MCP server – see [manual configuration |#manual-mcp-configuration] below. + +**Important:** After installation, restart your AI tool. The MCP server only connects when the tool starts. + + +How It Works +============ + +MCP Inspector runs as a background process that your AI tool can communicate with. When AI needs information about your application, it sends a request to MCP Inspector, which: + +1. Loads your application's DI container (using `App\Bootstrap`) +2. Executes the requested query (get services, read database schema, etc.) +3. Returns the result to the AI + +All operations are **read-only**. MCP Inspector can't modify your database, change configuration, or execute commands. + + +DI Container Tools +================== + +These tools let AI explore your service definitions. + + +di_get_services +--------------- + +Lists all registered services. You can filter by name or type. + +When AI asks "What mail services do I have?", it calls: + +``` +di_get_services("mail") +``` + +And gets a list like: + +``` +- mail.mailer (Nette\Mail\Mailer) +- App\Model\QueueMailer +- App\Core\SmtpTransport +``` + + +di_get_service +-------------- + +Gets detailed information about a specific service – how it's created, what setup methods are called, what tags it has. + + +di_get_parameters +----------------- + +Reads configuration parameters. Want to know what your database settings are? + +``` +di_get_parameters("database") +``` + +Note: Sensitive values (passwords, tokens, API keys) are automatically masked. + + +di_find_by_tag +-------------- + +Finds services with a specific tag. Useful for discovering CLI commands: + +``` +di_find_by_tag("console.command") +``` + + +di_find_by_type +--------------- + +Finds services implementing a specific interface: + +``` +di_find_by_type("Nette\\Security\\Authenticator") +``` + + +di_get_extensions +----------------- + +Lists all registered DI extensions with their configuration. + + +Database Tools +============== + +These tools give AI visibility into your database structure. + + +db_get_tables +------------- + +Lists all tables in your database. + + +db_get_columns +-------------- + +Gets detailed column information for a table – types, whether they're nullable, default values, and foreign key relationships. + +``` +db_get_columns("order") +``` + +Returns something like: + +``` +- id: int (PRIMARY KEY) +- customer_id: int (FK → customer.id) +- status: varchar(20) +- total: decimal(10,2) +- created_at: datetime +``` + + +db_get_relationships +-------------------- + +Shows all foreign key relationships in your database – which tables reference which other tables. + + +db_get_indexes +-------------- + +Lists indexes for a specific table. + + +db_explain_query +---------------- + +Runs `EXPLAIN` on a SELECT query to analyze its performance. AI can use this to suggest query optimizations. + + +db_generate_entity +------------------ + +The most useful tool for quick development. Given a table name, it generates a complete PHP entity class with proper type hints: + +``` +db_generate_entity("product") +``` + +Generates: + +```php +/** + * @property-read int $id + * @property-read string $name + * @property-read float $unit_price + * @property-read ?CategoryRow $category + * @property-read DateTimeImmutable $created_at + */ +final class ProductRow extends Table\ActiveRow +{ +} +``` + + +Router Tools +============ + +These tools help AI understand your URL structure. + + +router_get_routes +----------------- + +Lists all registered routes with their masks and default values. + + +router_match_url +---------------- + +Given a URL, finds which presenter and action handles it: + +``` +router_match_url("/admin/products/edit/5") +``` + +Returns: + +``` +Presenter: Admin:Product +Action: edit +Parameters: id=5 +``` + + +router_generate_url +------------------- + +Generates a URL for a given presenter and action: + +``` +router_generate_url("Admin:Product:edit", {"id": 5}) +``` + + +Tracy Tools +=========== + +These tools let AI see error logs and help with debugging. They're incredibly useful when something goes wrong – instead of you describing the error, AI can read it directly. + + +tracy_get_last_exception +------------------------ + +Gets the most recent exception from Tracy's log, including the full stack trace. When something breaks, this is the first thing AI checks. + +``` +tracy_get_last_exception() +``` + +Returns the exception class, message, file, line number, and complete stack trace. AI can analyze this to identify the root cause and suggest a fix. + +Example response: +``` +Exception: Nette\Database\UniqueConstraintViolationException +Message: Duplicate entry 'john@example.com' for key 'email' +File: /app/Model/UserService.php:45 +Stack trace: + #0 /app/Presentation/Admin/UserPresenter.php:32 + #1 /vendor/nette/application/src/... +``` + + +tracy_get_exceptions +-------------------- + +Lists recent exception files from Tracy's log directory. Useful for finding patterns or recurring issues. + +``` +tracy_get_exceptions(5) +``` + +Returns the 5 most recent exception files with timestamps. You can then use `tracy_get_exception_detail` to examine any of them. + + +tracy_get_exception_detail +-------------------------- + +Gets the complete details of a specific exception file. Use this when you want to examine an older exception, not just the latest one. + +``` +tracy_get_exception_detail("exception-2024-01-15-143022-abc123.html") +``` + + +tracy_get_warnings +------------------ + +Shows recent PHP warnings and notices from Tracy's log. These often indicate problems that don't crash the application but should be fixed. + +``` +tracy_get_warnings(10) +``` + +Common warnings AI can help fix: +- Undefined array key +- Deprecated function calls +- Type mismatch warnings + + +tracy_get_log +------------- + +Reads entries from any Tracy log level. Tracy supports multiple log files: `error.log`, `warning.log`, `info.log`, and custom levels. + +``` +tracy_get_log("error", 20) +``` + +This reads the last 20 entries from the error log. Useful for seeing a history of issues, not just the most recent one. + + +Creating Custom Tools +===================== + +You can extend MCP Inspector with your own tools. This is useful if you have application-specific data that AI should be able to query. + +Create a class implementing the `Toolkit` interface: + +```php +use Mcp\Capability\Attribute\McpTool; +use Nette\McpInspector\Toolkit; +use Nette\McpInspector\Bridge\BootstrapBridge; + +class OrderToolkit implements Toolkit +{ + public function __construct( + private BootstrapBridge $bridge, + ) {} + + /** + * Get pending orders count and total value. + */ + #[McpTool(name: 'orders_get_pending_summary')] + public function getPendingSummary(): array + { + $db = $this->bridge->getContainer() + ->getByType(Nette\Database\Explorer::class); + + $result = $db->table('order') + ->where('status', 'pending') + ->select('COUNT(*) AS count, SUM(total) AS total') + ->fetch(); + + return [ + 'count' => $result->count, + 'total' => $result->total, + ]; + } +} +``` + +Register it in `mcp-config.neon`: + +```neon +toolkits: + - App\Mcp\OrderToolkit +``` + +Now AI can call `orders_get_pending_summary()` to get real-time order statistics. + + +Configuration +============= + +MCP Inspector works out of the box with the default Nette project structure. If your setup is different, create `mcp-config.neon` in your project root: + +```neon +# Path to Bootstrap file (if not in default location) +bootstrap: src/Bootstrap.php + +# Bootstrap class name (if different from default) +bootstrapClass: MyApp\Bootstrap + +# Additional custom toolkits +toolkits: + - App\Mcp\OrderToolkit + - App\Mcp\CustomerToolkit +``` + + +Manual MCP Configuration +------------------------ + +For AI tools other than Claude Code (which configures automatically via the plugin), add MCP Inspector to your tool's configuration: + +**For most MCP-compatible tools**, create `.mcp.json` in your project root: + +```json +{ + "mcpServers": { + "nette-inspector": { + "command": "php", + "args": ["vendor/bin/mcp-inspector"] + } + } +} +``` + +**For Cursor**, add to `.cursor/mcp.json`: + +```json +{ + "mcpServers": { + "nette-inspector": { + "command": "php", + "args": ["vendor/bin/mcp-inspector"] + } + } +} +``` + +Consult your AI tool's documentation for the exact configuration location. + + +Security Considerations +======================= + +MCP Inspector is designed for development environments. Here's what you should know: + +**Read-only by design** – All tools only read data, never modify it. + +**Database protection** – The `db_explain_query` tool only accepts SELECT, SHOW, DESCRIBE, and EXPLAIN queries. INSERT, UPDATE, DELETE, and other modifying queries are rejected. + +**Sensitive data masking** – Configuration values containing words like "password", "secret", "token", or "apikey" are automatically masked with `***MASKED***`. + +**Do not expose in production** – MCP Inspector should only run on development machines. It provides detailed information about your application internals that you don't want exposed publicly. + +{{composer: nette/mcp-inspector}} diff --git a/ai/en/tips.texy b/ai/en/tips.texy new file mode 100644 index 0000000000..586f558519 --- /dev/null +++ b/ai/en/tips.texy @@ -0,0 +1,296 @@ +Tips for AI-Assisted Development +******************************** + +
+ +AI is a powerful tool, but like any tool, you get better results when you know how to use it well. This page collects practical advice from real-world experience with AI-assisted Nette development. + +- How to write prompts that get better results +- Making the most of MCP Inspector +- Proven workflows for common tasks +- Mistakes to avoid + +
+ + +Writing Better Prompts +====================== + + +The Art of Being Specific +------------------------- + +The single biggest improvement you can make is being specific. Compare these two prompts: + +**Vague prompt:** + +``` +Create a form +``` + +This gives the AI almost no context. What form? What fields? What validation? The AI has to make assumptions, and those assumptions might not match what you need. + +**Specific prompt:** + +``` +Create a ProductForm with: +- name: text field, required, max 100 characters +- price: float field, required, must be positive +- description: textarea, optional +- category: select from CategoryRow entities + +Use Bootstrap 5 rendering. The form should work for both creating new products and editing existing ones. +``` + +Now the AI knows exactly what you need and can generate code that works on the first try. + + +Point to Existing Patterns +-------------------------- + +Your codebase already has patterns. Instead of explaining them, point the AI to examples: + +``` +Create an OrderPresenter. Follow the same patterns as ProductPresenter – +same structure, same way of handling forms, same template organization. +``` + +The AI will read ProductPresenter and replicate the patterns you're already using. + + +Let MCP Do the Heavy Lifting +---------------------------- + +If you have MCP Inspector installed (and you should!), don't explain your application – let the AI discover it: + +**Instead of:** + +``` +My product table has columns: id (int), name (varchar), price (decimal), +category_id (int, foreign key to category), created_at (datetime)... +``` + +**Just say:** + +``` +Generate an entity for the product table. +``` + +The AI will call `db_get_columns("product")` and see the actual schema. The generated entity will match your real database, including any columns you might have forgotten to mention. + + +Give Context About Your Goals +----------------------------- + +AI can't read your mind. If there's a reason behind your request, share it: + +``` +I need to optimize the product listing page. It's currently loading +all products at once, which is slow when there are thousands of items. +The page needs to support filtering by category and sorting by price or name. +``` + +This helps the AI suggest an appropriate solution (pagination, lazy loading, caching) rather than just blindly implementing what you asked for. + + +Working with MCP Inspector +========================== + +MCP Inspector is most powerful when you use it strategically. + + +Explore Before You Build +------------------------ + +Starting a new feature? Let the AI understand the context first: + +``` +I'm going to add order tracking. Before we start: +1. What services do I have related to orders? +2. What does my order table look like? +3. What routes handle order-related pages? +``` + +This gives the AI context about your existing code, so the new feature fits naturally. + + +Debug Smarter +------------- + +When something goes wrong, don't describe the error – let the AI see it: + +``` +Something broke. Check the Tracy log for the last exception +and tell me what went wrong. +``` + +The AI will call `tracy_get_last_exception()`, read the stack trace, and can often identify the problem faster than you could explain it. + + +Verify Before You Create +------------------------ + +Before adding new routes or links, verify what exists: + +``` +What presenter handles /admin/products/edit? I want to make sure +I'm not creating something that conflicts. +``` + + +Common Workflows +================ + +Here are proven approaches for common tasks. + + +Creating a Complete CRUD +------------------------ + +Don't ask for one piece at a time. Give the AI the full picture: + +``` +Create a complete CRUD for managing products: + +1. ProductPresenter with actions: list, add, edit, delete +2. ProductForm as a component (works for both add and edit) +3. Latte templates for all actions +4. Route suggestions + +Use the actual product table schema. Follow the patterns +in CategoryPresenter if it exists. +``` + + +Adding a New Feature +-------------------- + +Break it down into phases that build on each other: + +``` +I need to add customer reviews to products. + +Phase 1 - Data layer: +- Look at the product table +- Suggest the review table schema +- Create ReviewRow entity + +Phase 2 - Business logic: +- Create ReviewService for CRUD operations +- Add methods to get reviews for a product + +Phase 3 - UI: +- Add review display to ProductPresenter:detail +- Create ReviewForm for submitting reviews +``` + + +Refactoring Existing Code +------------------------- + +Let the AI understand before it changes: + +``` +Analyze the OrderService class. What does each method do? +Are there any code smells or improvements you'd suggest? +``` + +Then: + +``` +The calculateTotal method is doing too much. Split it into +smaller methods while keeping the same public interface. +``` + + +Mistakes to Avoid +================= + + +Not Reviewing Generated Code +---------------------------- + +AI generates code quickly, but that doesn't mean every line is perfect. Always review: + +- **Database queries** – Are they efficient? Do they need indexes? +- **Security** – Is input validated? Are there authorization checks? +- **Edge cases** – What happens with empty data? Null values? + +AI is very good, but it's still an assistant. You're the developer responsible for the final code. + + +Ignoring Validation Feedback +---------------------------- + +If you're using the [Claude Code plugin |claude-code], it validates your Latte templates and NEON files automatically. When it reports an error, the AI knows about it. Instead of manually fixing the error, just say: + +``` +Fix the error you just created. +``` + +The AI will read the validation output and correct the mistake. + + +Forgetting Service Registration +------------------------------- + +When the AI creates a new service class, it sometimes forgets to register it in the DI container. If you get "Service not found" errors, ask: + +``` +What changes do I need in services.neon for the new OrderExportService? +``` + + +Asking for Too Much at Once +--------------------------- + +While AI can handle complex tasks, sometimes it helps to break them down: + +**Too ambitious:** + +``` +Build me a complete e-commerce system with product catalog, +shopping cart, checkout, payments, order tracking, and admin panel. +``` + +**Better approach:** + +``` +Let's build an e-commerce system step by step. Start with the product +catalog – I need to list, view, and admin products. +``` + + +When AI Excels (and When It Doesn't) +==================================== + + +AI is Great For +--------------- + +- **Boilerplate code** – Presenters, forms, entities, basic templates +- **Following patterns** – "Do it like X but for Y" +- **Understanding code** – "What does this method do?" +- **Generating tests** – Given implementation, create tests +- **Refactoring** – Improving code structure while keeping behavior + + +Consider Manual Coding For +-------------------------- + +- **Complex business logic** – Domain rules that require careful thinking +- **Performance-critical code** – Algorithms that need optimization +- **Security-sensitive code** – Authentication, authorization, encryption +- **Novel solutions** – Things that don't follow existing patterns + +AI is a multiplier, not a replacement. It makes good developers faster, but it still needs a good developer guiding it. + + +Final Thoughts +============== + +The best way to learn AI-assisted development is to practice. Start with simple tasks, pay attention to what works, and gradually take on more complex projects. + +And remember: the AI is your assistant. You're still the developer. You make the decisions, you review the code, and you're responsible for the quality of the final product. + +Happy coding! diff --git a/ai/meta.json b/ai/meta.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/ai/meta.json @@ -0,0 +1 @@ +{} diff --git a/application/cs/creating-links.texy b/application/cs/creating-links.texy index 011beea750..8658cb3646 100644 --- a/application/cs/creating-links.texy +++ b/application/cs/creating-links.texy @@ -12,7 +12,7 @@ Tvořit odkazy v Nette je jednoduché, jako ukazovat prstem. Stačí jen namíř -Díky [obousměrnému routování |routing] nebudete nikdy muset do šablon či kódu zapisovat navrdo URL adresy vaší aplikace, které se mohou později měnit, nebo je komplikovaně skládat. V odkazu stačí uvést presenter a akci, předat případné parametry a framework už URL vygeneruje sám. Vlastně je to velice podobné, jako když voláte funkci. To se vám bude líbit. +Díky [obousměrnému routování |routing] nebudete nikdy muset do šablon či kódu zapisovat natvrdo URL adresy vaší aplikace, které se mohou později měnit, nebo je komplikovaně skládat. V odkazu stačí uvést presenter a akci, předat případné parametry a framework už URL vygeneruje sám. Vlastně je to velice podobné, jako když voláte funkci. To se vám bude líbit. V šabloně presenteru diff --git a/application/cs/presenters.texy b/application/cs/presenters.texy index 04cd942e32..f00a645bba 100644 --- a/application/cs/presenters.texy +++ b/application/cs/presenters.texy @@ -393,6 +393,8 @@ public function actionShow(int $id, ?string $slug = null): void } ``` +Kompletní vzor, který kombinuje routovací filtry s `canonicalize()` pro generování SEO-friendly URL, najdete v návodu [Hezké URL se slugem |best-practices:pretty-urls]. + Události -------- diff --git a/application/cs/routing.texy b/application/cs/routing.texy index 3a2e753731..b5a7648612 100644 --- a/application/cs/routing.texy +++ b/application/cs/routing.texy @@ -325,6 +325,8 @@ Obecné filtry dávají možnost upravit chování routy naprosto jakýmkoliv zp Pokud má parametr definovaný vlastní filtr a současně existuje obecný filtr, provede se vlastní `FilterIn` před obecným a naopak obecný `FilterOut` před vlastním. Tedy uvnitř obecného filtru jsou hodnoty parametrů `presenter` resp. `action` zapsané ve stylu PascalCase resp. camelCase. +Praktické využití těchto filtrů — generování SEO-friendly URL typu `/clanek/123-jak-upect-chleba` bez zásahu do šablon — najdete v návodu [Hezké URL se slugem |best-practices:pretty-urls]. + Jednosměrky OneWay ------------------ diff --git a/application/cs/templates.texy b/application/cs/templates.texy index 568b40837e..5e4452a586 100644 --- a/application/cs/templates.texy +++ b/application/cs/templates.texy @@ -274,7 +274,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template #[Latte\Attributes\TemplateFunction] public function isWeekend(DateTimeInterface $date): bool { - return $date->format('N') >= 6 + return $date->format('N') >= 6; } } ``` diff --git a/application/en/presenters.texy b/application/en/presenters.texy index 7658686bbf..272c3216f9 100644 --- a/application/en/presenters.texy +++ b/application/en/presenters.texy @@ -393,6 +393,8 @@ public function actionShow(int $id, ?string $slug = null): void } ``` +For a complete pattern that combines route filters with `canonicalize()` to produce SEO-friendly URLs, see [Pretty URLs with Slugs |best-practices:pretty-urls]. + Events ------ diff --git a/application/en/routing.texy b/application/en/routing.texy index 4b83f317f2..8cf31e3c99 100644 --- a/application/en/routing.texy +++ b/application/en/routing.texy @@ -325,6 +325,8 @@ General filters provide the ability to modify the route's behavior in absolutely If a parameter has its own filter defined and a general filter also exists, the custom `FilterIn` is executed before the general one, and conversely, the general `FilterOut` is executed before the custom one. Thus, inside the general filter, the values of the parameters `presenter` and `action` are written in PascalCase or camelCase style, respectively. +See [Pretty URLs with Slugs |best-practices:pretty-urls] for a practical use of these filters — generating SEO-friendly URLs like `/article/123-how-to-bake-bread` without modifying any templates. + OneWay Flag ----------- diff --git a/application/en/templates.texy b/application/en/templates.texy index 6a5ba43fd3..c5de1f1484 100644 --- a/application/en/templates.texy +++ b/application/en/templates.texy @@ -274,7 +274,7 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template #[Latte\Attributes\TemplateFunction] public function isWeekend(DateTimeInterface $date): bool { - return $date->format('N') >= 6 + return $date->format('N') >= 6; } } ``` diff --git a/best-practices/bg/@home.texy b/best-practices/bg/@home.texy index 808c4d31b7..31c68a5d23 100644 --- a/best-practices/bg/@home.texy +++ b/best-practices/bg/@home.texy @@ -42,7 +42,6 @@ Nette Приложения - [Защо Nette използва PascalCase нотация за константи? |https://blog.nette.org/bg/for-less-screaming-in-the-code] - [Защо Nette не използва суфикс Interface? |https://blog.nette.org/bg/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: съвети за използване |composer] -- [Съвети за редактори & инструменти |editors-and-tools] - [Въведение в обектно-ориентираното програмиране |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/bg/editors-and-tools.texy b/best-practices/bg/editors-and-tools.texy deleted file mode 100644 index 89751ce259..0000000000 --- a/best-practices/bg/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Редактори & инструменти -*********************** - -.[perex] -Може да сте опитен програмист, но само с добри инструменти ще станете майстор. В тази глава ще намерите съвети за важни инструменти, редактори и плъгини. - - -IDE редактор -============ - -Определено препоръчваме да използвате пълнофункционално IDE за разработка, като PhpStorm, NetBeans, VS Code, а не само текстов редактор с поддръжка на PHP. Разликата е наистина съществена. Няма причина да се задоволявате само с редактор, който може да оцветява синтаксиса, но не достига възможностите на водещо IDE, което точно подсказва, следи за грешки, може да рефакторира код и много повече. Някои IDE са платени, други дори безплатни. - -**NetBeans IDE** има вградена поддръжка за Nette, Latte и NEON. - -**PhpStorm**: инсталирайте тези плъгини в `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: намерете плъгина "Nette Latte + Neon" в marketplace. - -Свържете също Tracy с редактора си. Когато се покаже страница с грешка, ще можете да кликнете върху имената на файловете и те ще се отворят в редактора с курсор на съответния ред. Прочетете [как да конфигурирате системата |tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan е инструмент, който открива логически грешки в кода, преди да го стартирате. - -Инсталираме го с помощта на Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Създаваме конфигурационен файл `phpstan.neon` в проекта: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -И след това го оставяме да анализира класовете в папката `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Изчерпателна документация можете да намерите директно на [уебсайта на PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] проверява и евентуално коригира някои от формалните грешки във вашия изходен код: - -- премахва [BOM |nette:glossary#BOM] -- проверява валидността на [Latte |latte:] шаблоните -- проверява валидността на файловете `.neon`, `.php` и `.json` -- проверява за наличие на [контролни знаци |nette:glossary#Контролни знаци] -- проверява дали файлът е кодиран в UTF-8 -- проверява за неправилно записани `/* @anotace */` (липсва звездичка) -- премахва затварящия таг `?>` от PHP файловете -- премахва интервалите в края на реда и ненужните редове в края на файла -- нормализира разделителите на редове до системните (ако посочите опцията `-l`) - - -Composer -======== - -[Composer |Composer] е инструмент за управление на зависимости в PHP. Позволява ни да декларираме произволно сложни зависимости на отделни библиотеки и след това ги инсталира вместо нас в нашия проект. - - -Requirements Checker -==================== - -Това беше инструмент, който тестваше средата за изпълнение на сървъра и информираше дали (и до каква степен) е възможно да се използва framework-ът. В момента Nette може да се използва на всеки сървър, който има минималната изисквана версия на PHP. diff --git a/best-practices/cs/@home.texy b/best-practices/cs/@home.texy index 612d75048f..e95aa101a3 100644 --- a/best-practices/cs/@home.texy +++ b/best-practices/cs/@home.texy @@ -19,6 +19,7 @@ Nette Aplikace - [Dynamické snippety |dynamic-snippets] - [Jak používat atribut #Requires |attribute-requires] - [Jak správně používat POST odkazy |post-links] +- [Hezké URL se slugem |pretty-urls]
@@ -42,7 +43,6 @@ Obecné - [Proč Nette používá PascalCase notaci konstant? |https://blog.nette.org/cs/za-mene-kriku-v-kodu] - [Proč Nette nepoužívá příponu Interface? |https://blog.nette.org/cs/predpony-a-pripony-do-nazvu-rozhrani-nepatri] - [Composer: tipy pro použití |composer] -- [Tipy na editory & nástroje |editors-and-tools] - [Úvod do objektově orientovaného programování |nette:introduction-to-object-oriented-programming]
diff --git a/best-practices/cs/creating-editing-form.texy b/best-practices/cs/creating-editing-form.texy index 4530f060d4..d43c67faf8 100644 --- a/best-practices/cs/creating-editing-form.texy +++ b/best-practices/cs/creating-editing-form.texy @@ -130,7 +130,6 @@ Záznam si uložíme do property `$record`, abychom jej měli k dispozici v meto $this->facade->update($id, $data); // ... } -} ``` Nicméně, a to by mělo být **nejdůležitejším poznatkem celého kódu**, musíme se při tvorbě formuláře ujistit, že akce je skutečně `edit`. Protože jinak by ověření v metodě `actionEdit()` vůbec neproběhlo! diff --git a/best-practices/cs/editors-and-tools.texy b/best-practices/cs/editors-and-tools.texy deleted file mode 100644 index 13e3d10138..0000000000 --- a/best-practices/cs/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editory & nástroje -****************** - -.[perex] -Můžete být zdatný programátor, ale teprve s dobrými nástroji se z vás stane mistr. V této kapitole najdete tipy na důležité nástroje, editory a pluginy. - - -IDE editor -========== - -Rozhodně doporučujeme pro vývoj používat plnohodnotné IDE, jako je třeba PhpStorm, NetBeans, VS Code, a nikoliv jen textový editor s podporou PHP. Rozdíl je opravdu zásadní. Není důvod se spokojit s pouhým editorem, který sice umí obarvovat syntaxi, ale nedosahuje možností špičkového IDE, které přesně napovídá, hlídá chyby, umí refaktorovat kód a spoustu dalšího. Některé IDE jsou placené, jiné dokonce zdarma. - -**NetBeans IDE** má podporu pro Nette, Latte a NEON už vestavěnou. - -**PhpStorm**: nainstalujte si tyto pluginy v `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: najděte v marketplace "Nette Latte + Neon" plugin. - -Také si propojte Tracy s editorem. Při zobrazení chybové stránky pak půjde kliknout na jména souborů a ty se otevřou v editoru s kurzorem na příslušné řádce. Přečtěte si, [jak systém nakonfigurovat|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan je nástroj, který odhalí logické chyby v kódu dřív, než jej spustíte. - -Nainstalujeme jej pomocí Composeru: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Vytvoříme v projektu konfigurační soubor `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -A následně jej necháme zanalyzovat třídy ve složce `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Vyčerpávající dokumentaci najdete přímo na [stránkách PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] zkontroluje a případně opraví některé z formálních chyb ve vašich zdrojových kódech: - -- odstraňuje [BOM |nette:glossary#BOM] -- kontroluje validitu [Latte |latte:] šablon -- kontroluje validitu souborů `.neon`, `.php` a `.json` -- kontroluje výskyt [kontrolních znaků |nette:glossary#Kontrolní znaky] -- kontroluje, zda je soubor kódován v UTF-8 -- kontroluje chybně zapsané `/* @anotace */` (chybí hvězdička) -- odstraňuje ukončovací `?>` u PHP souborů -- odstraňuje pravostranné mezery a zbytečné řádky na konci souboru -- normalizuje oddělovače řádků na systémové (pokud uvedete volbu `-l`) - - -Composer -======== - -[Composer] je nástroj na správu závislostí v PHP. Dovoluje nám deklarovat libovolně složité závislosti jednotlivých knihoven a pak je za nás nainstaluje do našeho projektu. - - -Requirements Checker -==================== - -Šlo o nástroj, který testoval běhové prostředí serveru a informoval, zda (a do jaké míry) je možné framework používat. V současnosti je Nette možné používat na každém serveru, který má minimální požadovanou verzi PHP. diff --git a/best-practices/cs/lets-create-contact-form.texy b/best-practices/cs/lets-create-contact-form.texy index e5d44812fa..23fde0f0c5 100644 --- a/best-practices/cs/lets-create-contact-form.texy +++ b/best-practices/cs/lets-create-contact-form.texy @@ -48,9 +48,6 @@ Komponentu `contactForm` necháme vykreslit v šabloně `Home/default.latte`: Pro samotné odeslání emailu vytvoříme novou třídu, kterou nazveme `ContactFacade` a umístíme ji do souboru `app/Model/ContactFacade.php`: ```php -addRoute('clanek/[-]', 'Article:detail'); +``` + +Maska `[-]` říká: po ID může (ale nemusí) následovat pomlčka a slug. Routa přijímá `/clanek/123` i `/clanek/123-cokoli`. + +Poznámka k parametru ``: defaultně matchuje libovolné znaky **kromě lomítka** — přesně to, co chceme. Pokud napíšete ``, parametr bude matchovat i lomítka, takže `/clanek/123-neco/jineho` by se naparsovalo jako jediný slug obsahující `/`. Pokud nechcete lomítka ve slugu, zůstaňte u defaultního ``. + +URL se teď parsuje správně, ale generované odkazy slug neobsahují. Dalším krokem je routu naučit, jak slug doplnit. + + +Generování slugu bez zásahu do šablon +===================================== + +Tohle je hlavní varianta. Stávající `n:href="Article:detail, $id"` volání zůstávají beze změny napříč celou aplikací — router si titulek vyhledá sám. + +Použijeme **obecný filtr** pod klíčem prázdného stringu — ten vidí všechny parametry najednou a může slug doplnit: + +```php +use Nette\Routing\Route; +use Nette\Utils\Strings; + +$router->addRoute('clanek/[-]', [ + 'presenter' => 'Article', + 'action' => 'detail', + '' => [ + Route::FilterOut => function (array $params) use ($slugProvider): array { + if (isset($params['id']) && empty($params['slug'])) { + $params['slug'] = $slugProvider->getSlug((int) $params['id']); + } + return $params; + }, + ], +]); +``` + +`FilterOut` se spustí pokaždé, když router **generuje** URL. Pokud slug nebyl předán, filtr titulek dohledá a doplní. + +Slugy můžete nasadit napříč celou aplikací jedinou změnou — jednou definicí routy. Každý odkaz v každé šabloně začne automaticky produkovat `/clanek/123-jak-upect-chleba`. Žádný grep, žádné hledání po šablonách, žádný přehlédnutý case. + + +Cache pro vyhledávání +===================== + +Jedno volání odkazu znamená jeden DB dotaz, ale typická stránka jich má hodně — výpisy, drobečková navigace, „naposledy prohlížené", související články. Stejné ID článku se v rámci jednoho requestu objeví v několika odkazech a nechceme do DB chodit pokaždé. + +Stačí drobná per-request cache. Obalte DB volání malou službou: + +```php +final class SlugProvider +{ + /** @var array */ + private array $cache = []; + + public function __construct( + private Nette\Database\Explorer $db, + ) { + } + + public function getSlug(int $id): string + { + return $this->cache[$id] ??= Strings::webalize(Strings::truncate( + (string) $this->db->fetchField('SELECT title FROM article WHERE id = ?', $id), + 100, '' + )); + } +} +``` + +To stačí — jeden DB dotaz na unikátní ID za request. + + +Předání titulku ze šablony (volitelná rychlá cesta) +=================================================== + +Pokud máte titulek v šabloně po ruce, můžete se DB dotazu úplně vyhnout. Předejte titulek jako pojmenovaný parametr: + +```latte +{$article->title} +``` + +…a přidejte per-parametrový `FilterOut`, který titulek převede na URL-bezpečný tvar: + +```php +$router->addRoute('clanek/[-]', [ + 'presenter' => 'Article', + 'action' => 'detail', + 'slug' => [ + Route::FilterOut => fn($title) => Strings::webalize(Strings::truncate($title, 100, '')), + ], + '' => [/* fallback s vyhledáním z předchozí ukázky */], +]); +``` + +Oba filtry spolupracují. Per-parametrový `FilterOut` proběhne první a předaný titulek převede na slug. Obecný filtr pak vidí, že slug je už vyplněn, a vyhledání v DB přeskočí. Šablony, které titulek nepředávají, dál fungují — projdou cestou s vyhledáváním. + +Použijte to jen tam, kde to opravdu hraje roli (velké výpisy renderované stokrát za request). Pro většinu aplikace cachované vyhledávání stačí. + + +Kanonizace: přesměrování na správnou URL +======================================== + +Umíme teď generovat `/clanek/123-jak-upect-chleba`, ale routa pořád přijímá `/clanek/123` i `/clanek/123-cokoli-co-nekdo-napsal`. To je záměr — chceme krátké URL (viz níže) a chceme, aby staré nebo ručně napsané odkazy fungovaly. Ale nechceme, aby vyhledávače indexovaly stejný článek pod několika adresami. + +Řešením je [kanonizace |application:presenters#kanonizace]: když uživatel přijde po nekanonické URL, aplikace ho přesměruje 301 na správnou. Stará se o to metoda `canonicalize()`: + +```php +public function actionDetail(int $id, ?string $slug = null): void +{ + $article = $this->facade->getArticle($id); + if (!$article) { + $this->error(); + } + + // vygeneruje kanonickou URL přes stejný FilterOut + // a pokud se liší od současné URL, přesměruje HTTP 301 + $this->canonicalize('detail', ['id' => $id]); + + $this->template->article = $article; +} +``` + +`canonicalize()` vygeneruje kanonickou URL stejným způsobem jako `link()` (takže projde stejným `FilterOut`) a porovná ji s aktuální URL. Pokud se liší, přesměruje HTTP 301. Návštěvník skončí na správné URL, vyhledávače vidí jen jednu kanonickou verzi. + + +Jedno místo, které určuje, jak slug vypadá +========================================== + +Všimněte si, že `Strings::webalize(Strings::truncate(..., 100, ''))` žije na **jediném místě** — uvnitř `SlugProvider` (nebo v per-parametrovém `FilterOut`). Stejná logika vyrobí odkaz v šabloně, URL v `redirect()` i kanonický tvar v `canonicalize()`. + +Když budete chtít pravidla později změnit (jiný limit délky, jiná transliterace, vyhazování dalších znaků), upravíte jeden řádek. Bez tohoto byste riskovali, že `redirect()` vygeneruje `/clanek/123-jak-upect-chleba`, zatímco `canonicalize()` bude očekávat `/clanek/123-jak-upect-chl` (protože někde někdo použil jiný `truncate`), a aplikace by se přesměrovávala donekonečna. + + +Bonus: krátké URL stále fungují +=============================== + +Protože je slug nepovinný, fungují i adresy bez něj: + +``` +/clanek/123 +``` + +To se hodí pro: +- **QR kódy** — kratší URL znamená méně hustý a lépe skenovatelný kód +- **SMS a chat** — vejde se do tweetu, vypadá úhledně +- **Tištěné materiály** — krátkou URL se rychleji napíše + +Když uživatel takovou URL otevře, `canonicalize()` ho přesměruje 301 na plnou verzi se slugem, takže vyhledávače stejně uvidí jen kanonický tvar. Můžete mít krátkost i SEO zároveň. + + +Shrnutí +======= + +- Maska `[-]` dělá slug nepovinným. Defaultní `` nematchuje `/`; `` použijte jen tehdy, když opravdu chcete lomítka ve slugu. +- Obecný `FilterOut` pod klíčem `''` dohledá titulek podle ID — **bez zásahu do šablon kdekoli v aplikaci**. +- Vyhledávání obalte drobnou per-request cache; jeden DB dotaz na unikátní ID stačí. +- Volitelně může per-parametrový `FilterOut` umožnit šablonám titulek předat přímo a vyhledávání přeskočit. +- `$this->canonicalize()` v action přesměruje nekanonické URL na správnou s HTTP 301. +- Vzorec pro slug (`webalize` + `truncate`) žije na jednom místě — změníte ho jednou, projeví se všude. +- Krátké URL jen s ID dál fungují, což se hodí pro QR kódy a SMS. + +Více o filtrech a kanonizaci najdete v dokumentaci [routování |application:routing#obecne-filtry] a [presenterů |application:presenters#kanonizace]. diff --git a/best-practices/de/@home.texy b/best-practices/de/@home.texy index d855293435..8f253a9392 100644 --- a/best-practices/de/@home.texy +++ b/best-practices/de/@home.texy @@ -42,7 +42,6 @@ Allgemeines - [Warum Nette die PascalCase-Notation für Konstanten verwendet |https://blog.nette.org/de/for-less-screaming-in-the-code] - [Warum Nette das Interface-Suffix nicht verwendet |https://blog.nette.org/de/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: Tipps zur Verwendung |composer] -- [Tipps für Editoren & Werkzeuge |editors-and-tools] - [Einführung in die objektorientierte Programmierung |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/de/editors-and-tools.texy b/best-practices/de/editors-and-tools.texy deleted file mode 100644 index bda0c9c7fb..0000000000 --- a/best-practices/de/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editoren & Werkzeuge -******************** - -.[perex] -Sie können ein geschickter Programmierer sein, aber erst mit guten Werkzeugen werden Sie zum Meister. In diesem Kapitel finden Sie Tipps zu wichtigen Werkzeugen, Editoren und Plugins. - - -IDE-Editor -========== - -Wir empfehlen dringend, für die Entwicklung eine vollwertige IDE wie PhpStorm, NetBeans, VS Code zu verwenden und nicht nur einen Texteditor mit PHP-Unterstützung. Der Unterschied ist wirklich grundlegend. Es gibt keinen Grund, sich mit einem reinen Editor zufrieden zu geben, der zwar Syntax hervorheben kann, aber nicht die Möglichkeiten einer Spitzen-IDE erreicht, die präzise Vorschläge macht, Fehler überwacht, Code refaktorieren kann und vieles mehr. Einige IDEs sind kostenpflichtig, andere sogar kostenlos. - -**NetBeans IDE** hat bereits integrierte Unterstützung für Nette, Latte und NEON. - -**PhpStorm**: Installieren Sie diese Plugins unter `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: Suchen Sie im Marketplace nach dem Plugin "Nette Latte + Neon". - -Verbinden Sie auch Tracy mit dem Editor. Bei der Anzeige einer Fehlerseite können Sie dann auf Dateinamen klicken und diese werden im Editor mit dem Cursor an der entsprechenden Zeile geöffnet. Lesen Sie, [wie das System konfiguriert wird|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan ist ein Werkzeug, das logische Fehler im Code aufdeckt, bevor Sie ihn ausführen. - -Wir installieren es mit Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Wir erstellen im Projekt eine Konfigurationsdatei `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Und lassen es anschließend die Klassen im Ordner `app/` analysieren: - -```shell -vendor/bin/phpstan analyse app -``` - -Eine ausführliche Dokumentation finden Sie direkt auf den [PHPStan-Seiten |https://phpstan.org]. - - -Code Checker -============ - -Der [Code Checker|code-checker:] überprüft und korrigiert gegebenenfalls einige formale Fehler in Ihren Quellcodes: - -- entfernt [BOM |nette:glossary#BOM] -- überprüft die Gültigkeit von [Latte |latte:]-Templates -- überprüft die Gültigkeit von `.neon`-, `.php`- und `.json`-Dateien -- überprüft das Vorkommen von [Steuerzeichen |nette:glossary#Steuerzeichen] -- überprüft, ob die Datei in UTF-8 kodiert ist -- überprüft falsch geschriebene `/* @annotation */` (Stern fehlt) -- entfernt abschließende `?>` bei PHP-Dateien -- entfernt Leerzeichen am Zeilenende und unnötige Zeilen am Ende der Datei -- normalisiert Zeilentrenner auf Systemstandard (wenn Sie die Option `-l` angeben) - - -Composer -======== - -[Composer] ist ein Werkzeug zur Verwaltung von Abhängigkeiten in PHP. Es ermöglicht uns, beliebig komplexe Abhängigkeiten einzelner Bibliotheken zu deklarieren und diese dann für uns in unser Projekt zu installieren. - - -Requirements Checker -==================== - -Dies war ein Werkzeug, das die Laufzeitumgebung des Servers testete und informierte, ob (und inwieweit) das Framework verwendet werden kann. Derzeit kann Nette auf jedem Server verwendet werden, der die minimal erforderliche PHP-Version hat. diff --git a/best-practices/el/@home.texy b/best-practices/el/@home.texy index 0e8088a224..4b0fced2a6 100644 --- a/best-practices/el/@home.texy +++ b/best-practices/el/@home.texy @@ -42,7 +42,6 @@ - [Γιατί το Nette χρησιμοποιεί τη σημειογραφία PascalCase για σταθερές; |https://blog.nette.org/el/for-less-screaming-in-the-code] - [Γιατί το Nette δεν χρησιμοποιεί το επίθημα Interface; |https://blog.nette.org/el/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: συμβουλές χρήσης |composer] -- [Συμβουλές για editors & εργαλεία |editors-and-tools] - [Εισαγωγή στον αντικειμενοστρεφή προγραμματισμό |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/el/editors-and-tools.texy b/best-practices/el/editors-and-tools.texy deleted file mode 100644 index a5d46f739c..0000000000 --- a/best-practices/el/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Επεξεργαστές & εργαλεία -*********************** - -.[perex] -Μπορεί να είστε ένας ικανός προγραμματιστής, αλλά μόνο με καλά εργαλεία γίνεστε μάστορας. Σε αυτό το κεφάλαιο θα βρείτε συμβουλές για σημαντικά εργαλεία, επεξεργαστές και plugins. - - -IDE editor -========== - -Συνιστούμε ανεπιφύλακτα τη χρήση ενός πλήρους IDE για την ανάπτυξη, όπως το PhpStorm, το NetBeans, το VS Code, και όχι απλώς ενός επεξεργαστή κειμένου με υποστήριξη PHP. Η διαφορά είναι πραγματικά θεμελιώδης. Δεν υπάρχει λόγος να αρκεστείτε σε έναν απλό επεξεργαστή που, αν και μπορεί να χρωματίζει τη σύνταξη, δεν φτάνει τις δυνατότητες ενός κορυφαίου IDE, το οποίο προτείνει με ακρίβεια, ελέγχει για σφάλματα, μπορεί να αναδιαμορφώσει τον κώδικα και πολλά άλλα. Ορισμένα IDE είναι επί πληρωμή, άλλα είναι ακόμη και δωρεάν. - -Το **NetBeans IDE** έχει ενσωματωμένη υποστήριξη για Nette, Latte και NEON. - -**PhpStorm**: εγκαταστήστε αυτά τα plugins στο `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: βρείτε το plugin "Nette Latte + Neon" στο marketplace. - -Συνδέστε επίσης το Tracy με τον επεξεργαστή σας. Όταν εμφανίζεται μια σελίδα σφάλματος, θα μπορείτε να κάνετε κλικ στα ονόματα των αρχείων και αυτά θα ανοίγουν στον επεξεργαστή με τον κέρσορα στην αντίστοιχη γραμμή. Διαβάστε [πώς να διαμορφώσετε το σύστημα |tracy:open-files-in-ide]. - - -PHPStan -======= - -Το PHPStan είναι ένα εργαλείο που εντοπίζει λογικά σφάλματα στον κώδικα πριν τον εκτελέσετε. - -Το εγκαθιστούμε χρησιμοποιώντας το Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Δημιουργούμε στο έργο ένα αρχείο διαμόρφωσης `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Και στη συνέχεια το αφήνουμε να αναλύσει τις κλάσεις στον φάκελο `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Μπορείτε να βρείτε εξαντλητική τεκμηρίωση απευθείας στην [ιστοσελίδα του PHPStan |https://phpstan.org]. - - -Code Checker -============ - -Ο [Code Checker|code-checker:] ελέγχει και ενδεχομένως διορθώνει ορισμένα από τα τυπικά σφάλματα στους πηγαίους κώδικές σας: - -- αφαιρεί το [BOM |nette:glossary#BOM] -- ελέγχει την εγκυρότητα των templates [Latte |latte:] -- ελέγχει την εγκυρότητα των αρχείων `.neon`, `.php` και `.json` -- ελέγχει την ύπαρξη [χαρακτήρων ελέγχου |nette:glossary#Control characters] -- ελέγχει αν το αρχείο είναι κωδικοποιημένο σε UTF-8 -- ελέγχει λανθασμένα γραμμένα `/* @anotace */` (λείπει ο αστερίσκος) -- αφαιρεί το τελικό `?>` από τα αρχεία PHP -- αφαιρεί τα δεξιά κενά και τις περιττές γραμμές στο τέλος του αρχείου -- κανονικοποιεί τους διαχωριστές γραμμών σε συστήματος (αν δώσετε την επιλογή `-l`) - - -Composer -======== - -Ο [Composer |Composer] είναι ένα εργαλείο διαχείρισης εξαρτήσεων στο PHP. Μας επιτρέπει να δηλώνουμε αυθαίρετα πολύπλοκες εξαρτήσεις μεμονωμένων βιβλιοθηκών και στη συνέχεια τις εγκαθιστά για εμάς στο έργο μας. - - -Requirements Checker -==================== - -Ήταν ένα εργαλείο που δοκίμαζε το περιβάλλον εκτέλεσης του server και ενημέρωνε αν (και σε ποιο βαθμό) ήταν δυνατό να χρησιμοποιηθεί το framework. Επί του παρόντος, το Nette μπορεί να χρησιμοποιηθεί σε κάθε server που έχει την ελάχιστη απαιτούμενη έκδοση PHP. diff --git a/best-practices/en/@home.texy b/best-practices/en/@home.texy index 04508b55aa..650201c107 100644 --- a/best-practices/en/@home.texy +++ b/best-practices/en/@home.texy @@ -19,6 +19,7 @@ Nette Application - [Dynamic Snippets |dynamic-snippets] - [How to Use the #Requires Attribute |attribute-requires] - [How to Properly Use POST Links |post-links] +- [Pretty URLs with Slugs |pretty-urls]
@@ -42,7 +43,6 @@ General - [Why Does Nette Use PascalCase Notation for Constants? |https://blog.nette.org/en/for-less-screaming-in-the-code] - [Why Doesn't Nette Use the Interface Suffix? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: Usage Tips |composer] -- [Tips for Editors & Tools |editors-and-tools] - [Introduction to Object-Oriented Programming |nette:introduction-to-object-oriented-programming]
diff --git a/best-practices/en/creating-editing-form.texy b/best-practices/en/creating-editing-form.texy index 27e0af202b..86003dffc6 100644 --- a/best-practices/en/creating-editing-form.texy +++ b/best-practices/en/creating-editing-form.texy @@ -130,7 +130,6 @@ We store the record in the `$record` property, making it available in the `creat $this->facade->update($id, $data); // ... } -} ``` However, and this should be **the most important takeaway from the entire code**, we must ensure the action is indeed `edit` when creating the form. Otherwise, the verification in the `actionEdit()` method would not occur at all! diff --git a/best-practices/en/editors-and-tools.texy b/best-practices/en/editors-and-tools.texy deleted file mode 100644 index c6109dcbab..0000000000 --- a/best-practices/en/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editors & Tools -*************** - -.[perex] -You might be a skilled programmer, but good tools are what make you a master. This chapter provides tips on essential tools, editors, and plugins. - - -IDE Editor -========== - -We strongly recommend using a full-featured IDE for development, like PhpStorm, NetBeans, or VS Code, rather than just a text editor with PHP support. The difference is truly significant. There's no reason to settle for a basic editor that only offers syntax highlighting when you can have a top-tier IDE providing accurate code suggestions, error checking, refactoring capabilities, and much more. Some IDEs are paid, while others are free. - -**NetBeans IDE** has built-in support for Nette, Latte, and NEON. - -**PhpStorm**: Install these plugins via `Settings > Plugins > Marketplace`: -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: Find the "Nette Latte + Neon" plugin in the marketplace. - -Also, integrate Tracy with your editor. When an error page is displayed, clicking on file names will open them directly in your editor at the corresponding line. Learn [how to configure this feature |tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan is a static analysis tool that detects logical errors in your code before you even run it. - -Install it using Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Create a configuration file `phpstan.neon` in your project: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Then, let it analyze the classes within the `app/` directory: - -```shell -vendor/bin/phpstan analyse app -``` - -You can find comprehensive documentation directly on the [PHPStan website |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] checks and potentially fixes some formal errors in your source code: - -- removes [BOM |nette:glossary#BOM] -- checks the validity of [Latte |latte:] templates -- checks the validity of `.neon`, `.php`, and `.json` files -- checks for [control characters |nette:glossary#Control Characters] -- checks if the file is encoded in UTF-8 -- checks for incorrectly written `/* @annotations */` (missing second asterisk) -- removes trailing `?>` PHP tags from files containing only PHP code -- removes trailing whitespace and unnecessary blank lines at the end of files -- normalizes line endings to the system default (using the `-l` option) - - -Composer -======== - -[Composer] is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and manages their installation and updates. - - -Requirements Checker -==================== - -This was a tool that tested the server's runtime environment and indicated whether (and to what extent) the framework could be used. Currently, Nette can be used on any server that meets the minimum required PHP version. diff --git a/best-practices/en/lets-create-contact-form.texy b/best-practices/en/lets-create-contact-form.texy index 0fd677048d..695985f569 100644 --- a/best-practices/en/lets-create-contact-form.texy +++ b/best-practices/en/lets-create-contact-form.texy @@ -48,9 +48,6 @@ Let's render the `contactForm` component in the `Home/default.latte` template: For sending the email itself, we'll create a new class named `ContactFacade` and place it in the file `app/Model/ContactFacade.php`: ```php -addRoute('article/[-]', 'Article:detail'); +``` + +The mask `[-]` says: there may be a hyphen and a slug after the ID, but it's not required. The route accepts both `/article/123` and `/article/123-anything`. + +A note on the parameter ``: by default it matches any characters **except a slash** — exactly what we want. If you write ``, the parameter will match slashes too, so `/article/123-something/else` would parse as a single slug containing `/`. Stay with the default `` unless you really need that. + +So far the URL is parsed correctly, but generated links won't contain the slug. The next step is to teach the route how to fill the slug in. + + +Generating the Slug Without Touching Templates +============================================== + +This is the killer variant. Existing `n:href="Article:detail, $id"` calls keep working unchanged across the whole application — the router looks the title up by itself. + +We do this with a **general filter** under the empty-string key — it sees all parameters at once and can add the slug: + +```php +use Nette\Routing\Route; +use Nette\Utils\Strings; + +$router->addRoute('article/[-]', [ + 'presenter' => 'Article', + 'action' => 'detail', + '' => [ + Route::FilterOut => function (array $params) use ($slugProvider): array { + if (isset($params['id']) && empty($params['slug'])) { + $params['slug'] = $slugProvider->getSlug((int) $params['id']); + } + return $params; + }, + ], +]); +``` + +`FilterOut` runs every time the router **generates** a URL. If the slug wasn't passed in, the filter looks the title up and adds it. + +You can deploy slugs across a whole application in a single change — just one route definition. Every link in every template starts producing `/article/123-how-to-bake-bread` automatically. No grep, no template hunt, no missed corner case. + + +Cache the Lookup +================ + +One link generates one DB query, but a typical page has many — listings, breadcrumbs, "last viewed", related articles. The same article ID often appears in several links during a single request, and you don't want to hit the database every time. + +A tiny per-request cache solves this. Wrap the DB call in a small service: + +```php +final class SlugProvider +{ + /** @var array */ + private array $cache = []; + + public function __construct( + private Nette\Database\Explorer $db, + ) { + } + + public function getSlug(int $id): string + { + return $this->cache[$id] ??= Strings::webalize(Strings::truncate( + (string) $this->db->fetchField('SELECT title FROM article WHERE id = ?', $id), + 100, '' + )); + } +} +``` + +That's enough — one DB hit per unique ID per request. + + +Passing the Title from the Template (Optional Fast Path) +======================================================== + +When the title is already at hand in the template, you can skip the DB lookup entirely. Pass the title as a named parameter: + +```latte +{$article->title} +``` + +…and add a per-parameter `FilterOut` that turns the title into a URL-safe string: + +```php +$router->addRoute('article/[-]', [ + 'presenter' => 'Article', + 'action' => 'detail', + 'slug' => [ + Route::FilterOut => fn($title) => Strings::webalize(Strings::truncate($title, 100, '')), + ], + '' => [/* the lookup-fallback from above */], +]); +``` + +The two filters cooperate. The per-parameter `FilterOut` runs first and turns the supplied title into a slug. The general filter then sees the slug is already filled and skips the DB lookup. Templates that don't pass the title still work — they go through the lookup path. + +Use this only where it matters (large listings rendered hundreds of times per request). For most of the application the cached lookup is fast enough. + + +Canonization: Redirect to the Right URL +======================================= + +We can now generate `/article/123-how-to-bake-bread`, but the route still accepts `/article/123` and `/article/123-anything-someone-wrote`. That's deliberate — we want short URLs (more on that below) and we want old or hand-typed links to keep working. But we don't want search engines to index the same article under multiple addresses. + +The solution is [canonization |application:presenters#canonization]: when the user arrives via a non-canonical URL, the application 301-redirects them to the correct one. The `canonicalize()` method handles this: + +```php +public function actionDetail(int $id, ?string $slug = null): void +{ + $article = $this->facade->getArticle($id); + if (!$article) { + $this->error(); + } + + // generates the canonical URL through the same FilterOut + // and redirects with HTTP 301 if it differs from the current URL + $this->canonicalize('detail', ['id' => $id]); + + $this->template->article = $article; +} +``` + +`canonicalize()` generates the canonical URL the same way `link()` would (so it runs through the same `FilterOut`) and compares it to the current URL. If they differ, it redirects with HTTP 301. Visitors land on the right URL, search engines see only one canonical version. + + +One Place That Decides What the Slug Looks Like +=============================================== + +Notice that the `Strings::webalize(Strings::truncate(..., 100, ''))` call lives in a single place — inside `SlugProvider` (or the per-parameter `FilterOut`). The same logic produces the link in the template, the URL in `redirect()`, and the canonical form in `canonicalize()`. + +If you want to change the rules later (different length limit, different transliteration, stripping extra characters), you change one line. Without this, you'd risk `redirect()` generating `/article/123-how-to-bake-bread` while `canonicalize()` expects `/article/123-how-to-bake-bre` (because someone applied a different `truncate` length elsewhere), and the application would redirect in a loop. + + +Bonus: Short URLs Still Work +============================ + +Because the slug is optional, addresses without it still work: + +``` +/article/123 +``` + +This is useful for: +- **QR codes** — shorter URL means a less dense, more scannable code +- **SMS and chat** — fits in a tweet, looks tidy +- **Printed materials** — a short URL is faster to type + +When a user opens such a URL, `canonicalize()` 301-redirects them to the full version with the slug, so search engines still see only the canonical form. You can have shortness and SEO at the same time. + + +Summary +======= + +- Mask `[-]` makes the slug optional. The default `` doesn't match `/`; use `` only if you really want slashes in the slug. +- A general `FilterOut` under the `''` key looks the title up by ID — **no template changes anywhere in the application**. +- Wrap the lookup in a tiny per-request cache; one DB query per unique ID is plenty. +- Optionally, a per-parameter `FilterOut` lets templates pass the title directly and skip the lookup. +- `$this->canonicalize()` in the action redirects non-canonical URLs to the right one with HTTP 301. +- The slug formula (`webalize` + `truncate`) lives in one place — change it once, take effect everywhere. +- Short ID-only URLs keep working, which is handy for QR codes and SMS. + +You'll find more about filters and canonization in the [routing |application:routing#general-filters] and [presenters |application:presenters#canonization] documentation. diff --git a/best-practices/es/@home.texy b/best-practices/es/@home.texy index 6a6ee9df47..e8747088c6 100644 --- a/best-practices/es/@home.texy +++ b/best-practices/es/@home.texy @@ -42,7 +42,6 @@ General - [¿Por qué Nette usa la notación PascalCase para las constantes? |https://blog.nette.org/es/for-less-screaming-in-the-code] - [¿Por qué Nette no usa el sufijo Interface? |https://blog.nette.org/es/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: consejos para su uso |composer] -- [Consejos sobre editores y herramientas |editors-and-tools] - [Introducción a la programación orientada a objetos |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/es/editors-and-tools.texy b/best-practices/es/editors-and-tools.texy deleted file mode 100644 index 36d9c62866..0000000000 --- a/best-practices/es/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editores y herramientas -*********************** - -.[perex] -Puedes ser un programador competente, pero solo con buenas herramientas te convertirás en un maestro. En este capítulo encontrarás consejos sobre herramientas, editores y plugins importantes. - - -Editor IDE -========== - -Recomendamos encarecidamente utilizar un IDE completo para el desarrollo, como PhpStorm, NetBeans, VS Code, y no solo un editor de texto con soporte para PHP. La diferencia es realmente fundamental. No hay razón para conformarse con un simple editor que colorea la sintaxis pero no alcanza las capacidades de un IDE de primer nivel, que sugiere con precisión, detecta errores, puede refactorizar código y mucho más. Algunos IDE son de pago, otros incluso gratuitos. - -**NetBeans IDE** ya tiene soporte integrado para Nette, Latte y NEON. - -**PhpStorm**: instala estos plugins en `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: busca el plugin "Nette Latte + Neon" en el marketplace. - -También vincula Tracy con tu editor. Cuando se muestre una página de error, podrás hacer clic en los nombres de los archivos y se abrirán en el editor con el cursor en la línea correspondiente. Lee [cómo configurar el sistema|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan es una herramienta que detecta errores lógicos en el código antes de ejecutarlo. - -Lo instalamos usando Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Creamos un archivo de configuración `phpstan.neon` en el proyecto: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Y luego le pedimos que analice las clases en la carpeta `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Encontrarás documentación exhaustiva directamente en el [sitio web de PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] comprueba y, opcionalmente, corrige algunos de los errores formales en tus códigos fuente: - -- elimina [BOM |nette:glossary#BOM] -- comprueba la validez de las plantillas [Latte |latte:] -- comprueba la validez de los archivos `.neon`, `.php` y `.json` -- comprueba la presencia de [caracteres de control |nette:glossary#Caracteres de control] -- comprueba si el archivo está codificado en UTF-8 -- comprueba `/* @anotaciones */` mal escritas (falta el asterisco) -- elimina el `?>` final de los archivos PHP -- elimina los espacios finales y las líneas innecesarias al final del archivo -- normaliza los separadores de línea a los del sistema (si se especifica la opción `-l`) - - -Composer -======== - -[Composer |Composer] es una herramienta para gestionar dependencias en PHP. Nos permite declarar dependencias arbitrariamente complejas de bibliotecas individuales y luego las instala por nosotros en nuestro proyecto. - - -Requirements Checker -==================== - -Era una herramienta que probaba el entorno de ejecución del servidor e informaba si (y en qué medida) se podía utilizar el framework. Actualmente, Nette se puede utilizar en cualquier servidor que tenga la versión mínima requerida de PHP. diff --git a/best-practices/fr/@home.texy b/best-practices/fr/@home.texy index 829741034c..a81b037dcf 100644 --- a/best-practices/fr/@home.texy +++ b/best-practices/fr/@home.texy @@ -42,7 +42,6 @@ Général - [Pourquoi Nette utilise la notation PascalCase pour les constantes ? |https://blog.nette.org/fr/for-less-screaming-in-the-code] - [Pourquoi Nette n'utilise pas le suffixe Interface ? |https://blog.nette.org/fr/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer : conseils d'utilisation |composer] -- [Conseils sur les éditeurs & outils |editors-and-tools] - [Introduction à la programmation orientée objet |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/fr/editors-and-tools.texy b/best-practices/fr/editors-and-tools.texy deleted file mode 100644 index f80342f3fe..0000000000 --- a/best-practices/fr/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Éditeurs & Outils -***************** - -.[perex] -Vous pouvez être un programmeur compétent, mais ce n'est qu'avec de bons outils que vous deviendrez un maître. Dans ce chapitre, vous trouverez des conseils sur les outils, éditeurs et plugins importants. - - -Éditeur IDE -=========== - -Nous recommandons vivement d'utiliser un IDE complet pour le développement, tel que PhpStorm, NetBeans, VS Code, et pas seulement un éditeur de texte avec prise en charge PHP. La différence est vraiment fondamentale. Il n'y a aucune raison de se contenter d'un simple éditeur qui colore la syntaxe mais n'atteint pas les capacités d'un IDE de pointe, qui suggère précisément, surveille les erreurs, peut refactoriser le code et bien plus encore. Certains IDE sont payants, d'autres sont même gratuits. - -**NetBeans IDE** intègre déjà la prise en charge de Nette, Latte et NEON. - -**PhpStorm** : installez ces plugins dans `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code** : trouvez le plugin "Nette Latte + Neon" dans le marketplace. - -Connectez également Tracy à votre éditeur. Lorsque la page d'erreur s'affiche, vous pourrez cliquer sur les noms de fichiers et ils s'ouvriront dans l'éditeur avec le curseur sur la ligne correspondante. Lisez [comment configurer le système|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan est un outil qui détecte les erreurs logiques dans le code avant même de l'exécuter. - -Nous l'installons à l'aide de Composer : - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Nous créons un fichier de configuration `phpstan.neon` dans le projet : - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Et ensuite, nous le laissons analyser les classes dans le dossier `app/` : - -```shell -vendor/bin/phpstan analyse app -``` - -Vous trouverez une documentation exhaustive directement sur le [site web de PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] vérifie et corrige éventuellement certaines erreurs formelles dans vos codes sources : - -- supprime le [BOM |nette:glossary#BOM] -- vérifie la validité des templates [Latte |latte:] -- vérifie la validité des fichiers `.neon`, `.php` et `.json` -- vérifie la présence de [caractères de contrôle |nette:glossary#Caractères de contrôle] -- vérifie si le fichier est encodé en UTF-8 -- vérifie les `/* @anotace */` mal écrites (manque une étoile) -- supprime les `?>` de fin dans les fichiers PHP -- supprime les espaces de fin de ligne et les lignes vides inutiles à la fin du fichier -- normalise les séparateurs de ligne en séparateurs système (si vous spécifiez l'option `-l`) - - -Composer -======== - -[Composer |best-practices:composer] est un outil de gestion des dépendances en PHP. Il nous permet de déclarer des dépendances arbitrairement complexes de différentes bibliothèques et les installe ensuite pour nous dans notre projet. - - -Requirements Checker -==================== - -C'était un outil qui testait l'environnement d'exécution du serveur et informait si (et dans quelle mesure) le framework pouvait être utilisé. Actuellement, Nette peut être utilisé sur n'importe quel serveur disposant de la version minimale requise de PHP. diff --git a/best-practices/hu/@home.texy b/best-practices/hu/@home.texy index e1ab1cabd8..e3118f3835 100644 --- a/best-practices/hu/@home.texy +++ b/best-practices/hu/@home.texy @@ -42,7 +42,6 @@ Nette Alkalmazások - [Miért használja a Nette a PascalCase konstans jelölést? |https://blog.nette.org/hu/for-less-screaming-in-the-code] - [Miért nem használja a Nette az Interface utótagot? |https://blog.nette.org/hu/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: használati tippek |composer] -- [Tippek szerkesztőkhöz & eszközökhöz |editors-and-tools] - [Bevezetés az objektumorientált programozásba |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/hu/editors-and-tools.texy b/best-practices/hu/editors-and-tools.texy deleted file mode 100644 index 7104666da7..0000000000 --- a/best-practices/hu/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Szerkesztők és eszközök -*********************** - -.[perex] -Lehetsz ügyes programozó, de csak jó eszközökkel válsz mesterré. Ebben a fejezetben tippeket találsz fontos eszközökhöz, szerkesztőkhöz és bővítményekhez. - - -IDE szerkesztő -============== - -Határozottan javasoljuk, hogy a fejlesztéshez teljes értékű IDE-t használj, mint például a PhpStorm, NetBeans, VS Code, és ne csak egy PHP támogatással rendelkező szövegszerkesztőt. A különbség valóban alapvető. Nincs ok megelégedni egy egyszerű szerkesztővel, amely ugyan tudja színezni a szintaxist, de nem éri el egy csúcskategóriás IDE képességeit, amely pontosan súg, figyeli a hibákat, képes refaktorálni a kódot és sok minden mást. Néhány IDE fizetős, mások pedig ingyenesek. - -A **NetBeans IDE** beépített támogatással rendelkezik a Nette, Latte és NEON számára. - -**PhpStorm**: telepítsd ezeket a bővítményeket a `Settings > Plugins > Marketplace` menüpontban: -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: keresd meg a marketplace-en a "Nette Latte + Neon" bővítményt. - -Kapcsold össze a Tracy-t is a szerkesztővel. Amikor egy hibaoldal jelenik meg, rákattinthatsz a fájlnevekre, és azok megnyílnak a szerkesztőben a megfelelő sorra állított kurzorral. Olvasd el, [hogyan konfiguráld a rendszert |tracy:open-files-in-ide]. - - -PHPStan -======= - -A PHPStan egy eszköz, amely logikai hibákat tár fel a kódban, mielőtt futtatnád azt. - -Telepítsük a Composer segítségével: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Hozzunk létre egy konfigurációs fájlt a projektben `phpstan.neon` néven: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Majd futtassuk az elemzést az `app/` mappában lévő osztályokon: - -```shell -vendor/bin/phpstan analyse app -``` - -Kimerítő dokumentációt találsz közvetlenül a [PHPStan oldalán |https://phpstan.org]. - - -Code Checker -============ - -A [Code Checker|code-checker:] ellenőrzi és szükség esetén kijavítja a forráskódok néhány formai hibáját: - -- eltávolítja a [BOM |nette:glossary#BOM]-ot -- ellenőrzi a [Latte |latte:] sablonok érvényességét -- ellenőrzi a `.neon`, `.php` és `.json` fájlok érvényességét -- ellenőrzi a [vezérlőkarakterek |nette:glossary#Vezérlő karakterek] előfordulását -- ellenőrzi, hogy a fájl UTF-8 kódolású-e -- ellenőrzi a hibásan írt `/* @anotace */` (hiányzik a csillag) -- eltávolítja a záró `?>` PHP fájlokból -- eltávolítja a jobb oldali szóközöket és a felesleges sorokat a fájl végéről -- normalizálja a sorelválasztókat a rendszer alapértelmezettjére (ha megadja a `-l` opciót) - - -Composer -======== - -A [Composer |best-practices:composer] egy függőségkezelő eszköz PHP-hez. Lehetővé teszi számunkra, hogy tetszőlegesen összetett függőségeket deklaráljunk az egyes könyvtárakhoz, majd telepíti őket a projektünkbe. - - -Requirements Checker -==================== - -Ez egy eszköz volt, amely tesztelte a szerver futási környezetét, és tájékoztatott arról, hogy (és milyen mértékben) lehet használni a keretrendszert. Jelenleg a Nette minden olyan szerveren használható, amely rendelkezik a minimálisan szükséges PHP verzióval. diff --git a/best-practices/it/@home.texy b/best-practices/it/@home.texy index 7a11feda65..d4cc303b8b 100644 --- a/best-practices/it/@home.texy +++ b/best-practices/it/@home.texy @@ -42,7 +42,6 @@ Generale - [Perché Nette usa la notazione PascalCase per le costanti? |https://blog.nette.org/it/for-less-screaming-in-the-code] - [Perché Nette non usa il suffisso Interface? |https://blog.nette.org/it/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: suggerimenti per l'uso |composer] -- [Suggerimenti per editor e strumenti |editors-and-tools] - [Introduzione alla programmazione orientata agli oggetti |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/it/editors-and-tools.texy b/best-practices/it/editors-and-tools.texy deleted file mode 100644 index 9386b93f8e..0000000000 --- a/best-practices/it/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editor e strumenti -****************** - -.[perex] -Potreste essere un programmatore esperto, ma solo con i buoni strumenti diventerete dei maestri. In questo capitolo troverete suggerimenti su strumenti, editor e plugin importanti. - - -Editor IDE -========== - -Consigliamo vivamente di utilizzare un IDE completo per lo sviluppo, come PhpStorm, NetBeans, VS Code, e non solo un editor di testo con supporto PHP. La differenza è davvero fondamentale. Non c'è motivo di accontentarsi di un semplice editor che colora la sintassi ma non raggiunge le capacità di un IDE di alto livello, che suggerisce con precisione, controlla gli errori, sa refattorizzare il codice e molto altro. Alcuni IDE sono a pagamento, altri addirittura gratuiti. - -**NetBeans IDE** ha il supporto per Nette, Latte e NEON già integrato. - -**PhpStorm**: installate questi plugin in `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: cercate nel marketplace il plugin "Nette Latte + Neon". - -Collegate anche Tracy all'editor. Quando viene visualizzata una pagina di errore, potrete cliccare sui nomi dei file e questi si apriranno nell'editor con il cursore sulla riga corrispondente. Leggete [come configurare il sistema|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan è uno strumento che rileva gli errori logici nel codice prima ancora di eseguirlo. - -Lo installiamo tramite Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Creiamo nel progetto il file di configurazione `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -E successivamente lo facciamo analizzare le classi nella cartella `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Troverete una documentazione esaustiva direttamente sul [sito web di PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] controlla ed eventualmente corregge alcuni errori formali nei vostri codici sorgente: - -- rimuove il [BOM |nette:glossary#BOM] -- controlla la validità dei template [Latte |latte:] -- controlla la validità dei file `.neon`, `.php` e `.json` -- controlla la presenza di [caratteri di controllo |nette:glossary#Caratteri di controllo] -- controlla se il file è codificato in UTF-8 -- controlla `/* @anotace */` scritti erroneamente (manca l'asterisco) -- rimuove il tag di chiusura `?>` dai file PHP -- rimuove gli spazi finali e le righe vuote alla fine del file -- normalizza i separatori di riga a quelli di sistema (se si specifica l'opzione `-l`) - - -Composer -======== - -[Composer |Composer] è uno strumento per la gestione delle dipendenze in PHP. Ci permette di dichiarare dipendenze arbitrariamente complesse tra le singole librerie e poi le installa per noi nel nostro progetto. - - -Requirements Checker -==================== - -Era uno strumento che testava l'ambiente di runtime del server e informava se (e in che misura) fosse possibile utilizzare il framework. Attualmente, Nette può essere utilizzato su qualsiasi server che abbia la versione minima richiesta di PHP. diff --git a/best-practices/ja/@home.texy b/best-practices/ja/@home.texy index eab0e604fe..12c1bd9707 100644 --- a/best-practices/ja/@home.texy +++ b/best-practices/ja/@home.texy @@ -42,7 +42,6 @@ Netteアプリケーション - [なぜ Nette は定数に PascalCase 記法を使用するのですか? |https://blog.nette.org/en/for-less-screaming-in-the-code] - [なぜ Nette は Interface 接尾辞を使用しないのですか? |https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: 使用のヒント |composer] -- [エディタとツールのヒント |editors-and-tools] - [オブジェクト指向プログラミング入門 |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/ja/editors-and-tools.texy b/best-practices/ja/editors-and-tools.texy deleted file mode 100644 index 36e72f6ea2..0000000000 --- a/best-practices/ja/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -エディタとツール -******** - -.[perex] -あなたは熟練したプログラマかもしれませんが、優れたツールがあってこそマスターになれます。この章では、重要なツール、エディタ、プラグインのヒントを紹介します。 - - -IDEエディタ -======= - -開発には、PhpStorm、NetBeans、VS Codeなどの本格的なIDEを使用することを強くお勧めします。単なるPHPサポート付きのテキストエディタだけではありません。違いは本当に決定的です。構文を色付けできるだけの単なるエディタで満足する理由はありません。それは、正確なヒントを提供し、エラーを監視し、コードをリファクタリングし、その他多くのことができるトップクラスのIDEの能力には及びません。一部のIDEは有料ですが、無料のものもあります。 - -**NetBeans IDE** は、Nette、Latte、NEONのサポートを組み込みで持っています。 - -**PhpStorm**: `Settings > Plugins > Marketplace` でこれらのプラグインをインストールしてください -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: マーケットプレイスで "Nette Latte + Neon" プラグインを見つけてください。 - -また、Tracyをエディタと連携させてください。エラーページが表示されたときに、ファイル名をクリックすると、エディタで該当する行にカーソルがある状態で開くことができます。[システムの設定方法|tracy:open-files-in-ide] を読んでください。 - - -PHPStan -======= - -PHPStanは、コードを実行する前に論理エラーを検出するツールです。 - -Composerを使用してインストールします: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -プロジェクトに設定ファイル `phpstan.neon` を作成します: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -そして、`app/` フォルダ内のクラスを分析させます: - -```shell -vendor/bin/phpstan analyse app -``` - -包括的なドキュメントは、[PHPStanのサイト |https://phpstan.org] で直接見つけることができます。 - - -Code Checker -============ - -[Code Checker|code-checker:] は、ソースコード内の一部の形式的なエラーをチェックし、場合によっては修正します: - -- [BOM |nette:glossary#BOM] を削除します -- [Latte |latte:] テンプレートの有効性をチェックします -- `.neon`、`.php`、`.json` ファイルの有効性をチェックします -- [制御文字 |nette:glossary#制御文字] の出現をチェックします -- ファイルがUTF-8でエンコードされているかチェックします -- 誤って書かれた `/* @anotace */` (アスタリスクが欠けている)をチェックします -- PHPファイルの終了タグ `?>` を削除します -- ファイルの末尾にある右側のスペースや不要な行を削除します -- `-l` オプションを指定した場合、行区切り文字をシステムのものに正規化します - - -Composer -======== - -[Composer |best-practices:composer] はPHPの依存関係管理ツールです。これにより、個々のライブラリの任意の複雑な依存関係を宣言し、それらをプロジェクトにインストールすることができます。 - - -Requirements Checker -==================== - -これは、サーバーの実行環境をテストし、フレームワークを使用できるかどうか(およびどの程度まで)を通知するツールでした。現在、Netteは最小限必要なPHPバージョンを持つすべてのサーバーで使用できます。 diff --git a/best-practices/pl/@home.texy b/best-practices/pl/@home.texy index 64470576e1..1f1d0231b0 100644 --- a/best-practices/pl/@home.texy +++ b/best-practices/pl/@home.texy @@ -42,7 +42,6 @@ Ogólne - [Dlaczego Nette używa notacji PascalCase dla stałych? |https://blog.nette.org/pl/for-less-screaming-in-the-code] - [Dlaczego Nette nie używa przyrostka Interface? |https://blog.nette.org/pl/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: wskazówki dotyczące użycia |composer] -- [Wskazówki dotyczące edytorów i narzędzi |editors-and-tools] - [Wprowadzenie do programowania obiektowego |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/pl/editors-and-tools.texy b/best-practices/pl/editors-and-tools.texy deleted file mode 100644 index 7488231779..0000000000 --- a/best-practices/pl/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Edytory i narzędzia -******************* - -.[perex] -Możesz być biegłym programistą, ale dopiero z dobrymi narzędziami staniesz się mistrzem. W tym rozdziale znajdziesz wskazówki dotyczące ważnych narzędzi, edytorów i wtyczek. - - -Edytor IDE -========== - -Zdecydowanie zalecamy używanie do programowania pełnoprawnego IDE, takiego jak PhpStorm, NetBeans, VS Code, a nie tylko edytora tekstu z obsługą PHP. Różnica jest naprawdę zasadnicza. Nie ma powodu zadowalać się zwykłym edytorem, który co prawda potrafi kolorować składnię, ale nie dorównuje możliwościom zaawansowanego IDE, które precyzyjnie podpowiada, pilnuje błędów, potrafi refaktoryzować kod i wiele więcej. Niektóre IDE są płatne, inne nawet darmowe. - -**NetBeans IDE** ma wbudowane wsparcie dla Nette, Latte i NEON. - -**PhpStorm**: zainstaluj te wtyczki w `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: znajdź w marketplace wtyczkę "Nette Latte + Neon". - -Połącz również Tracy z edytorem. Podczas wyświetlania strony błędu będzie można kliknąć na nazwy plików, a te otworzą się w edytorze z kursorem na odpowiedniej linii. Przeczytaj, [jak skonfigurować system|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan to narzędzie, które wykrywa błędy logiczne w kodzie, zanim go uruchomisz. - -Zainstalujemy go za pomocą Composera: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Utworzymy w projekcie plik konfiguracyjny `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -A następnie zlecimy mu analizę klas w folderze `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Wyczerpującą dokumentację znajdziesz bezpośrednio na [stronie PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] sprawdza i ewentualnie poprawia niektóre błędy formalne w twoich kodach źródłowych: - -- usuwa [BOM |nette:glossary#BOM] -- sprawdza poprawność szablonów [Latte |latte:] -- sprawdza poprawność plików `.neon`, `.php` i `.json` -- sprawdza występowanie [znaków kontrolnych |nette:glossary#Znaki kontrolne] -- sprawdza, czy plik jest kodowany w UTF-8 -- sprawdza błędnie zapisane `/* @anotace */` (brakuje gwiazdki) -- usuwa kończące `?>` w plikach PHP -- usuwa spacje na końcu linii i zbędne linie na końcu pliku -- normalizuje separatory linii do systemowych (jeśli podasz opcję `-l`) - - -Composer -======== - -[Composer|best-practices:composer] to narzędzie do zarządzania zależnościami w PHP. Pozwala nam deklarować dowolnie złożone zależności poszczególnych bibliotek, a następnie instaluje je za nas w naszym projekcie. - - -Requirements Checker -==================== - -Było to narzędzie, które testowało środowisko uruchomieniowe serwera i informowało, czy (i w jakim stopniu) można używać frameworka. Obecnie Nette można używać na każdym serwerze, który ma minimalną wymaganą wersję PHP. diff --git a/best-practices/pt/@home.texy b/best-practices/pt/@home.texy index ff77ce2b7f..3deee7f759 100644 --- a/best-practices/pt/@home.texy +++ b/best-practices/pt/@home.texy @@ -42,7 +42,6 @@ Geral - [Por que o Nette usa a notação PascalCase para constantes? |https://blog.nette.org/pt/for-less-screaming-in-the-code] - [Por que o Nette não usa o sufixo Interface? |https://blog.nette.org/pt/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: dicas de uso |composer] -- [Dicas sobre editores & ferramentas |editors-and-tools] - [Introdução à programação orientada a objetos |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/pt/editors-and-tools.texy b/best-practices/pt/editors-and-tools.texy deleted file mode 100644 index 6d841136f7..0000000000 --- a/best-practices/pt/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editores & Ferramentas -********************** - -.[perex] -Você pode ser um programador habilidoso, mas é com boas ferramentas que você se torna um mestre. Neste capítulo, você encontrará dicas sobre ferramentas importantes, editores e plugins. - - -Editor IDE -========== - -Recomendamos fortemente o uso de um IDE completo para desenvolvimento, como PhpStorm, NetBeans, VS Code, e não apenas um editor de texto com suporte a PHP. A diferença é realmente fundamental. Não há razão para se contentar com um simples editor que, embora possa colorir a sintaxe, não atinge as capacidades de um IDE de ponta, que sugere com precisão, monitora erros, pode refatorar código e muito mais. Alguns IDEs são pagos, outros são até gratuitos. - -**NetBeans IDE** já vem com suporte integrado para Nette, Latte e NEON. - -**PhpStorm**: instale estes plugins em `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: encontre o plugin "Nette Latte + Neon" no marketplace. - -Conecte também o Tracy ao seu editor. Ao exibir uma página de erro, você poderá clicar nos nomes dos arquivos e eles serão abertos no editor com o cursor na linha correspondente. Leia [como configurar o sistema|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan é uma ferramenta que detecta erros lógicos no código antes mesmo de você executá-lo. - -Instalamos usando o Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Criamos um arquivo de configuração `phpstan.neon` no projeto: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -E, em seguida, deixamos que ele analise as classes na pasta `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Você encontrará documentação completa diretamente no [site do PHPStan |https://phpstan.org]. - - -Code Checker -============ - -O [Code Checker|code-checker:] verifica e, opcionalmente, corrige alguns erros formais em seus códigos-fonte: - -- remove [BOM |nette:glossary#BOM] -- verifica a validade dos templates [Latte |latte:] -- verifica a validade dos arquivos `.neon`, `.php` e `.json` -- verifica a ocorrência de [caracteres de controle |nette:glossary#Caracteres de controle] -- verifica se o arquivo está codificado em UTF-8 -- verifica `/* @anotações */` escritas incorretamente (falta um asterisco) -- remove `?>` de fechamento em arquivos PHP -- remove espaços em branco à direita e linhas desnecessárias no final do arquivo -- normaliza os separadores de linha para os do sistema (se você usar a opção `-l`) - - -Composer -======== - -[Composer|best-practices:composer] é uma ferramenta para gerenciamento de dependências em PHP. Permite declarar dependências arbitrariamente complexas de bibliotecas individuais e, em seguida, as instala para nós em nosso projeto. - - -Requirements Checker -==================== - -Era uma ferramenta que testava o ambiente de execução do servidor e informava se (e em que medida) o framework poderia ser usado. Atualmente, o Nette pode ser usado em qualquer servidor que tenha a versão mínima exigida do PHP. diff --git a/best-practices/ro/@home.texy b/best-practices/ro/@home.texy index a742e5d015..13cd0f4a31 100644 --- a/best-practices/ro/@home.texy +++ b/best-practices/ro/@home.texy @@ -42,7 +42,6 @@ Generale - [De ce Nette utilizează notația PascalCase pentru constante? |https://blog.nette.org/ro/for-less-screaming-in-the-code] - [De ce Nette nu utilizează sufixul Interface? |https://blog.nette.org/ro/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: sfaturi de utilizare |composer] -- [Sfaturi pentru editori & instrumente |editors-and-tools] - [Introducere în programarea orientată pe obiecte |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/ro/editors-and-tools.texy b/best-practices/ro/editors-and-tools.texy deleted file mode 100644 index 7c44d258a6..0000000000 --- a/best-practices/ro/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editoare & instrumente -********************** - -.[perex] -Poți fi un programator priceput, dar numai cu instrumentele potrivite devii un maestru. În acest capitol vei găsi sfaturi despre instrumente, editoare și plugin-uri importante. - - -Editor IDE -========== - -Recomandăm cu tărie utilizarea unui IDE complet pentru dezvoltare, cum ar fi PhpStorm, NetBeans, VS Code, și nu doar un editor de text cu suport pentru PHP. Diferența este cu adevărat fundamentală. Nu există niciun motiv să te mulțumești cu un simplu editor care colorează sintaxa, dar nu atinge capacitățile unui IDE de top, care oferă sugestii precise, verifică erorile, poate refactoriza codul și multe altele. Unele IDE-uri sunt plătite, altele sunt chiar gratuite. - -**NetBeans IDE** are suport încorporat pentru Nette, Latte și NEON. - -**PhpStorm**: instalează aceste plugin-uri în `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: găsește pluginul "Nette Latte + Neon" în marketplace. - -Conectează, de asemenea, Tracy la editor. Când se afișează pagina de eroare, vei putea da clic pe numele fișierelor și acestea se vor deschide în editor cu cursorul pe linia corespunzătoare. Citește [cum să configurezi sistemul |tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan este un instrument care detectează erorile logice din cod înainte de a-l rula. - -Îl instalăm folosind Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Creăm în proiect fișierul de configurare `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Și apoi îl lăsăm să analizeze clasele din directorul `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Documentația exhaustivă o găsiți direct pe [site-ul PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker |code-checker:] verifică și, eventual, corectează unele dintre erorile formale din codurile sursă: - -- elimină [BOM |nette:glossary#BOM] -- verifică validitatea șabloanelor [Latte |latte:] -- verifică validitatea fișierelor `.neon`, `.php` și `.json` -- verifică prezența [caracterelor de control |nette:glossary#Caractere de control] -- verifică dacă fișierul este codificat în UTF-8 -- verifică `/* @anotace */` scrise incorect (lipsește asteriscul) -- elimină `?>` de închidere din fișierele PHP -- elimină spațiile de la sfârșitul rândului și rândurile goale inutile de la sfârșitul fișierului -- normalizează delimitatorii de rând la cei de sistem (dacă specificați opțiunea `-l`) - - -Composer -======== - -[Composer |best-practices:composer] este un instrument pentru gestionarea dependențelor în PHP. Ne permite să declarăm dependențe oricât de complexe ale diferitelor biblioteci și apoi le instalează pentru noi în proiectul nostru. - - -Requirements Checker -==================== - -Acesta a fost un instrument care testa mediul de rulare al serverului și informa dacă (și în ce măsură) framework-ul poate fi utilizat. În prezent, Nette poate fi utilizat pe orice server care are versiunea minimă necesară de PHP. diff --git a/best-practices/ru/@home.texy b/best-practices/ru/@home.texy index 1ea3ce7e1e..07d421647a 100644 --- a/best-practices/ru/@home.texy +++ b/best-practices/ru/@home.texy @@ -42,7 +42,6 @@ - [Почему Nette использует PascalCase нотацию для констант? |https://blog.nette.org/ru/for-less-screaming-in-the-code] - [Почему Nette не использует суффикс Interface? |https://blog.nette.org/ru/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: советы по использованию |composer] -- [Советы по редакторам и инструментам |editors-and-tools] - [Введение в объектно-ориентированное программирование |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/ru/editors-and-tools.texy b/best-practices/ru/editors-and-tools.texy deleted file mode 100644 index 7508f40017..0000000000 --- a/best-practices/ru/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Редакторы и инструменты -*********************** - -.[perex] -Вы можете быть опытным программистом, но только с хорошими инструментами вы станете мастером. В этой главе вы найдете советы по важным инструментам, редакторам и плагинам. - - -IDE редактор -============ - -Мы настоятельно рекомендуем использовать для разработки полноценную IDE, такую как PhpStorm, NetBeans, VS Code, а не просто текстовый редактор с поддержкой PHP. Разница действительно существенная. Нет причин довольствоваться простым редактором, который хоть и умеет подсвечивать синтаксис, но не достигает возможностей передовой IDE, которая точно подсказывает, отслеживает ошибки, умеет рефакторить код и многое другое. Некоторые IDE платные, другие даже бесплатные. - -**NetBeans IDE** имеет встроенную поддержку Nette, Latte и NEON. - -**PhpStorm**: установите эти плагины в `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: найдите в marketplace плагин "Nette Latte + Neon". - -Также свяжите Tracy с редактором. При отображении страницы ошибки можно будет кликнуть на имена файлов, и они откроются в редакторе с курсором на соответствующей строке. Прочтите, [как настроить систему|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan — это инструмент, который обнаруживает логические ошибки в коде до его запуска. - -Установим его с помощью Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Создадим в проекте конфигурационный файл `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -А затем позволим ему проанализировать классы в папке `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Исчерпывающую документацию вы найдете прямо на [сайте PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] проверяет и, при необходимости, исправляет некоторые формальные ошибки в ваших исходных кодах: - -- удаляет [BOM |nette:glossary#BOM] -- проверяет валидность шаблонов [Latte |latte:] -- проверяет валидность файлов `.neon`, `.php` и `.json` -- проверяет наличие [контрольных символов |nette:glossary#Управляющие символы] -- проверяет, закодирован ли файл в UTF-8 -- проверяет неправильно записанные `/* @anotace */` (отсутствует звездочка) -- удаляет завершающие `?>` в PHP файлах -- удаляет пробелы в конце строк и лишние строки в конце файла -- нормализует разделители строк к системным (если указана опция `-l`) - - -Composer -======== - -[Composer] — это инструмент для управления зависимостями в PHP. Он позволяет нам объявлять произвольно сложные зависимости отдельных библиотек и затем устанавливает их для нас в наш проект. - - -Requirements Checker -==================== - -Это был инструмент, который тестировал среду выполнения сервера и сообщал, можно ли (и в какой степени) использовать фреймворк. В настоящее время Nette можно использовать на любом сервере, имеющем минимально требуемую версию PHP. diff --git a/best-practices/sl/@home.texy b/best-practices/sl/@home.texy index a4cf0efbec..930d03f006 100644 --- a/best-practices/sl/@home.texy +++ b/best-practices/sl/@home.texy @@ -42,7 +42,6 @@ Splošno - [Zakaj Nette uporablja PascalCase notacijo konstant? |https://blog.nette.org/sl/for-less-screaming-in-the-code] - [Zakaj Nette ne uporablja pripone Interface? |https://blog.nette.org/sl/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: nasveti za uporabo |composer] -- [Nasveti za urejevalnike & orodja |editors-and-tools] - [Uvod v objektno orientirano programiranje |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/sl/editors-and-tools.texy b/best-practices/sl/editors-and-tools.texy deleted file mode 100644 index 9ac5d2ff3c..0000000000 --- a/best-practices/sl/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Urejevalniki & orodja -********************* - -.[perex] -Lahko ste spreten programer, vendar šele z dobrimi orodji postanete mojster. V tem poglavju boste našli nasvete za pomembna orodja, urejevalnike in vtičnike. - - -IDE urejevalnik -=============== - -Vsekakor priporočamo, da za razvoj uporabljate polnopravno IDE, kot so na primer PhpStorm, NetBeans, VS Code, in ne le urejevalnika besedil s podporo za PHP. Razlika je resnično bistvena. Ni razloga, da bi se zadovoljili zgolj z urejevalnikom, ki sicer zna obarvati sintakso, vendar ne dosega zmožnosti vrhunskega IDE-ja, ki natančno predlaga, preverja napake, zna refaktorirati kodo in še veliko več. Nekateri IDE-ji so plačljivi, drugi celo brezplačni. - -**NetBeans IDE** ima podporo za Nette, Latte in NEON že vgrajeno. - -**PhpStorm**: namestite te vtičnike v `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: v tržnici (marketplace) poiščite vtičnik "Nette Latte + Neon". - -Povežite tudi Tracy z urejevalnikom. Pri prikazu strani z napako bo potem mogoče klikniti na imena datotek, ki se bodo odprla v urejevalniku s kazalcem na ustrezni vrstici. Preberite, [kako konfigurirati sistem|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan je orodje, ki odkrije logične napake v kodi, preden jo zaženete. - -Namestimo ga s pomočjo Composerja: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -V projektu ustvarimo konfiguracijsko datoteko `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Nato pustimo, da analizira razrede v mapi `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Izčrpno dokumentacijo najdete neposredno na [straneh PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] preveri in po potrebi popravi nekatere formalne napake v vaši izvorni kodi: - -- odstranjuje [BOM |nette:glossary#BOM] -- preverja veljavnost predlog [Latte |latte:] -- preverja veljavnost datotek `.neon`, `.php` in `.json` -- preverja pojav [kontrolnih znakov |nette:glossary#Kontrolni znaki] -- preverja, ali je datoteka kodirana v UTF-8 -- preverja napačno zapisane `/* @anotacije */` (manjka zvezdica) -- odstranjuje zaključno oznako `?>` pri PHP datotekah -- odstranjuje presledke na desni strani in nepotrebne vrstice na koncu datoteke -- normalizira ločila vrstic na sistemska (če navedete možnost `-l`) - - -Composer -======== - -[Composer |best-practices:composer] je orodje za upravljanje odvisnosti v PHP. Omogoča nam deklariranje poljubno zapletenih odvisnosti posameznih knjižnic in jih nato za nas namesti v naš projekt. - - -Requirements Checker -==================== - -To je bilo orodje, ki je testiralo izvajalno okolje strežnika in obveščalo, ali (in v kolikšni meri) je mogoče ogrodje uporabljati. Trenutno je Nette mogoče uporabljati na vsakem strežniku, ki ima minimalno zahtevano različico PHP. diff --git a/best-practices/tr/@home.texy b/best-practices/tr/@home.texy index c8b90b9e40..095c54c8f0 100644 --- a/best-practices/tr/@home.texy +++ b/best-practices/tr/@home.texy @@ -42,7 +42,6 @@ Genel - [Nette neden PascalCase sabit gösterimini kullanıyor? |https://blog.nette.org/tr/for-less-screaming-in-the-code] - [Nette neden Interface son ekini kullanmıyor? |https://blog.nette.org/tr/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: kullanım ipuçları |composer] -- [Düzenleyiciler ve araçlar için ipuçları |editors-and-tools] - [Nesne yönelimli programlamaya giriş |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/tr/editors-and-tools.texy b/best-practices/tr/editors-and-tools.texy deleted file mode 100644 index e1822a4311..0000000000 --- a/best-practices/tr/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Editörler & Araçlar -******************* - -.[perex] -Yetenekli bir programcı olabilirsiniz, ancak ancak iyi araçlarla bir usta olursunuz. Bu bölümde önemli araçlar, editörler ve eklentiler hakkında ipuçları bulacaksınız. - - -IDE Editörü -=========== - -Geliştirme için kesinlikle PhpStorm, NetBeans, VS Code gibi tam özellikli bir IDE kullanmanızı öneririz, sadece PHP desteği olan bir metin editörü değil. Fark gerçekten çok büyük. Sadece sözdizimini renklendirebilen, ancak tam olarak ipucu veren, hataları kontrol eden, kodu yeniden düzenleyebilen ve çok daha fazlasını yapabilen birinci sınıf bir IDE'nin yeteneklerine ulaşamayan bir editörle yetinmek için hiçbir neden yok. Bazı IDE'ler ücretlidir, diğerleri ise ücretsizdir. - -**NetBeans IDE** Nette, Latte ve NEON desteği zaten yerleşiktir. - -**PhpStorm**: `Settings > Plugins > Marketplace` bölümünden şu eklentileri yükleyin -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: marketplace'te "Nette Latte + Neon" eklentisini bulun. - -Ayrıca Tracy'yi editörünüzle bağlayın. Hata sayfası görüntülendiğinde, dosya adlarına tıklayabilir ve bunlar editörde ilgili satırda imleçle açılır. [Sistemi nasıl yapılandıracağınızı |tracy:open-files-in-ide] okuyun. - - -PHPStan -======= - -PHPStan, kodu çalıştırmadan önce mantıksal hataları ortaya çıkaran bir araçtır. - -Composer kullanarak kurarız: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Projede `phpstan.neon` yapılandırma dosyasını oluştururuz: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -Ve ardından `app/` klasöründeki sınıfları analiz etmesini sağlarız: - -```shell -vendor/bin/phpstan analyse app -``` - -Kapsamlı belgeleri doğrudan [PHPStan web sitesinde |https://phpstan.org] bulabilirsiniz. - - -Code Checker -============ - -[Code Checker|code-checker:] kaynak kodlarınızdaki bazı biçimsel hataları kontrol eder ve gerekirse düzeltir: - -- [BOM |nette:glossary#BOM] kaldırır -- [Latte |latte:] şablonlarının geçerliliğini kontrol eder -- `.neon`, `.php` ve `.json` dosyalarının geçerliliğini kontrol eder -- [kontrol karakterlerinin |nette:glossary#Kontrol Karakterleri] varlığını kontrol eder -- dosyanın UTF-8 olarak kodlanıp kodlanmadığını kontrol eder -- yanlış yazılmış `/* @anotace */` (yıldız eksik) kontrol eder -- PHP dosyalarındaki kapanış `?>` etiketini kaldırır -- dosya sonundaki sağdaki boşlukları ve gereksiz satırları kaldırır -- satır ayırıcılarını sistem varsayılanlarına normalleştirir (`-l` seçeneğini belirtirseniz) - - -Composer -======== - -[Composer |Composer] PHP'de bağımlılıkları yönetmek için bir araçtır. Bireysel kütüphanelerin keyfi olarak karmaşık bağımlılıklarını bildirmemize ve ardından bunları projemize kurmamıza olanak tanır. - - -Requirements Checker -==================== - -Sunucunun çalışma zamanı ortamını test eden ve framework'ün kullanılıp kullanılamayacağını (ve ne ölçüde) bildiren bir araçtı. Şu anda Nette, minimum gerekli PHP sürümüne sahip her sunucuda kullanılabilir. diff --git a/best-practices/uk/@home.texy b/best-practices/uk/@home.texy index f9d3510c2b..623e6f8453 100644 --- a/best-practices/uk/@home.texy +++ b/best-practices/uk/@home.texy @@ -42,7 +42,6 @@ - [Чому Nette використовує PascalCase нотацію констант? |https://blog.nette.org/uk/for-less-screaming-in-the-code] - [Чому Nette не використовує суфікс Interface? |https://blog.nette.org/uk/prefixes-and-suffixes-do-not-belong-in-interface-names] - [Composer: поради щодо використання |composer] -- [Поради щодо редакторів та інструментів |editors-and-tools] - [Вступ до об'єктно-орієнтованого програмування |nette:introduction-to-object-oriented-programming] diff --git a/best-practices/uk/editors-and-tools.texy b/best-practices/uk/editors-and-tools.texy deleted file mode 100644 index 86380ff279..0000000000 --- a/best-practices/uk/editors-and-tools.texy +++ /dev/null @@ -1,84 +0,0 @@ -Редактори та інструменти -************************ - -.[perex] -Ви можете бути вправним програмістом, але лише з хорошими інструментами ви станете майстром. У цьому розділі ви знайдете поради щодо важливих інструментів, редакторів та плагінів. - - -IDE редактор -============ - -Ми наполегливо рекомендуємо використовувати для розробки повноцінне IDE, таке як PhpStorm, NetBeans, VS Code, а не просто текстовий редактор з підтримкою PHP. Різниця справді суттєва. Немає причин задовольнятися простим редактором, який хоч і вміє підсвічувати синтаксис, але не досягає можливостей топового IDE, яке точно підказує, відстежує помилки, вміє рефакторити код та багато іншого. Деякі IDE платні, інші навіть безкоштовні. - -**NetBeans IDE** має вбудовану підтримку Nette, Latte та NEON. - -**PhpStorm**: встановіть ці плагіни в `Settings > Plugins > Marketplace` -- Nette framework helpers -- Latte -- NEON support -- Nette Tester - -**VS Code**: знайдіть у marketplace плагін "Nette Latte + Neon". - -Також зв'яжіть Tracy з редактором. При відображенні сторінки помилки можна буде клікнути на імена файлів, і вони відкриються в редакторі з курсором на відповідному рядку. Прочитайте, [як налаштувати систему|tracy:open-files-in-ide]. - - -PHPStan -======= - -PHPStan — це інструмент, який виявляє логічні помилки в коді ще до його запуску. - -Встановимо його за допомогою Composer: - -```shell -composer require --dev phpstan/phpstan-nette -``` - -Створимо в проекті конфігураційний файл `phpstan.neon`: - -```neon -includes: - - vendor/phpstan/phpstan-nette/extension.neon - -parameters: - scanDirectories: - - app - - level: 5 -``` - -А потім запустимо аналіз класів у папці `app/`: - -```shell -vendor/bin/phpstan analyse app -``` - -Вичерпну документацію ви знайдете безпосередньо на [сайті PHPStan |https://phpstan.org]. - - -Code Checker -============ - -[Code Checker|code-checker:] перевіряє та, за потреби, виправляє деякі формальні помилки у ваших вихідних кодах: - -- видаляє [BOM |nette:glossary#BOM] -- перевіряє валідність шаблонів [Latte |latte:] -- перевіряє валідність файлів `.neon`, `.php` та `.json` -- перевіряє наявність [контрольних символів |nette:glossary#Керуючі символи] -- перевіряє, чи файл закодований у UTF-8 -- перевіряє помилково записані `/* @anotace */` (відсутня зірочка) -- видаляє завершальний `?>` у PHP файлах -- видаляє пробіли в кінці рядків та зайві рядки в кінці файлу -- нормалізує роздільники рядків до системних (якщо вказати опцію `-l`) - - -Composer -======== - -[Composer | Composer] — це інструмент для керування залежностями в PHP. Він дозволяє нам декларувати довільно складні залежності окремих бібліотек, а потім встановлює їх для нас у наш проект. - - -Requirements Checker -==================== - -Це був інструмент, який тестував середовище виконання сервера та інформував, чи (і якою мірою) можна використовувати фреймворк. На даний момент Nette можна використовувати на будь-якому сервері, який має мінімально необхідну версію PHP. diff --git a/bootstrap/bg/@home.texy b/bootstrap/bg/@home.texy index 3f9b20f4a1..675b61584a 100644 --- a/bootstrap/bg/@home.texy +++ b/bootstrap/bg/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Ако използвате целия framework, не е необходимо да правите нищо повече. В проекта имате подготвена директория `config/` за конфигурационните файлове и зареждането им се управлява от [зареждащото устройство на приложението |application:bootstrapping#Конфигурация на DI контейнера]. Тази статия е за потребители, които използват само една библиотека на Nette и искат да използват възможностите на конфигурационните файлове. -Конфигурационните файлове обикновено се записват във [формат NEON|neon:format] и най-добре се редактират в [редактори с неговата поддръжка |best-practices:editors-and-tools#IDE редактор]. Могат да се разглеждат като ръководства за **създаване и конфигуриране** на обекти. Следователно, резултатът от зареждането на конфигурацията ще бъде така наречената фабрика, която е обект, който по заявка ще ни създаде други обекти, които искаме да използваме. Например връзка с база данни и т.н. +Конфигурационните файлове обикновено се записват във [формат NEON|neon:format] и най-добре се редактират в [редактори с неговата поддръжка |tools:ide]. Могат да се разглеждат като ръководства за **създаване и конфигуриране** на обекти. Следователно, резултатът от зареждането на конфигурацията ще бъде така наречената фабрика, която е обект, който по заявка ще ни създаде други обекти, които искаме да използваме. Например връзка с база данни и т.н. Тази фабрика се нарича още *dependency injection контейнер* (DI container) и ако се интересувате от подробности, прочетете главата за [dependency injection |dependency-injection:]. diff --git a/bootstrap/cs/@home.texy b/bootstrap/cs/@home.texy index 9e3f2acaa6..fad72a0871 100644 --- a/bootstrap/cs/@home.texy +++ b/bootstrap/cs/@home.texy @@ -7,7 +7,7 @@ Jednotlivé součásti Nette nastavujeme pomocí konfiguračních souborů. Uká .[tip] Pokud používate celý framework, není potřeba nic dalšího dělat. V projektu máte pro konfigurační soubory předpřipravený adresář `config/` a jejich načítání má na starosti [zavaděč aplikace |application:bootstrapping#Konfigurace DI kontejneru]. Tento článek je pro uživatele, kteří používají jen jednu knihovnu Nette a chtějí využít možnosti konfiguračních souborů. -Konfigurační soubory se obvykle zapisují ve [formátu NEON|neon:format] a nejlépe se upravují v [editorech s jeho podporou |best-practices:editors-and-tools#IDE editor]. Lze je chápat jako návody, jak **vytvářet a konfigurovat** objekty. Tedy výsledkem načtení konfigurace bude tzv. továrna, což je objekt, který nám na požádání vytvoří další objekty, které chceme používat. Například databázové spojení apod. +Konfigurační soubory se obvykle zapisují ve [formátu NEON|neon:format] a nejlépe se upravují v [editorech s jeho podporou |tools:ide]. Lze je chápat jako návody, jak **vytvářet a konfigurovat** objekty. Tedy výsledkem načtení konfigurace bude tzv. továrna, což je objekt, který nám na požádání vytvoří další objekty, které chceme používat. Například databázové spojení apod. Této továrně se také říká *dependency injection kontejner* (DI container) a pokud by vás zajímaly podrobnosti, přečtěte si kapitolu o [dependency injection |dependency-injection:]. diff --git a/bootstrap/de/@home.texy b/bootstrap/de/@home.texy index 8f49650c62..82fe54e45b 100644 --- a/bootstrap/de/@home.texy +++ b/bootstrap/de/@home.texy @@ -7,7 +7,7 @@ Einzelne Nette-Komponenten werden über Konfigurationsdateien eingerichtet. Wir .[tip] Wenn Sie das gesamte Framework verwenden, müssen Sie nichts weiter tun. In Ihrem Projekt gibt es ein vorbereitetes Verzeichnis `config/` für Konfigurationsdateien, und deren Laden wird vom [Anwendungs-Bootstrap |application:bootstrapping#Konfiguration des DI-Containers] übernommen. Dieser Artikel richtet sich an Benutzer, die nur eine Nette-Bibliothek verwenden und die Möglichkeiten der Konfigurationsdateien nutzen möchten. -Konfigurationsdateien werden normalerweise im [NEON-Format|neon:format] geschrieben und am besten in [Editoren mit NEON-Unterstützung |best-practices:editors-and-tools#IDE-Editor] bearbeitet. Sie können als Anleitungen zum **Erstellen und Konfigurieren** von Objekten verstanden werden. Das Ergebnis des Ladens der Konfiguration ist also eine sogenannte Factory, ein Objekt, das auf Anfrage weitere Objekte erstellt, die wir verwenden möchten. Zum Beispiel eine Datenbankverbindung usw. +Konfigurationsdateien werden normalerweise im [NEON-Format|neon:format] geschrieben und am besten in [Editoren mit NEON-Unterstützung |tools:ide] bearbeitet. Sie können als Anleitungen zum **Erstellen und Konfigurieren** von Objekten verstanden werden. Das Ergebnis des Ladens der Konfiguration ist also eine sogenannte Factory, ein Objekt, das auf Anfrage weitere Objekte erstellt, die wir verwenden möchten. Zum Beispiel eine Datenbankverbindung usw. Dieser Factory wird auch *Dependency Injection Container* (DI-Container) genannt. Wenn Sie an Details interessiert sind, lesen Sie das Kapitel über [Dependency Injection |dependency-injection:]. diff --git a/bootstrap/el/@home.texy b/bootstrap/el/@home.texy index 8b4cf46446..9eaf9b36a0 100644 --- a/bootstrap/el/@home.texy +++ b/bootstrap/el/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Αν χρησιμοποιείτε ολόκληρο το framework, δεν χρειάζεται να κάνετε τίποτα άλλο. Στο έργο σας, έχετε έναν προετοιμασμένο κατάλογο `config/` για αρχεία διαμόρφωσης, και η φόρτωσή τους αναλαμβάνεται από τον [φορτωτή της εφαρμογής |application:bootstrapping#Διαμόρφωση του DI Container]. Αυτό το άρθρο είναι για χρήστες που χρησιμοποιούν μόνο μία βιβλιοθήκη Nette και θέλουν να εκμεταλλευτούν τις δυνατότητες των αρχείων διαμόρφωσης. -Τα αρχεία διαμόρφωσης συνήθως γράφονται σε [μορφή NEON |neon:format] και επεξεργάζονται καλύτερα σε [editors με υποστήριξη για αυτό |best-practices:editors-and-tools#IDE editor]. Μπορούν να θεωρηθούν ως οδηγίες για το πώς να **δημιουργείτε και να διαμορφώνετε** αντικείμενα. Έτσι, το αποτέλεσμα της φόρτωσης της διαμόρφωσης θα είναι ένα λεγόμενο factory, το οποίο είναι ένα αντικείμενο που, κατόπιν αιτήματος, θα δημιουργήσει άλλα αντικείμενα που θέλουμε να χρησιμοποιήσουμε. Για παράδειγμα, συνδέσεις βάσης δεδομένων κ.λπ. +Τα αρχεία διαμόρφωσης συνήθως γράφονται σε [μορφή NEON |neon:format] και επεξεργάζονται καλύτερα σε [editors με υποστήριξη για αυτό |tools:ide]. Μπορούν να θεωρηθούν ως οδηγίες για το πώς να **δημιουργείτε και να διαμορφώνετε** αντικείμενα. Έτσι, το αποτέλεσμα της φόρτωσης της διαμόρφωσης θα είναι ένα λεγόμενο factory, το οποίο είναι ένα αντικείμενο που, κατόπιν αιτήματος, θα δημιουργήσει άλλα αντικείμενα που θέλουμε να χρησιμοποιήσουμε. Για παράδειγμα, συνδέσεις βάσης δεδομένων κ.λπ. Αυτό το factory ονομάζεται επίσης *dependency injection container* (DI container) και αν σας ενδιαφέρουν οι λεπτομέρειες, διαβάστε το κεφάλαιο για το [dependency injection |dependency-injection:]. diff --git a/bootstrap/en/@home.texy b/bootstrap/en/@home.texy index 0e80ab16c2..ad053c85de 100644 --- a/bootstrap/en/@home.texy +++ b/bootstrap/en/@home.texy @@ -7,7 +7,7 @@ Individual Nette components are configured using configuration files. We will sh .[tip] If you are using the entire framework, there is no need to do anything else. Your project has a prepared `config/` directory for configuration files, and their loading is handled by the [application loader |application:bootstrapping#DI Container Configuration]. This article is for users who use only a single Nette library and want to take advantage of configuration files. -Configuration files are usually written in [NEON format|neon:format] and are best edited in [editors that support it |best-practices:editors-and-tools#IDE Editor]. They can be thought of as instructions on how to **create and configure** objects. Thus, the result of loading a configuration will be a so-called factory, which is an object that creates on demand other objects you want to use. For example, a database connection, etc. +Configuration files are usually written in [NEON format|neon:format] and are best edited in [editors that support it |tools:ide]. They can be thought of as instructions on how to **create and configure** objects. Thus, the result of loading a configuration will be a so-called factory, which is an object that creates on demand other objects you want to use. For example, a database connection, etc. This factory is also called a *dependency injection container* (DI container), and if you are interested in the details, read the chapter on [dependency injection |dependency-injection:]. diff --git a/bootstrap/es/@home.texy b/bootstrap/es/@home.texy index 25321bada6..e6b3068d34 100644 --- a/bootstrap/es/@home.texy +++ b/bootstrap/es/@home.texy @@ -7,7 +7,7 @@ Configuramos los componentes individuales de Nette usando archivos de configurac .[tip] Si está utilizando todo el framework, no necesita hacer nada más. En su proyecto, tiene un directorio `config/` preparado para archivos de configuración, y la [carga de la aplicación |application:bootstrapping#Configuración del contenedor DI] se encarga de cargarlos. Este artículo es para usuarios que utilizan solo una librería de Nette y desean aprovechar las capacidades de los archivos de configuración. -Los archivos de configuración generalmente se escriben en [formato NEON|neon:format] y se editan mejor en [editores con soporte para él |best-practices:editors-and-tools#Editor IDE]. Pueden verse como instrucciones sobre cómo **crear y configurar** objetos. Por lo tanto, el resultado de cargar la configuración será una llamada fábrica, que es un objeto que creará otros objetos que queremos usar bajo demanda. Por ejemplo, una conexión a la base de datos, etc. +Los archivos de configuración generalmente se escriben en [formato NEON|neon:format] y se editan mejor en [editores con soporte para él |tools:ide]. Pueden verse como instrucciones sobre cómo **crear y configurar** objetos. Por lo tanto, el resultado de cargar la configuración será una llamada fábrica, que es un objeto que creará otros objetos que queremos usar bajo demanda. Por ejemplo, una conexión a la base de datos, etc. Esta fábrica también se llama *contenedor de inyección de dependencias* (contenedor DI) y si está interesado en los detalles, lea el capítulo sobre [inyección de dependencias |dependency-injection:]. diff --git a/bootstrap/fr/@home.texy b/bootstrap/fr/@home.texy index 25f662ac6c..d3e9912a50 100644 --- a/bootstrap/fr/@home.texy +++ b/bootstrap/fr/@home.texy @@ -7,7 +7,7 @@ Les composants individuels de Nette sont configurés à l'aide de fichiers de co .[tip] Si vous utilisez le framework complet, vous n'avez rien d'autre à faire. Votre projet dispose d'un répertoire `config/` préparé pour les fichiers de configuration, et leur chargement est géré par [le chargeur de l'application |application:bootstrapping#Configuration du Conteneur DI]. Cet article s'adresse aux utilisateurs qui n'utilisent qu'une seule bibliothèque Nette et souhaitent profiter des fonctionnalités des fichiers de configuration. -Les fichiers de configuration sont généralement écrits au [format NEON |neon:format] et sont mieux édités dans des [éditeurs qui le prennent en charge |best-practices:editors-and-tools#Éditeur IDE]. Ils peuvent être considérés comme des instructions sur la façon de **créer et configurer** des objets. Ainsi, le résultat du chargement de la configuration sera une soi-disant factory, qui est un objet qui créera d'autres objets que nous voulons utiliser à la demande. Par exemple, une connexion à une base de données, etc. +Les fichiers de configuration sont généralement écrits au [format NEON |neon:format] et sont mieux édités dans des [éditeurs qui le prennent en charge |tools:ide]. Ils peuvent être considérés comme des instructions sur la façon de **créer et configurer** des objets. Ainsi, le résultat du chargement de la configuration sera une soi-disant factory, qui est un objet qui créera d'autres objets que nous voulons utiliser à la demande. Par exemple, une connexion à une base de données, etc. Cette factory est également appelée *conteneur d'injection de dépendances* (conteneur DI), et si vous êtes intéressé par les détails, lisez le chapitre sur [l'injection de dépendances |dependency-injection:]. diff --git a/bootstrap/hu/@home.texy b/bootstrap/hu/@home.texy index 86a0ca10df..51c3a05002 100644 --- a/bootstrap/hu/@home.texy +++ b/bootstrap/hu/@home.texy @@ -7,7 +7,7 @@ A Nette egyes részeit konfigurációs fájlok segítségével állítjuk be. Me .[tip] Ha a teljes keretrendszert használja, nincs szükség további teendőkre. A projektben van egy előkészített `config/` könyvtár a konfigurációs fájlok számára, és ezek betöltéséért az [alkalmazás betöltő |application:bootstrapping#DI konténer konfigurálása] felelős. Ez a cikk azoknak a felhasználóknak szól, akik csak egy Nette könyvtárat használnak, és ki szeretnék használni a konfigurációs fájlok lehetőségeit. -A konfigurációs fájlokat általában [NEON formátumban|neon:format] írják, és a legjobban [az azt támogató szerkesztőkben |best-practices:editors-and-tools#IDE szerkesztő] lehet szerkeszteni. Útmutatóként foghatók fel, hogyan **hozzunk létre és konfiguráljunk** objektumokat. Tehát a konfiguráció betöltésének eredménye egy úgynevezett factory lesz, ami egy olyan objektum, amely kérésre létrehozza számunkra a használni kívánt további objektumokat. Például adatbázis-kapcsolatokat stb. +A konfigurációs fájlokat általában [NEON formátumban|neon:format] írják, és a legjobban [az azt támogató szerkesztőkben |tools:ide] lehet szerkeszteni. Útmutatóként foghatók fel, hogyan **hozzunk létre és konfiguráljunk** objektumokat. Tehát a konfiguráció betöltésének eredménye egy úgynevezett factory lesz, ami egy olyan objektum, amely kérésre létrehozza számunkra a használni kívánt további objektumokat. Például adatbázis-kapcsolatokat stb. Ezt a factory-t *dependency injection konténernek* (DI konténer) is nevezik, és ha érdeklik a részletek, olvassa el a [dependency injection |dependency-injection:] fejezetet. diff --git a/bootstrap/it/@home.texy b/bootstrap/it/@home.texy index 72a8b4d1f0..cbd055400a 100644 --- a/bootstrap/it/@home.texy +++ b/bootstrap/it/@home.texy @@ -7,7 +7,7 @@ Le singole parti di Nette vengono impostate tramite file di configurazione. Vedi .[tip] Se si utilizza l'intero framework, non è necessario fare altro. Nel progetto è presente una directory `config/` preimpostata per i file di configurazione, e il loro caricamento è gestito dal [bootloader dell'applicazione |application:bootstrapping#Configurazione del Container DI]. Questo articolo è per gli utenti che utilizzano solo una libreria Nette e vogliono sfruttare le possibilità dei file di configurazione. -I file di configurazione sono solitamente scritti in [formato NEON|neon:format] e si modificano al meglio negli [editor con supporto per esso |best-practices:editors-and-tools#Editor IDE]. Possono essere visti come istruzioni su come **creare e configurare** oggetti. Quindi, il risultato del caricamento della configurazione sarà una cosiddetta factory, che è un oggetto che, su richiesta, ci creerà altri oggetti che vogliamo utilizzare. Ad esempio, connessioni al database, ecc. +I file di configurazione sono solitamente scritti in [formato NEON|neon:format] e si modificano al meglio negli [editor con supporto per esso |tools:ide]. Possono essere visti come istruzioni su come **creare e configurare** oggetti. Quindi, il risultato del caricamento della configurazione sarà una cosiddetta factory, che è un oggetto che, su richiesta, ci creerà altri oggetti che vogliamo utilizzare. Ad esempio, connessioni al database, ecc. Questa factory è anche chiamata *dependency injection container* (container DI) e se sei interessato ai dettagli, leggi il capitolo sulla [dependency injection |dependency-injection:]. diff --git a/bootstrap/ja/@home.texy b/bootstrap/ja/@home.texy index 80ea76d567..1cbdaf1b1d 100644 --- a/bootstrap/ja/@home.texy +++ b/bootstrap/ja/@home.texy @@ -7,7 +7,7 @@ Nette の個々のコンポーネントは設定ファイルを使用して設 .[tip] フレームワーク全体を使用している場合、追加の作業は必要ありません。プロジェクトには設定ファイル用の `config/` ディレクトリが用意されており、それらの読み込みは[アプリケーションブートローダー |application:bootstrapping#DIコンテナの設定]が担当します。 この記事は、Nette のライブラリを 1 つだけ使用し、設定ファイルの機能を利用したいユーザー向けです。 -設定ファイルは通常[NEON 形式|neon:format]で記述され、[サポートされているエディタ |best-practices:editors-and-tools#IDEエディタ]で編集するのが最適です。これらはオブジェクトを**作成および設定**する方法の指示として理解できます。したがって、設定の読み込み結果はいわゆるファクトリであり、これはリクエストに応じて使用したい他のオブジェクト(データベース接続など)を作成するオブジェクトです。 +設定ファイルは通常[NEON 形式|neon:format]で記述され、[サポートされているエディタ |tools:ide]で編集するのが最適です。これらはオブジェクトを**作成および設定**する方法の指示として理解できます。したがって、設定の読み込み結果はいわゆるファクトリであり、これはリクエストに応じて使用したい他のオブジェクト(データベース接続など)を作成するオブジェクトです。 このファクトリは*依存関係注入コンテナ*(DI コンテナ)とも呼ばれ、詳細に興味がある場合は[依存関係注入 |dependency-injection:]に関する章をお読みください。 diff --git a/bootstrap/pl/@home.texy b/bootstrap/pl/@home.texy index 5089994f3b..cdddd465a8 100644 --- a/bootstrap/pl/@home.texy +++ b/bootstrap/pl/@home.texy @@ -7,7 +7,7 @@ Poszczególne części Nette ustawiamy za pomocą plików konfiguracyjnych. Poka .[tip] Jeśli używasz całego frameworka, nie trzeba nic więcej robić. W projekcie masz przygotowany katalog `config/` na pliki konfiguracyjne, a ich wczytywaniem zajmuje się [bootloader aplikacji |application:bootstrapping#Konfiguracja kontenera DI]. Ten artykuł jest dla użytkowników, którzy używają tylko jednej biblioteki Nette i chcą wykorzystać możliwości plików konfiguracyjnych. -Pliki konfiguracyjne zazwyczaj zapisuje się w [formacie NEON|neon:format] i najlepiej edytuje się je w [edytorach z jego obsługą |best-practices:editors-and-tools#Edytor IDE]. Można je rozumieć jako instrukcje, jak **tworzyć i konfigurować** obiekty. Zatem wynikiem wczytania konfiguracji będzie tzw. fabryka, czyli obiekt, który na żądanie utworzy nam kolejne obiekty, których chcemy używać. Na przykład połączenie z bazą danych itp. +Pliki konfiguracyjne zazwyczaj zapisuje się w [formacie NEON|neon:format] i najlepiej edytuje się je w [edytorach z jego obsługą |tools:ide]. Można je rozumieć jako instrukcje, jak **tworzyć i konfigurować** obiekty. Zatem wynikiem wczytania konfiguracji będzie tzw. fabryka, czyli obiekt, który na żądanie utworzy nam kolejne obiekty, których chcemy używać. Na przykład połączenie z bazą danych itp. Ta fabryka nazywana jest również *kontenerem dependency injection* (kontenerem DI), a jeśli interesują Cię szczegóły, przeczytaj rozdział o [dependency injection |dependency-injection:]. diff --git a/bootstrap/pt/@home.texy b/bootstrap/pt/@home.texy index 0344fc188a..d08859b9a8 100644 --- a/bootstrap/pt/@home.texy +++ b/bootstrap/pt/@home.texy @@ -7,7 +7,7 @@ Os componentes individuais do Nette são configurados usando arquivos de configu .[tip] Se você estiver usando todo o framework, não há necessidade de fazer mais nada. No seu projeto, você tem um diretório `config/` pré-preparado para arquivos de configuração, e o carregamento deles é responsabilidade do [carregador da aplicação |application:bootstrapping#Configuração do contêiner de DI]. Este artigo é para usuários que usam apenas uma biblioteca Nette e desejam aproveitar as opções dos arquivos de configuração. -Os arquivos de configuração são geralmente escritos no [formato NEON|neon:format] e são melhor editados em [editores com suporte a ele |best-practices:editors-and-tools#Editor IDE]. Eles podem ser entendidos como instruções sobre como **criar e configurar** objetos. Ou seja, o resultado do carregamento da configuração será uma chamada fábrica, que é um objeto que, sob demanda, criará outros objetos que queremos usar. Por exemplo, uma conexão de banco de dados, etc. +Os arquivos de configuração são geralmente escritos no [formato NEON|neon:format] e são melhor editados em [editores com suporte a ele |tools:ide]. Eles podem ser entendidos como instruções sobre como **criar e configurar** objetos. Ou seja, o resultado do carregamento da configuração será uma chamada fábrica, que é um objeto que, sob demanda, criará outros objetos que queremos usar. Por exemplo, uma conexão de banco de dados, etc. Essa fábrica também é chamada de *contêiner de injeção de dependência* (contêiner DI) e, se você estiver interessado em detalhes, leia o capítulo sobre [injeção de dependência |dependency-injection:]. diff --git a/bootstrap/ro/@home.texy b/bootstrap/ro/@home.texy index 16606ee9e5..12893d9b60 100644 --- a/bootstrap/ro/@home.texy +++ b/bootstrap/ro/@home.texy @@ -7,7 +7,7 @@ Componentele individuale Nette sunt configurate folosind fișiere de configurare .[tip] Dacă utilizați întregul framework, nu este nevoie să faceți nimic altceva. În proiect aveți un director `config/` pregătit pentru fișierele de configurare, iar încărcarea lor este gestionată de [încărcătorul aplicației |application:bootstrapping#Configurarea containerului DI]. Acest articol este pentru utilizatorii care folosesc doar o singură bibliotecă Nette și doresc să profite de posibilitățile fișierelor de configurare. -Fișierele de configurare sunt de obicei scrise în [formatul NEON|neon:format] și cel mai bine se editează în [editori cu suport pentru acesta |best-practices:editors-and-tools#Editor IDE]. Ele pot fi înțelese ca instrucțiuni despre cum să **creați și configurați** obiecte. Prin urmare, rezultatul încărcării configurației va fi așa-numita fabrică (factory), care este un obiect ce ne va crea la cerere alte obiecte pe care dorim să le folosim. De exemplu, conexiuni la baze de date etc. +Fișierele de configurare sunt de obicei scrise în [formatul NEON|neon:format] și cel mai bine se editează în [editori cu suport pentru acesta |tools:ide]. Ele pot fi înțelese ca instrucțiuni despre cum să **creați și configurați** obiecte. Prin urmare, rezultatul încărcării configurației va fi așa-numita fabrică (factory), care este un obiect ce ne va crea la cerere alte obiecte pe care dorim să le folosim. De exemplu, conexiuni la baze de date etc. Această fabrică se mai numește și *dependency injection container* (container DI) și, dacă sunteți interesat de detalii, citiți capitolul despre [dependency injection |dependency-injection:]. diff --git a/bootstrap/ru/@home.texy b/bootstrap/ru/@home.texy index ec99937fd8..c91184ed5a 100644 --- a/bootstrap/ru/@home.texy +++ b/bootstrap/ru/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Если вы используете весь фреймворк, вам не нужно ничего делать. В проекте у вас есть подготовленный каталог `config/` для конфигурационных файлов, и их загрузкой занимается [загрузчик приложения |application:bootstrapping#Конфигурация DI-контейнера]. Эта статья предназначена для пользователей, которые используют только одну библиотеку Nette и хотят воспользоваться возможностями конфигурационных файлов. -Конфигурационные файлы обычно пишутся в [формате NEON|neon:format] и лучше всего редактируются в [редакторах с его поддержкой |best-practices:editors-and-tools#IDE редактор]. Их можно рассматривать как инструкции по **созданию и настройке** объектов. Таким образом, результатом загрузки конфигурации будет так называемая фабрика, то есть объект, который по запросу создаст для нас другие объекты, которые мы хотим использовать. Например, соединение с базой данных и т. д. +Конфигурационные файлы обычно пишутся в [формате NEON|neon:format] и лучше всего редактируются в [редакторах с его поддержкой |tools:ide]. Их можно рассматривать как инструкции по **созданию и настройке** объектов. Таким образом, результатом загрузки конфигурации будет так называемая фабрика, то есть объект, который по запросу создаст для нас другие объекты, которые мы хотим использовать. Например, соединение с базой данных и т. д. Эта фабрика также называется *контейнером внедрения зависимостей* (DI container), и если вас интересуют подробности, прочитайте главу о [внедрении зависимостей |dependency-injection:]. diff --git a/bootstrap/sl/@home.texy b/bootstrap/sl/@home.texy index 76641a1cce..23868a18ef 100644 --- a/bootstrap/sl/@home.texy +++ b/bootstrap/sl/@home.texy @@ -7,7 +7,7 @@ Posamezne komponente Nette nastavljamo s pomočjo konfiguracijskih datotek. Poka .[tip] Če uporabljate celotno ogrodje, ni treba storiti ničesar dodatnega. V projektu imate za konfiguracijske datoteke pripravljen imenik `config/` in za njihovo nalaganje skrbi [zavajalec aplikacije |application:bootstrapping#Konfiguracija DI vsebnika]. Ta članek je za uporabnike, ki uporabljajo samo eno knjižnico Nette in želijo izkoristiti možnosti konfiguracijskih datotek. -Konfiguracijske datoteke se običajno pišejo v [formatu NEON|neon:format] in se najbolje urejajo v [urejevalnikih z njegovo podporo |best-practices:editors-and-tools#IDE urejevalnik]. Lahko jih razumemo kot navodila, kako **ustvarjati in konfigurirati** objekte. Torej bo rezultat nalaganja konfiguracije tako imenovana tovarna, kar je objekt, ki nam na zahtevo ustvari druge objekte, ki jih želimo uporabljati. Na primer povezavo s podatkovno bazo itd. +Konfiguracijske datoteke se običajno pišejo v [formatu NEON|neon:format] in se najbolje urejajo v [urejevalnikih z njegovo podporo |tools:ide]. Lahko jih razumemo kot navodila, kako **ustvarjati in konfigurirati** objekte. Torej bo rezultat nalaganja konfiguracije tako imenovana tovarna, kar je objekt, ki nam na zahtevo ustvari druge objekte, ki jih želimo uporabljati. Na primer povezavo s podatkovno bazo itd. Tej tovarni se tudi reče *dependency injection vsebnik* (DI vsebnik) in če vas zanimajo podrobnosti, preberite poglavje o [dependency injection |dependency-injection:]. diff --git a/bootstrap/tr/@home.texy b/bootstrap/tr/@home.texy index 732122fed8..94298ab84a 100644 --- a/bootstrap/tr/@home.texy +++ b/bootstrap/tr/@home.texy @@ -7,7 +7,7 @@ Nette'nin bireysel bileşenlerini yapılandırma dosyaları kullanarak ayarlıyo .[tip] Eğer tüm framework'ü kullanıyorsanız, başka bir şey yapmanıza gerek yoktur. Projenizde yapılandırma dosyaları için önceden hazırlanmış bir `config/` dizini bulunur ve bunların yüklenmesinden [uygulama yükleyicisi |application:bootstrapping#DI Konteyner Yapılandırması] sorumludur. Bu makale, yalnızca bir Nette kütüphanesi kullanan ve yapılandırma dosyalarının olanaklarından yararlanmak isteyen kullanıcılar içindir. -Yapılandırma dosyaları genellikle [NEON formatında|neon:format] yazılır ve en iyi şekilde [destekleyen düzenleyicilerde |best-practices:editors-and-tools#IDE Editörü] düzenlenir. Bunları, nesnelerin **nasıl oluşturulacağı ve yapılandırılacağı** konusunda talimatlar olarak düşünebiliriz. Yani, yapılandırmanın yüklenmesinin sonucu, istek üzerine kullanmak istediğimiz diğer nesneleri (örneğin, veritabanı bağlantısı vb.) oluşturacak olan fabrika olarak adlandırılan bir nesne olacaktır. +Yapılandırma dosyaları genellikle [NEON formatında|neon:format] yazılır ve en iyi şekilde [destekleyen düzenleyicilerde |tools:ide] düzenlenir. Bunları, nesnelerin **nasıl oluşturulacağı ve yapılandırılacağı** konusunda talimatlar olarak düşünebiliriz. Yani, yapılandırmanın yüklenmesinin sonucu, istek üzerine kullanmak istediğimiz diğer nesneleri (örneğin, veritabanı bağlantısı vb.) oluşturacak olan fabrika olarak adlandırılan bir nesne olacaktır. Bu fabrikaya aynı zamanda *dependency injection konteyneri* (DI konteyneri) denir ve ayrıntılarla ilgileniyorsanız, [dependency injection |dependency-injection:] bölümünü okuyun. diff --git a/bootstrap/uk/@home.texy b/bootstrap/uk/@home.texy index 1320bdf9fa..4561b0fe34 100644 --- a/bootstrap/uk/@home.texy +++ b/bootstrap/uk/@home.texy @@ -7,7 +7,7 @@ Nette Bootstrap .[tip] Якщо ви використовуєте весь фреймворк, нічого додаткового робити не потрібно. У проекті є підготовлений каталог `config/` для конфігураційних файлів, а за їх завантаження відповідає [завантажувач застосунку |application:bootstrapping#Конфігурація DI-контейнера]. Ця стаття призначена для користувачів, які використовують лише одну бібліотеку Nette і хочуть скористатися можливостями конфігураційних файлів. -Конфігураційні файли зазвичай записуються у [форматі NEON|neon:format] і найкраще редагуються в [редакторах з його підтримкою |best-practices:editors-and-tools#IDE редактор]. Їх можна розглядати як інструкції щодо **створення та конфігурації** об'єктів. Отже, результатом завантаження конфігурації буде так звана фабрика, тобто об'єкт, який за запитом створить для нас інші об'єкти, які ми хочемо використовувати. Наприклад, з'єднання з базою даних тощо. +Конфігураційні файли зазвичай записуються у [форматі NEON|neon:format] і найкраще редагуються в [редакторах з його підтримкою |tools:ide]. Їх можна розглядати як інструкції щодо **створення та конфігурації** об'єктів. Отже, результатом завантаження конфігурації буде так звана фабрика, тобто об'єкт, який за запитом створить для нас інші об'єкти, які ми хочемо використовувати. Наприклад, з'єднання з базою даних тощо. Ця фабрика також називається *dependency injection контейнером* (DI container), і якщо вас цікавлять подробиці, прочитайте розділ про [dependency injection |dependency-injection:]. diff --git a/caching/cs/@home.texy b/caching/cs/@home.texy index 17ddcaa49f..1d3f3eed17 100644 --- a/caching/cs/@home.texy +++ b/caching/cs/@home.texy @@ -125,7 +125,7 @@ Nebo pomocí 3. parametru v metodě `load()`, např: ```php $value = $cache->load($key, function () { - return ...; + return /* ... */; }, [Cache::Expire => '20 minutes']); ``` @@ -293,7 +293,7 @@ Velmi elegantně lze zachytávat a cachovat výstup: ```php if ($capture = $cache->capture($key)) { - echo ... // vypisujeme data + // echo ... vypisujeme data $capture->end(); // uložíme výstup do cache } diff --git a/caching/en/@home.texy b/caching/en/@home.texy index d8a7533643..e3557a0539 100644 --- a/caching/en/@home.texy +++ b/caching/en/@home.texy @@ -125,7 +125,7 @@ Or by using the 3rd parameter of the `load()` method itself, e.g.: ```php $value = $cache->load($key, function () { - return ...; + return /* ... */; }, [Cache::Expire => '20 minutes']); ``` @@ -293,7 +293,7 @@ Output can be captured and cached very elegantly: ```php if ($capture = $cache->capture($key)) { - echo ... // printing some data + // echo ... printing some data $capture->end(); // save the output to the cache } diff --git a/code-checker/bg/@home.texy b/code-checker/bg/@home.texy deleted file mode 100644 index ab284bfe7e..0000000000 --- a/code-checker/bg/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Инструментът [Code Checker |https://github.com/nette/code-checker] проверява и евентуално коригира някои от формалните грешки във вашия изходен код. - - -Инсталация -========== - -Code Checker не трябва да се добавя към зависимостите, а да се инсталира като проект. - -```shell -composer create-project nette/code-checker -``` - -Или го инсталирайте глобално с помощта на: - -```shell -composer global require nette/code-checker -``` - -и се уверете, че вашата глобална директория `vendor/bin` е в [променливата на средата $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Употреба -======== - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Без параметри проверява текущата директория в режим само за четене, с параметъра `-f` коригира файловете. - -Преди да се запознаете с него, определено първо архивирайте файловете си. - -За по-лесно стартиране можем да създадем файл `code.bat`: - -```shell -php path_to_Nette_tools\Code-Checker\code-checker %* -``` - - -Какво прави всичко това? -======================== - -- премахва [BOM |nette:glossary#BOM] -- проверява валидността на [Latte |latte:] шаблони -- проверява валидността на файлове `.neon`, `.php` и `.json` -- проверява за наличието на [контролни знаци |nette:glossary#Контролни знаци] -- проверява дали файлът е кодиран в UTF-8 -- проверява неправилно записани `/* @anotace */` (липсва звездичка) -- премахва завършващия `?>` при PHP файлове -- премахва десните интервали и излишните редове в края на файла -- нормализира разделителите на редове до системните (ако посочите опцията `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/cs/@home.texy b/code-checker/cs/@home.texy deleted file mode 100644 index a4d62f10d6..0000000000 --- a/code-checker/cs/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Nástroj [Code Checker |https://github.com/nette/code-checker] zkontroluje a případně opraví některé z formálních chyb ve vašich zdrojových kódech. - - -Instalace -========= - -Code Checker byste neměli přidávat do závislostí, ale instalovat jako projekt. - -```shell -composer create-project nette/code-checker -``` - -Nebo jej nainstalujte globálně pomocí: - -```shell -composer global require nette/code-checker -``` - -a ujistěte se, že váš globální adresář `vendor/bin` je v [proměnné prostředí $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Použití -======= - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Bez parametrů zkontroluje aktuální adresář v read-only režimu, s parametrem `-f` opravuje soubory. - -Než se s ním seznámíte, určitě si soubory nejdřív zazálohujte. - -Pro snadnější spouštění si můžeme vytvořit soubor `code.bat`: - -```shell -php cesta_k_Nette_tools\Code-Checker\code-checker %* -``` - - -Co všechno dělá? -================ - -- odstraňuje [BOM |nette:glossary#BOM] -- kontroluje validitu [Latte |latte:] šablon -- kontroluje validitu souborů `.neon`, `.php` a `.json` -- kontroluje výskyt [kontrolních znaků |nette:glossary#Kontrolní znaky] -- kontroluje, zda je soubor kódován v UTF-8 -- kontroluje chybně zapsané `/* @anotace */` (chybí hvězdička) -- odstraňuje ukončovací `?>` u PHP souborů -- odstraňuje pravostranné mezery a zbytečné řádky na konci souboru -- normalizuje oddělovače řádků na systémové (pokud uvedete volbu `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/de/@home.texy b/code-checker/de/@home.texy deleted file mode 100644 index 598b407465..0000000000 --- a/code-checker/de/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Das Werkzeug [Code Checker |https://github.com/nette/code-checker] überprüft und korrigiert gegebenenfalls einige formale Fehler in Ihrem Quellcode. - - -Installation -============ - -Code Checker sollten Sie nicht zu Ihren Abhängigkeiten hinzufügen, sondern als Projekt installieren. - -```shell -composer create-project nette/code-checker -``` - -Oder installieren Sie es global mit: - -```shell -composer global require nette/code-checker -``` - -und stellen Sie sicher, dass Ihr globales Verzeichnis `vendor/bin` in der [Umgebungsvariablen $PATH |https://getcomposer.org/doc/03-cli.md#global] enthalten ist. - - -Verwendung -========== - -``` -Usage: php code-checker [options] - -Options: - -d Zu scannender Ordner oder Datei (Standard: aktuelles Verzeichnis) - -i | --ignore Zu ignorierende Dateien - -f | --fix Korrigiert Dateien - -l | --eol Konvertiert Zeilenumbruchzeichen - --no-progress Keine Fortschrittspunkte anzeigen - --strict-types Prüft, ob die PHP 7.0-Direktive strict_types aktiviert ist -``` - -Ohne Parameter prüft es das aktuelle Verzeichnis im schreibgeschützten Modus, mit dem Parameter `-f` korrigiert es die Dateien. - -Bevor Sie sich damit vertraut machen, sichern Sie unbedingt zuerst Ihre Dateien. - -Für einen einfacheren Start können wir eine Datei `code.bat` erstellen: - -```shell -php pfad_zu_Nette_tools\Code-Checker\code-checker %* -``` - - -Was macht es alles? -=================== - -- entfernt das [BOM |nette:glossary#BOM] -- prüft die Gültigkeit von [Latte |latte:]-Templates -- prüft die Gültigkeit von `.neon`-, `.php`- und `.json`-Dateien -- prüft das Vorkommen von [Steuerzeichen |nette:glossary#Steuerzeichen] -- prüft, ob die Datei in UTF-8 kodiert ist -- prüft falsch geschriebene `/* @anotace */` (fehlendes Sternchen) -- entfernt das schließende `?>` bei PHP-Dateien -- entfernt Leerzeichen am Zeilenende und unnötige Leerzeilen am Dateiende -- normalisiert Zeilentrennzeichen auf Systemstandard (wenn Sie die Option `-l` angeben) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/el/@home.texy b/code-checker/el/@home.texy deleted file mode 100644 index de1f6401a0..0000000000 --- a/code-checker/el/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Το εργαλείο [Code Checker |https://github.com/nette/code-checker] ελέγχει και ενδεχομένως διορθώνει ορισμένα από τα τυπικά σφάλματα στους πηγαίους κώδικές σας. - - -Εγκατάσταση -=========== - -Δεν πρέπει να προσθέσετε το Code Checker στις εξαρτήσεις, αλλά να το εγκαταστήσετε ως έργο. - -```shell -composer create-project nette/code-checker -``` - -Ή εγκαταστήστε το καθολικά χρησιμοποιώντας: - -```shell -composer global require nette/code-checker -``` - -και βεβαιωθείτε ότι ο καθολικός σας κατάλογος `vendor/bin` βρίσκεται στη [μεταβλητή περιβάλλοντος $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Χρήση -===== - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Χωρίς παραμέτρους ελέγχει τον τρέχοντα κατάλογο σε κατάσταση μόνο ανάγνωσης, με την παράμετρο `-f` διορθώνει τα αρχεία. - -Πριν εξοικειωθείτε μαζί του, φροντίστε να δημιουργήσετε αντίγραφα ασφαλείας των αρχείων σας πρώτα. - -Για ευκολότερη εκτέλεση, μπορούμε να δημιουργήσουμε ένα αρχείο `code.bat`: - -```shell -php path_to_Nette_tools\Code-Checker\code-checker %* -``` - - -Τι κάνει; -========= - -- αφαιρεί το [BOM |nette:glossary#BOM] -- ελέγχει την εγκυρότητα των templates [Latte |latte:] -- ελέγχει την εγκυρότητα των αρχείων `.neon`, `.php` και `.json` -- ελέγχει την παρουσία [χαρακτήρων ελέγχου |nette:glossary#Control characters] -- ελέγχει εάν το αρχείο είναι κωδικοποιημένο σε UTF-8 -- ελέγχει για λανθασμένα γραμμένα `/* @anotace */` (λείπει ο αστερίσκος) -- αφαιρεί το τελικό `?>` από τα αρχεία PHP -- αφαιρεί τα δεξιά κενά και τις περιττές γραμμές στο τέλος του αρχείου -- κανονικοποιεί τους διαχωριστές γραμμών σε συστήματος (εάν δώσετε την επιλογή `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/en/@home.texy b/code-checker/en/@home.texy deleted file mode 100644 index 2bbaba1c33..0000000000 --- a/code-checker/en/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -The tool called [Code Checker |https://github.com/nette/code-checker] checks and optionally repairs some of the formal errors in your source code. - - -Installation -============ - -Code Checker should be installed as a project, not added as a dependency. - -```shell -composer create-project nette/code-checker -``` - -Or install it globally via: - -```shell -composer global require nette/code-checker -``` - -and make sure your global vendor binaries directory is in [your `$PATH` environment variable|https://getcomposer.org/doc/03-cli.md#global]. - - -Usage -===== - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Without parameters, it checks the current working directory in read-only mode; with the `-f` parameter, it fixes files. - -Before you get familiar with the tool, be sure to back up your files first. - -You can create a batch file, e.g., `code.bat`, for easier execution of Code Checker under Windows: - -```shell -php path_to\Nette_tools\Code-Checker\code-checker %* -``` - - -What Does Code Checker Do? -========================== - -- removes [BOM |nette:glossary#BOM] -- checks the validity of [Latte |latte:] templates -- checks the validity of `.neon`, `.php`, and `.json` files -- checks for [control characters |nette:glossary#Control Characters] -- checks whether the file is encoded in UTF-8 -- checks for misspelled `/* @annotations */` (missing second asterisk) -- removes PHP ending tags `?>` in PHP files -- removes trailing whitespace and unnecessary blank lines from the end of a file -- normalizes line endings to the system default (with the `-l` parameter) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/es/@home.texy b/code-checker/es/@home.texy deleted file mode 100644 index c6770a3010..0000000000 --- a/code-checker/es/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -La herramienta [Code Checker |https://github.com/nette/code-checker] comprueba y, opcionalmente, corrige algunos de los errores formales en sus códigos fuente. - - -Instalación -=========== - -No debe agregar Code Checker a las dependencias, sino instalarlo como un proyecto. - -```shell -composer create-project nette/code-checker -``` - -O instálelo globalmente usando: - -```shell -composer global require nette/code-checker -``` - -y asegúrese de que su directorio global `vendor/bin` esté en la [variable de entorno $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Uso -=== - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Sin parámetros, comprueba el directorio actual en modo de solo lectura, con el parámetro `-f` corrige los archivos. - -Antes de familiarizarse con él, asegúrese de hacer una copia de seguridad de sus archivos primero. - -Para facilitar la ejecución, podemos crear un archivo `code.bat`: - -```shell -php path_to_Nette_tools\Code-Checker\code-checker %* -``` - - -¿Qué hace todo esto? -==================== - -- elimina el [BOM |nette:glossary#BOM] -- comprueba la validez de las plantillas [Latte |latte:] -- comprueba la validez de los archivos `.neon`, `.php` y `.json` -- comprueba la presencia de [caracteres de control |nette:glossary#Caracteres de control] -- comprueba si el archivo está codificado en UTF-8 -- comprueba las `/* @anotaciones */` escritas incorrectamente (falta el asterisco) -- elimina el cierre `?>` de los archivos PHP -- elimina los espacios finales y las líneas innecesarias al final del archivo -- normaliza los separadores de línea a los del sistema (si especifica la opción `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/fr/@home.texy b/code-checker/fr/@home.texy deleted file mode 100644 index 13c595ee8c..0000000000 --- a/code-checker/fr/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -L'outil [Code Checker |https://github.com/nette/code-checker] vérifie et corrige éventuellement certaines erreurs formelles dans vos codes sources. - - -Installation -============ - -Code Checker ne doit pas être ajouté aux dépendances, mais installé en tant que projet. - -```shell -composer create-project nette/code-checker -``` - -Ou installez-le globalement en utilisant : - -```shell -composer global require nette/code-checker -``` - -et assurez-vous que votre répertoire global `vendor/bin` est dans [la variable d'environnement $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Utilisation -=========== - -``` -Usage: php code-checker [options] - -Options: - -d Dossier ou fichier à analyser (par défaut : répertoire courant) - -i | --ignore Fichiers à ignorer - -f | --fix Corrige les fichiers - -l | --eol Convertit les caractères de nouvelle ligne - --no-progress N'affiche pas les points de progression - --strict-types Vérifie si la directive PHP 7.0 strict_types est activée -``` - -Sans paramètres, il vérifie le répertoire actuel en mode lecture seule, avec le paramètre `-f`, il corrige les fichiers. - -Avant de vous familiariser avec lui, assurez-vous de sauvegarder d'abord vos fichiers. - -Pour faciliter l'exécution, nous pouvons créer un fichier `code.bat` : - -```shell -php chemin_vers_Nette_tools\Code-Checker\code-checker %* -``` - - -Que fait-il ? -============= - -- supprime le [BOM |nette:glossary#BOM] -- vérifie la validité des templates [Latte |latte:] -- vérifie la validité des fichiers `.neon`, `.php` et `.json` -- vérifie la présence de [caractères de contrôle |nette:glossary#Caractères de contrôle] -- vérifie si le fichier est encodé en UTF-8 -- vérifie les `/* @annotations */` mal écrites (étoile manquante) -- supprime le `?>` de fin des fichiers PHP -- supprime les espaces de fin et les lignes vides inutiles à la fin du fichier -- normalise les séparateurs de lignes en séparateurs système (si vous spécifiez l'option `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/hu/@home.texy b/code-checker/hu/@home.texy deleted file mode 100644 index e676665b2f..0000000000 --- a/code-checker/hu/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -A [Code Checker |https://github.com/nette/code-checker] eszköz ellenőrzi és szükség esetén kijavítja a forráskódjaiban található néhány formai hibát. - - -Telepítés -========= - -A Code Checkert nem szabad a függőségekhez hozzáadni, hanem projektként kell telepíteni. - -```shell -composer create-project nette/code-checker -``` - -Vagy telepítse globálisan a következővel: - -```shell -composer global require nette/code-checker -``` - -és győződjön meg róla, hogy a globális `vendor/bin` könyvtára benne van a [$PATH környezeti változóban |https://getcomposer.org/doc/03-cli.md#global]. - - -Használat -========= - -``` -Usage: php code-checker [options] - -Options: - -d Szkennelendő mappa vagy fájl (alapértelmezett: aktuális könyvtár) - -i | --ignore Figyelmen kívül hagyandó fájlok - -f | --fix Javítja a fájlokat - -l | --eol Újsor karakterek konvertálása - --no-progress Ne jelenítse meg a folyamatjelző pontokat - --strict-types Ellenőrzi, hogy a PHP 7.0 strict_types direktíva engedélyezve van-e -``` - -Paraméterek nélkül az aktuális könyvtárat ellenőrzi read-only módban, a `-f` paraméterrel javítja a fájlokat. - -Mielőtt megismerkedne vele, mindenképpen készítsen biztonsági másolatot a fájlokról. - -A könnyebb indítás érdekében létrehozhatunk egy `code.bat` fájlt: - -```shell -php path_to_Nette_tools\Code-Checker\code-checker %* -``` - - -Mit csinál pontosan? -==================== - -- eltávolítja a [BOM |nette:glossary#BOM]-ot -- ellenőrzi a [Latte |latte:] sablonok érvényességét -- ellenőrzi a `.neon`, `.php` és `.json` fájlok érvényességét -- ellenőrzi a [vezérlőkarakterek |nette:glossary#Vezérlő karakterek] előfordulását -- ellenőrzi, hogy a fájl UTF-8 kódolású-e -- ellenőrzi a hibásan írt `/* @anotace */` (hiányzik a csillag) -- eltávolítja a záró `?>` taget a PHP fájlokból -- eltávolítja a jobb oldali szóközöket és a felesleges sorokat a fájl végéről -- normalizálja a sorelválasztókat a rendszer alapértelmezettjére (ha megadja a `-l` opciót) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/it/@home.texy b/code-checker/it/@home.texy deleted file mode 100644 index 4529024b15..0000000000 --- a/code-checker/it/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Lo strumento [Code Checker |https://github.com/nette/code-checker] controlla e, se necessario, corregge alcuni degli errori formali nei vostri codici sorgente. - - -Installazione -============= - -Code Checker non dovrebbe essere aggiunto alle dipendenze, ma installato come progetto. - -```shell -composer create-project nette/code-checker -``` - -Oppure installatelo globalmente tramite: - -```shell -composer global require nette/code-checker -``` - -e assicuratevi che la vostra directory globale `vendor/bin` sia nella [variabile d'ambiente $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Utilizzo -======== - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Senza parametri, controlla la directory corrente in modalità di sola lettura, con il parametro `-f` corregge i file. - -Prima di familiarizzare con esso, assicuratevi di eseguire il backup dei file. - -Per un avvio più semplice, possiamo creare un file `code.bat`: - -```shell -php percorso_a_Nette_tools\Code-Checker\code-checker %* -``` - - -Cosa fa? -======== - -- rimuove il [BOM |nette:glossary#BOM] -- controlla la validità dei template [Latte |latte:] -- controlla la validità dei file `.neon`, `.php` e `.json` -- controlla la presenza di [caratteri di controllo |nette:glossary#Caratteri di controllo] -- controlla se il file è codificato in UTF-8 -- controlla le annotazioni `/* @anotace */` scritte male (manca l'asterisco) -- rimuove i tag di chiusura `?>` dai file PHP -- rimuove gli spazi finali e le righe vuote alla fine del file -- normalizza i separatori di riga a quelli di sistema (se si specifica l'opzione `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/ja/@home.texy b/code-checker/ja/@home.texy deleted file mode 100644 index b01ce40115..0000000000 --- a/code-checker/ja/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -[Code Checker |https://github.com/nette/code-checker]ツールは、ソースコード内のいくつかの形式的なエラーをチェックし、必要に応じて修正します。 - - -インストール -====== - -Code Checkerは依存関係に追加するのではなく、プロジェクトとしてインストールする必要があります。 - -```shell -composer create-project nette/code-checker -``` - -または、次のようにグローバルにインストールします: - -```shell -composer global require nette/code-checker -``` - -そして、グローバルな `vendor/bin` ディレクトリが[$PATH 環境変数 |https://getcomposer.org/doc/03-cli.md#global]に含まれていることを確認してください。 - - -使用法 -=== - -``` -Usage: php code-checker [options] - -Options: - -d スキャンするフォルダまたはファイル(デフォルト:現在のディレクトリ) - -i | --ignore 無視するファイル - -f | --fix ファイルを修正 - -l | --eol 改行文字を変換 - --no-progress 進捗ドットを表示しない - --strict-types PHP 7.0 ディレクティブ strict_types が有効かどうかをチェック -``` - -パラメータなしでは、現在のディレクトリを読み取り専用モードでチェックします。パラメータ `-f` を指定すると、ファイルを修正します。 - -慣れる前に、必ずファイルをバックアップしてください。 - -簡単に実行するために、`code.bat` ファイルを作成できます: - -```shell -php path_to_Nette_tools\Code-Checker\code-checker %* -``` - - -何をするのですか? -========= - -- [BOM |nette:glossary#BOM]を削除します -- [Latte |latte:] テンプレートの有効性をチェックします -- `.neon`、`.php`、`.json` ファイルの有効性をチェックします -- [制御文字 |nette:glossary#制御文字]の出現をチェックします -- ファイルがUTF-8でエンコードされているかチェックします -- 誤って記述された `/* @anotation */`(アスタリスクが欠けている)をチェックします -- PHP ファイルの末尾の `?>` を削除します -- ファイルの末尾の右側のスペースと不要な行を削除します -- (オプション `-l` を指定した場合)改行文字をシステム標準に正規化します - -{{leftbar: www:@menu-common}} diff --git a/code-checker/pl/@home.texy b/code-checker/pl/@home.texy deleted file mode 100644 index 23a99c3807..0000000000 --- a/code-checker/pl/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Narzędzie [Code Checker |https://github.com/nette/code-checker] sprawdza i ewentualnie naprawia niektóre formalne błędy w Twoich kodach źródłowych. - - -Instalacja -========== - -Code Checker nie powinien być dodawany do zależności, ale instalowany jako projekt. - -```shell -composer create-project nette/code-checker -``` - -Lub zainstaluj go globalnie za pomocą: - -```shell -composer global require nette/code-checker -``` - -i upewnij się, że twój globalny katalog `vendor/bin` jest w [zmiennej środowiskowej $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Użycie -====== - -``` -Usage: php code-checker [options] - -Options: - -d Katalog lub plik do skanowania (domyślnie: bieżący katalog) - -i | --ignore Pliki do ignorowania - -f | --fix Naprawia pliki - -l | --eol Konwertuj znaki nowej linii - --no-progress Nie pokazuj kropek postępu - --strict-types Sprawdza, czy dyrektywa PHP 7.0 strict_types jest włączona -``` - -Bez parametrów sprawdza bieżący katalog w trybie tylko do odczytu, z parametrem `-f` naprawia pliki. - -Zanim się z nim zapoznasz, na pewno najpierw zrób kopię zapasową plików. - -Dla łatwiejszego uruchamiania możemy utworzyć plik `code.bat`: - -```shell -php sciezka_do_Nette_tools\Code-Checker\code-checker %* -``` - - -Co wszystko robi? -================= - -- usuwa [BOM |nette:glossary#BOM] -- sprawdza poprawność szablonów [Latte |latte:] -- sprawdza poprawność plików `.neon`, `.php` i `.json` -- sprawdza występowanie [znaków kontrolnych |nette:glossary#Znaki kontrolne] -- sprawdza, czy plik jest zakodowany w UTF-8 -- sprawdza błędnie zapisane `/* @adnotacje */` (brakuje gwiazdki) -- usuwa kończące `?>` w plikach PHP -- usuwa prawostronne spacje i zbędne linie na końcu pliku -- normalizuje separatory linii do systemowych (jeśli podasz opcję `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/pt/@home.texy b/code-checker/pt/@home.texy deleted file mode 100644 index c50e0603c1..0000000000 --- a/code-checker/pt/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -A ferramenta [Code Checker |https://github.com/nette/code-checker] verifica e, opcionalmente, corrige alguns dos erros formais nos seus códigos-fonte. - - -Instalação -========== - -Você não deve adicionar o Code Checker às suas dependências, mas instalá-lo como um projeto. - -```shell -composer create-project nette/code-checker -``` - -Ou instale-o globalmente usando: - -```shell -composer global require nette/code-checker -``` - -e certifique-se de que seu diretório global `vendor/bin` esteja na [variável de ambiente $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Uso -=== - -``` -Usage: php code-checker [options] - -Options: - -d Pasta ou arquivo para escanear (padrão: diretório atual) - -i | --ignore Arquivos a ignorar - -f | --fix Corrige arquivos - -l | --eol Converte caracteres de nova linha - --no-progress Não mostrar pontos de progresso - --strict-types Verifica se a diretiva strict_types do PHP 7.0 está habilitada -``` - -Sem parâmetros, verifica o diretório atual no modo somente leitura; com o parâmetro `-f`, corrige os arquivos. - -Antes de se familiarizar com ele, certifique-se de fazer backup dos seus arquivos primeiro. - -Para facilitar a execução, podemos criar um arquivo `code.bat`: - -```shell -php caminho_para_Nette_tools\Code-Checker\code-checker %* -``` - - -O que ele faz? -============== - -- remove o [BOM |nette:glossary#BOM] -- verifica a validade dos templates [Latte |latte:] -- verifica a validade dos arquivos `.neon`, `.php` e `.json` -- verifica a ocorrência de [caracteres de controle |nette:glossary#Caracteres de controle] -- verifica se o arquivo está codificado em UTF-8 -- verifica `/* @anotações */` mal escritas (falta asterisco) -- remove `?>` de fechamento em arquivos PHP -- remove espaços em branco à direita e linhas desnecessárias no final do arquivo -- normaliza os separadores de linha para o padrão do sistema (se você usar a opção `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/ro/@home.texy b/code-checker/ro/@home.texy deleted file mode 100644 index c73570354d..0000000000 --- a/code-checker/ro/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Instrumentul [Code Checker |https://github.com/nette/code-checker] verifică și, eventual, corectează unele dintre erorile formale din codurile dvs. sursă. - - -Instalare -========= - -Code Checker nu ar trebui adăugat la dependențe, ci instalat ca proiect. - -```shell -composer create-project nette/code-checker -``` - -Sau instalați-l global folosind: - -```shell -composer global require nette/code-checker -``` - -și asigurați-vă că directorul dvs. global `vendor/bin` se află în [variabila de mediu $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Utilizare -========= - -``` -Usage: php code-checker [options] - -Options: - -d Director sau fișier de scanat (implicit: directorul curent) - -i | --ignore Fișiere de ignorat - -f | --fix Corectează fișierele - -l | --eol Convertește caracterele de sfârșit de linie - --no-progress Nu afișa punctele de progres - --strict-types Verifică dacă directiva PHP 7.0 strict_types este activată -``` - -Fără parametri, verifică directorul curent în modul read-only, cu parametrul `-f` corectează fișierele. - -Înainte de a vă familiariza cu el, asigurați-vă că faceți mai întâi o copie de rezervă a fișierelor. - -Pentru o rulare mai ușoară, putem crea un fișier `code.bat`: - -```shell -php cale_catre_Nette_tools\Code-Checker\code-checker %* -``` - - -Ce face? -======== - -- elimină [BOM |nette:glossary#BOM] -- verifică validitatea șabloanelor [Latte |latte:] -- verifică validitatea fișierelor `.neon`, `.php` și `.json` -- verifică prezența [caracterelor de control |nette:glossary#Caractere de control] -- verifică dacă fișierul este codificat în UTF-8 -- verifică `/* @adnotari */` scrise incorect (lipsește asteriscul) -- elimină `?>` de la sfârșitul fișierelor PHP -- elimină spațiile de la sfârșitul rândului și rândurile goale inutile de la sfârșitul fișierului -- normalizează separatorii de rând la cei de sistem (dacă specificați opțiunea `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/ru/@home.texy b/code-checker/ru/@home.texy deleted file mode 100644 index 911ba624aa..0000000000 --- a/code-checker/ru/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Инструмент [Code Checker |https://github.com/nette/code-checker] проверяет и при необходимости исправляет некоторые формальные ошибки в ваших исходных кодах. - - -Установка -========= - -Code Checker не следует добавлять в зависимости, а устанавливать как проект. - -```shell -composer create-project nette/code-checker -``` - -Или установите его глобально с помощью: - -```shell -composer global require nette/code-checker -``` - -и убедитесь, что ваш глобальный каталог `vendor/bin` находится в [переменной окружения $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Использование -============= - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Без параметров проверяет текущий каталог в режиме только для чтения, с параметром `-f` исправляет файлы. - -Прежде чем ознакомиться с ним, обязательно сделайте резервную копию файлов. - -Для более легкого запуска можно создать файл `code.bat`: - -```shell -php path_to_Nette_tools\Code-Checker\code-checker %* -``` - - -Что он делает? -============== - -- удаляет [BOM |nette:glossary#BOM] -- проверяет валидность шаблонов [Latte |latte:] -- проверяет валидность файлов `.neon`, `.php` и `.json` -- проверяет наличие [управляющих символов |nette:glossary#Управляющие символы] -- проверяет, закодирован ли файл в UTF-8 -- проверяет неправильно записанные `/* @anotace */` (отсутствует звездочка) -- удаляет завершающий `?>` у PHP-файлов -- удаляет пробелы в конце строк и лишние строки в конце файла -- нормализует разделители строк до системных (если указана опция `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/sl/@home.texy b/code-checker/sl/@home.texy deleted file mode 100644 index 27cbc98ca0..0000000000 --- a/code-checker/sl/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Orodje [Code Checker |https://github.com/nette/code-checker] preveri in po potrebi popravi nekatere formalne napake v vaših izvornih kodah. - - -Namestitev -========== - -Code Checkerja ne bi smeli dodajati med odvisnosti, ampak ga namestiti kot projekt. - -```shell -composer create-project nette/code-checker -``` - -Ali pa ga namestite globalno s pomočjo: - -```shell -composer global require nette/code-checker -``` - -in se prepričajte, da je vaš globalni imenik `vendor/bin` v [okoljski spremenljivki $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Uporaba -======= - -``` -Usage: php code-checker [options] - -Options: - -d Folder or file to scan (default: current directory) - -i | --ignore Files to ignore - -f | --fix Fixes files - -l | --eol Convert newline characters - --no-progress Do not show progress dots - --strict-types Checks whether PHP 7.0 directive strict_types is enabled -``` - -Brez parametrov preveri trenutni imenik v načinu samo za branje, s parametrom `-f` popravlja datoteke. - -Preden se z njim seznanite, si vsekakor najprej varnostno kopirajte datoteke. - -Za lažje zaganjanje si lahko ustvarimo datoteko `code.bat`: - -```shell -php pot_do_Nette_tools\Code-Checker\code-checker %* -``` - - -Kaj vse počne? -============== - -- odstranjuje [BOM |nette:glossary#BOM] -- preverja veljavnost [Latte |latte:] predlog -- preverja veljavnost datotek `.neon`, `.php` in `.json` -- preverja pojav [kontrolnih znakov |nette:glossary#Kontrolni znaki] -- preverja, ali je datoteka kodirana v UTF-8 -- preverja napačno zapisane `/* @anotace */` (manjka zvezdica) -- odstranjuje zaključne `?>` pri PHP datotekah -- odstranjuje desne presledke in nepotrebne vrstice na koncu datoteke -- normalizira ločila vrstic na sistemske (če navedete opcijo `-l`) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/tr/@home.texy b/code-checker/tr/@home.texy deleted file mode 100644 index ea2e1ecb22..0000000000 --- a/code-checker/tr/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -[Kod Denetleyicisi |https://github.com/nette/code-checker] aracı, kaynak kodlarınızdaki bazı biçimsel hataları kontrol eder ve gerekirse düzeltir. - - -Kurulum -======= - -Kod Denetleyicisini bağımlılıklara eklememeli, bir proje olarak kurmalısınız. - -```shell -composer create-project nette/code-checker -``` - -Veya küresel olarak kurun: - -```shell -composer global require nette/code-checker -``` - -ve küresel `vendor/bin` dizininizin [$PATH ortam değişkeninde |https://getcomposer.org/doc/03-cli.md#global] olduğundan emin olun. - - -Kullanım -======== - -``` -Usage: php code-checker [options] - -Options: - -d Taranacak klasör veya dosya (varsayılan: geçerli dizin) - -i | --ignore Yoksayılacak dosyalar - -f | --fix Dosyaları düzeltir - -l | --eol Yeni satır karakterlerini dönüştürür - --no-progress İlerleme noktalarını gösterme - --strict-types PHP 7.0 direktifi strict_types'ın etkin olup olmadığını kontrol eder -``` - -Parametresiz olarak geçerli dizini salt okunur modda kontrol eder, `-f` parametresiyle dosyaları düzeltir. - -Tanışmadan önce dosyalarınızı mutlaka yedekleyin. - -Daha kolay çalıştırmak için bir `code.bat` dosyası oluşturabiliriz: - -```shell -php nette_araçlarının_yolu\Code-Checker\code-checker %* -``` - - -Ne yapar? -========= - -- [BOM |nette:glossary#BOM] kaldırır -- [Latte |latte:] şablonlarının geçerliliğini kontrol eder -- `.neon`, `.php` ve `.json` dosyalarının geçerliliğini kontrol eder -- [Kontrol karakterlerinin |nette:glossary#Kontrol Karakterleri] varlığını kontrol eder -- Dosyanın UTF-8 olarak kodlanıp kodlanmadığını kontrol eder -- Yanlış yazılmış `/* @anotace */` (yıldız eksik) kontrol eder -- PHP dosyalarındaki kapanış `?>` etiketini kaldırır -- Sağdaki boşlukları ve dosyanın sonundaki gereksiz satırları kaldırır -- Satır ayırıcılarını sistem varsayılanına normalleştirir (`-l` seçeneğini belirtirseniz) - -{{leftbar: www:@menu-common}} diff --git a/code-checker/uk/@home.texy b/code-checker/uk/@home.texy deleted file mode 100644 index 261ea7550c..0000000000 --- a/code-checker/uk/@home.texy +++ /dev/null @@ -1,65 +0,0 @@ -Nette Code Checker -****************** - -.[perex] -Інструмент [Code Checker |https://github.com/nette/code-checker] перевіряє та, за потреби, виправляє деякі формальні помилки у ваших вихідних кодах. - - -Встановлення -============ - -Code Checker не слід додавати до залежностей, а встановлювати як проект. - -```shell -composer create-project nette/code-checker -``` - -Або встановіть його глобально за допомогою: - -```shell -composer global require nette/code-checker -``` - -і переконайтеся, що ваш глобальний каталог `vendor/bin` знаходиться у [змінній середовища $PATH |https://getcomposer.org/doc/03-cli.md#global]. - - -Використання -============ - -``` -Usage: php code-checker [options] - -Options: - -d Папка або файл для сканування (за замовчуванням: поточний каталог) - -i | --ignore Файли, які слід ігнорувати - -f | --fix Виправляє файли - -l | --eol Перетворює символи нового рядка - --no-progress Не показувати точки прогресу - --strict-types Перевіряє, чи увімкнена директива PHP 7.0 strict_types -``` - -Без параметрів перевіряє поточний каталог у режимі лише для читання, з параметром `-f` виправляє файли. - -Перш ніж ознайомитися з ним, обов'язково зробіть резервну копію файлів. - -Для полегшення запуску можна створити файл `code.bat`: - -```shell -php шлях_до_Nette_tools\Code-Checker\code-checker %* -``` - - -Що він робить? -============== - -- видаляє [BOM |nette:glossary#BOM] -- перевіряє валідність [Latte |latte:] шаблонів -- перевіряє валідність файлів `.neon`, `.php` та `.json` -- перевіряє наявність [керуючих символів |nette:glossary#Керуючі символи] -- перевіряє, чи файл закодований у UTF-8 -- перевіряє неправильно записані `/* @anotace */` (відсутня зірочка) -- видаляє завершальний `?>` у PHP файлах -- видаляє пробіли в кінці рядка та зайві рядки в кінці файлу -- нормалізує роздільники рядків до системних (якщо вказано опцію `-l`) - -{{leftbar: www:@menu-common}} diff --git a/contributing/bg/documentation.texy b/contributing/bg/documentation.texy index 4f03aca70a..0bf4828e7d 100644 --- a/contributing/bg/documentation.texy +++ b/contributing/bg/documentation.texy @@ -52,7 +52,7 @@ 1) В GitHub си създайте [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] на хранилището [nette/docs |https://github.com/nette/docs] 2) [Клонирайте |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] това хранилище на своя компютър 3) След това в [съответния branch |#Структура на документацията] направете промените -4) Проверете за излишни интервали в текста с помощта на инструмента [Code-Checker |code-checker:] +4) Проверете за излишни интервали в текста с помощта на инструмента [Code-Checker |tools:code-checker] 4) Запазете промените (commit) 6) Ако сте доволни от промените, изпратете ги (push) в GitHub към вашия fork 7) Оттам ги изпратете към хранилището `nette/docs`, като създадете [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/cs/coding-standard.texy b/contributing/cs/coding-standard.texy index aaef617655..95e9155667 100644 --- a/contributing/cs/coding-standard.texy +++ b/contributing/cs/coding-standard.texy @@ -6,6 +6,9 @@ Tento dokument popisuje pravidla a doporučení pro vývoj Nette. Při přispív Nette Coding Standard odpovídá [PSR-12 Extended Coding Style |https://www.php-fig.org/psr/psr-12/] se dvěma hlavními výjimkami: pro odsazení používá [#tabulátory místo mezer] a pro [konstanty tříd používá PascalCase|https://blog.nette.org/cs/za-mene-kriku-v-kodu]. +.[tip] +Mnoho z těchto pravidel umí automaticky kontrolovat a opravovat nástroj [Nette Coding Standard |tools:coding-standard], takže je nemusíte hlídat ručně. + Obecná pravidla =============== @@ -14,7 +17,7 @@ Obecná pravidla - Dva prázdné řádky se používají k oddělení metod pro lepší čitelnost. - Důvod použití shut-up operátoru musí být zdokumentován: `@mkdir($dir); // @ - adresář může existovat`. - Pokud je použit slabě typizovaný operátor porovnání (tj. `==`, `!=`, ...), musí být zdokumentován záměr: `// == přijmout null` -- Do jednoho souboru `exceptions.php` můžete zapsat více výjimek. +- Do jednoho souboru `exceptions.php` můžete zapsat více výjimek, do souboru `enums.php` více enumů. - U rozhraní se nespecifikuje viditelnost metod, protože jsou vždy veřejné. - Každá property, návratová hodnota a parametr musí mít uvedený typ. Naopak u finálních konstant typ nikdy neuvádíme, protože je zjevný. - K ohraničení řetězce by se měly používat jednoduché uvozovky, s výjimkou případů, kdy samotný literál obsahuje apostrofy. diff --git a/contributing/cs/documentation.texy b/contributing/cs/documentation.texy index c02587a359..130bbc6d31 100644 --- a/contributing/cs/documentation.texy +++ b/contributing/cs/documentation.texy @@ -52,7 +52,7 @@ Dokumentaci upravujte tímto způsobem: 1) na GitHubu si vytvořte [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] repositáře [nette/docs |https://github.com/nette/docs] 2) tento repositář [naklonujete |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] na svůj počítač 3) poté v [příslušné větvi |#Struktura dokumentace] proveďte změny -4) zkontroluje přebytečné mezery v textu pomocí nástroje [Code-Checker |code-checker:] +4) zkontroluje přebytečné mezery v textu pomocí nástroje [Code-Checker |tools:code-checker] 4) změny uložte (commitněte) 6) pokud jste se změnami spokojeni, odešlete (pushněte) je na GitHub do vašeho forku 7) odtud je odešlete do repositáře `nette/docs` vytvořením [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/de/documentation.texy b/contributing/de/documentation.texy index 1461cd05c5..58a2bc6fd7 100644 --- a/contributing/de/documentation.texy +++ b/contributing/de/documentation.texy @@ -52,7 +52,7 @@ Bearbeiten Sie die Dokumentation auf diese Weise: 1) Erstellen Sie auf GitHub einen [Fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] des Repositorys [nette/docs |https://github.com/nette/docs]. 2) [Klonen |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] Sie dieses Repository auf Ihren Computer. 3) Nehmen Sie dann im [entsprechenden Branch |#Struktur der Dokumentation] die Änderungen vor. -4) Überprüfen Sie überflüssige Leerzeichen im Text mit dem Werkzeug [Code-Checker |code-checker:]. +4) Überprüfen Sie überflüssige Leerzeichen im Text mit dem Werkzeug [Code-Checker |tools:code-checker]. 5) Speichern (committen) Sie die Änderungen. 6) Wenn Sie mit den Änderungen zufrieden sind, senden (pushen) Sie sie auf GitHub in Ihren Fork. 7) Senden Sie sie von dort an das Repository `nette/docs`, indem Sie einen [Pull Request|https://help.github.com/articles/creating-a-pull-request] (PR) erstellen. diff --git a/contributing/el/documentation.texy b/contributing/el/documentation.texy index 28e360e165..40c2eeaab6 100644 --- a/contributing/el/documentation.texy +++ b/contributing/el/documentation.texy @@ -52,7 +52,7 @@ 1) Στο GitHub, δημιουργήστε ένα [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] του αποθετηρίου [nette/docs |https://github.com/nette/docs]. 2) [Κλωνοποιήστε |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] αυτό το αποθετήριο στον υπολογιστή σας. 3) Στη συνέχεια, στον [κατάλληλο κλάδο |#Δομή της Τεκμηρίωσης] πραγματοποιήστε τις αλλαγές. -4) Ελέγξτε για περιττά κενά στο κείμενο χρησιμοποιώντας το εργαλείο [Code-Checker |code-checker:]. +4) Ελέγξτε για περιττά κενά στο κείμενο χρησιμοποιώντας το εργαλείο [Code-Checker |tools:code-checker]. 5) Αποθηκεύστε τις αλλαγές (commit). 6) Αν είστε ικανοποιημένοι με τις αλλαγές, στείλτε (push) τις στο GitHub στο δικό σας fork. 7) Από εκεί, υποβάλετέ τις στο αποθετήριο `nette/docs` δημιουργώντας ένα [pull request |https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/en/coding-standard.texy b/contributing/en/coding-standard.texy index df9a0a86cb..1f1f9cfb66 100644 --- a/contributing/en/coding-standard.texy +++ b/contributing/en/coding-standard.texy @@ -6,6 +6,9 @@ This document describes the rules and recommendations for developing Nette. When Nette Coding Standard corresponds to [PSR-12 Extended Coding Style |https://www.php-fig.org/psr/psr-12/] with two main exceptions: it uses [#tabs instead of spaces] for indentation, and uses [PascalCase for class constants|https://blog.nette.org/en/for-less-screaming-in-the-code]. +.[tip] +Many of these rules can be automatically checked and fixed by the [Nette Coding Standard |tools:coding-standard] tool, so you don't have to check them by hand. + General Rules ============= @@ -14,7 +17,7 @@ General Rules - Two empty lines are used to separate methods for better readability - The reason for using the shut-up operator (`@`) must be documented: `@mkdir($dir); // @ - directory may exist` - If a weak typed comparison operator is used (i.e., `==`, `!=`, ...), the intention must be documented: `// == to accept null` -- You can write multiple exception classes into a single file named `exceptions.php` +- You can write multiple exception classes into a single file named `exceptions.php`, and multiple enums into `enums.php` - The visibility of methods is not specified for interfaces because they are always public - Each property, return value, and parameter must have a type specified. Conversely, for final constants, we never specify the type because it is obvious - Single quotes should be used to delimit strings, except when the literal itself contains apostrophes diff --git a/contributing/en/documentation.texy b/contributing/en/documentation.texy index 3d2353444b..2406cf78b5 100644 --- a/contributing/en/documentation.texy +++ b/contributing/en/documentation.texy @@ -52,7 +52,7 @@ Edit the documentation as follows: 1) On GitHub, create a [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] of the [nette/docs |https://github.com/nette/docs] repository. 2) [Clone |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] this repository to your computer. 3) Then, make changes in the [appropriate branch |#Documentation Structure]. -4) Check for extra spaces in the text using the [Code-Checker |code-checker:] tool. +4) Check for extra spaces in the text using the [Code-Checker |tools:code-checker] tool. 5) Save (commit) the changes. 6) If you are satisfied with the changes, push them to GitHub to your fork. 7) From there, submit them to the `nette/docs` repository by creating a [pull request|https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/es/documentation.texy b/contributing/es/documentation.texy index f3e0e63004..ae4f4a4d34 100644 --- a/contributing/es/documentation.texy +++ b/contributing/es/documentation.texy @@ -52,7 +52,7 @@ Modifica la documentación de esta manera: 1) en GitHub, crea un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] del repositorio [nette/docs |https://github.com/nette/docs] 2) [clona |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] este repositorio en tu ordenador 3) luego, en la [rama apropiada |#Estructura de la documentación], realiza los cambios -4) comprueba si hay espacios sobrantes en el texto usando la herramienta [Code-Checker |code-checker:] +4) comprueba si hay espacios sobrantes en el texto usando la herramienta [Code-Checker |tools:code-checker] 5) guarda los cambios (haz commit) 6) si estás satisfecho con los cambios, envíalos (haz push) a GitHub a tu fork 7) desde allí, envíalos al repositorio `nette/docs` creando una [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/fr/documentation.texy b/contributing/fr/documentation.texy index 87d2fa6640..0ce553fc8a 100644 --- a/contributing/fr/documentation.texy +++ b/contributing/fr/documentation.texy @@ -52,7 +52,7 @@ Modifiez la documentation de cette manière : 1) Sur GitHub, créez un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] du dépôt [nette/docs |https://github.com/nette/docs]. 2) [Clonez |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] ce dépôt sur votre ordinateur. 3) Ensuite, dans la [branche appropriée |#Structure de la documentation], effectuez les modifications. -4) Vérifiez les espaces superflus dans le texte à l'aide de l'outil [Code-Checker |code-checker:]. +4) Vérifiez les espaces superflus dans le texte à l'aide de l'outil [Code-Checker |tools:code-checker]. 5) Enregistrez (commitez) les changements. 6) Si vous êtes satisfait des changements, envoyez-les (pushez) sur GitHub vers votre fork. 7) De là, envoyez-les au dépôt `nette/docs` en créant une [pull request|https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/hu/documentation.texy b/contributing/hu/documentation.texy index 7ca946186c..82e5bb4a63 100644 --- a/contributing/hu/documentation.texy +++ b/contributing/hu/documentation.texy @@ -52,7 +52,7 @@ A dokumentációt a következő módon szerkessze: 1) a GitHubon hozzon létre egy [forkot |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] a [nette/docs |https://github.com/nette/docs] repository-ból 2) ezt a repository-t [klónozza |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] a számítógépére 3) ezután a [megfelelő ágban |#Dokumentáció struktúrája] végezze el a változtatásokat -4) ellenőrizze a felesleges szóközöket a szövegben a [Code-Checker |code-checker:] eszközzel +4) ellenőrizze a felesleges szóközöket a szövegben a [Code-Checker |tools:code-checker] eszközzel 5) mentse el a változtatásokat (commitolja) 6) ha elégedett a változtatásokkal, küldje el (pusholja) őket a GitHubra a saját forkjába 7) onnan küldje el őket a `nette/docs` repository-ba egy [pull request |https://help.github.com/articles/creating-a-pull-request] (PR) létrehozásával diff --git a/contributing/it/documentation.texy b/contributing/it/documentation.texy index 93d0597b18..cdbebb2317 100644 --- a/contributing/it/documentation.texy +++ b/contributing/it/documentation.texy @@ -52,7 +52,7 @@ Modificate la documentazione in questo modo: 1) su GitHub, create un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] del repository [nette/docs |https://github.com/nette/docs] 2) [clonate |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] questo repository sul vostro computer 3) successivamente, nel [ramo appropriato |#Struttura della documentazione], apportate le modifiche -4) controllate gli spazi superflui nel testo tramite lo strumento [Code-Checker |code-checker:] +4) controllate gli spazi superflui nel testo tramite lo strumento [Code-Checker |tools:code-checker] 4) salvate (committate) le modifiche 6) se siete soddisfatti delle modifiche, inviatele (push) su GitHub al vostro fork 7) da lì, inviatele al repository `nette/docs` creando una [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/ja/documentation.texy b/contributing/ja/documentation.texy index 052c6485fd..cf0fae0bcd 100644 --- a/contributing/ja/documentation.texy +++ b/contributing/ja/documentation.texy @@ -52,7 +52,7 @@ GitHubインターフェースを利用するよりも、Gitバージョン管 1) GitHubで、[nette/docs |https://github.com/nette/docs] リポジトリの [フォーク |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] を作成します 2) このリポジトリを自分のコンピュータに [クローン |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] します 3) 次に、[関連するブランチ |#ドキュメントの構造] で変更を行います -4) [Code-Checker |code-checker:] ツールを使用して、テキスト内の余分なスペースをチェックします +4) [Code-Checker |tools:code-checker] ツールを使用して、テキスト内の余分なスペースをチェックします 4) 変更を保存(コミット)します 6) 変更に満足したら、GitHubの自分のフォークに送信(プッシュ)します 7) そこから、[プルリクエスト |https://help.github.com/articles/creating-a-pull-request] (PR) を作成して `nette/docs` リポジトリに送信します diff --git a/contributing/pl/documentation.texy b/contributing/pl/documentation.texy index d34ecbffc2..dc9560d3bd 100644 --- a/contributing/pl/documentation.texy +++ b/contributing/pl/documentation.texy @@ -52,7 +52,7 @@ Dokumentację modyfikuj w ten sposób: 1) na GitHubie utwórz [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] repozytorium [nette/docs |https://github.com/nette/docs] 2) to repozytorium [sklonujesz |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] na swój komputer 3) następnie w [odpowiedniej gałęzi |#Struktura dokumentacji] wprowadź zmiany -4) sprawdź zbędne spacje w tekście za pomocą narzędzia [Code-Checker |code-checker:] +4) sprawdź zbędne spacje w tekście za pomocą narzędzia [Code-Checker |tools:code-checker] 4) zmiany zapisz (commituj) 6) jeśli jesteś zadowolony ze zmian, wyślij (pushnij) je na GitHub do swojego forka 7) stamtąd wyślij je do repozytorium `nette/docs`, tworząc [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/pt/documentation.texy b/contributing/pt/documentation.texy index 4cf9f50cbb..55fa484724 100644 --- a/contributing/pt/documentation.texy +++ b/contributing/pt/documentation.texy @@ -52,7 +52,7 @@ Edite a documentação desta forma: 1) No GitHub, crie um [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] do repositório [nette/docs |https://github.com/nette/docs]. 2) [Clone |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] este repositório para o seu computador. 3) Em seguida, no [branch apropriado |#Estrutura da Documentação], faça as alterações. -4) Verifique se há espaços em branco extras no texto usando a ferramenta [Code-Checker |code-checker:]. +4) Verifique se há espaços em branco extras no texto usando a ferramenta [Code-Checker |tools:code-checker]. 5) Salve (commit) as alterações. 6) Se estiver satisfeito com as alterações, envie-as (push) para o GitHub no seu fork. 7) A partir daí, envie-as para o repositório `nette/docs` criando um [pull request|https://help.github.com/articles/creating-a-pull-request] (PR). diff --git a/contributing/ro/documentation.texy b/contributing/ro/documentation.texy index c51ce18e62..59f813f62f 100644 --- a/contributing/ro/documentation.texy +++ b/contributing/ro/documentation.texy @@ -52,7 +52,7 @@ Modificați documentația în acest mod: 1) pe GitHub creați un [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] al depozitului [nette/docs |https://github.com/nette/docs] 2) [clonați |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] acest depozit pe computerul dvs. 3) apoi în [ramura corespunzătoare |#Structura documentației] efectuați modificările -4) verificați spațiile în exces din text folosind instrumentul [Code-Checker |code-checker:] +4) verificați spațiile în exces din text folosind instrumentul [Code-Checker |tools:code-checker] 4) salvați modificările (commit) 6) dacă sunteți mulțumit de modificări, trimiteți-le (push) pe GitHub în fork-ul dvs. 7) de acolo le trimiteți către depozitul `nette/docs` creând un [pull request |https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/ru/documentation.texy b/contributing/ru/documentation.texy index dab56db27d..3fd2af6677 100644 --- a/contributing/ru/documentation.texy +++ b/contributing/ru/documentation.texy @@ -52,7 +52,7 @@ 1) на GitHub создайте [форк |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] репозитория [nette/docs |https://github.com/nette/docs] 2) этот репозиторий [клонируйте |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] на свой компьютер 3) затем в [соответствующей ветке |#Структура документации] внесите изменения -4) проверьте лишние пробелы в тексте с помощью инструмента [Code-Checker |code-checker:] +4) проверьте лишние пробелы в тексте с помощью инструмента [Code-Checker |tools:code-checker] 4) сохраните изменения (сделайте коммит) 6) если вы удовлетворены изменениями, отправьте (push) их на GitHub в ваш форк 7) оттуда отправьте их в репозиторий `nette/docs`, создав [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/sl/documentation.texy b/contributing/sl/documentation.texy index 8ae7191d0c..e452d2c834 100644 --- a/contributing/sl/documentation.texy +++ b/contributing/sl/documentation.texy @@ -52,7 +52,7 @@ Dokumentacijo urejajte na ta način: 1) na GitHubu si ustvarite [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] repozitorija [nette/docs |https://github.com/nette/docs] 2) ta repozitorij [klonirajte |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] na svoj računalnik 3) nato v [ustrezni veji |#Struktura dokumentacije] izvedite spremembe -4) preverite odvečne presledke v besedilu z orodjem [Code-Checker |code-checker:] +4) preverite odvečne presledke v besedilu z orodjem [Code-Checker |tools:code-checker] 4) spremembe shranite (commitnite) 6) če ste s spremembami zadovoljni, jih pošljite (pushnite) na GitHub v vaš fork 7) od tam jih pošljite v repozitorij `nette/docs` z ustvarjanjem [pull requesta|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/contributing/tr/documentation.texy b/contributing/tr/documentation.texy index b9efcf74e4..44d6aae888 100644 --- a/contributing/tr/documentation.texy +++ b/contributing/tr/documentation.texy @@ -52,7 +52,7 @@ Dokümantasyonu şu şekilde düzenleyin: 1) GitHub'da [nette/docs |https://github.com/nette/docs] deposunun bir [forkunu |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] oluşturun 2) Bu depoyu bilgisayarınıza [klonlayın |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] 3) Ardından [ilgili dalda |#Dokümantasyon yapısı] değişiklikleri yapın -4) [Code-Checker |code-checker:] aracını kullanarak metindeki fazla boşlukları kontrol edin +4) [Code-Checker |tools:code-checker] aracını kullanarak metindeki fazla boşlukları kontrol edin 5) Değişiklikleri kaydedin (commit) 6) Değişikliklerden memnunsanız, bunları GitHub'daki fork'unuza gönderin (push) 7) Oradan, bir [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) oluşturarak `nette/docs` deposuna gönderin diff --git a/contributing/uk/documentation.texy b/contributing/uk/documentation.texy index 95b53fa278..988d02cbc1 100644 --- a/contributing/uk/documentation.texy +++ b/contributing/uk/documentation.texy @@ -52,7 +52,7 @@ 1) на GitHub створіть [fork |https://help.github.com/en/github/getting-started-with-github/fork-a-repo] репозиторію [nette/docs |https://github.com/nette/docs] 2) цей репозиторій [клонуєте |https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository] на свій комп'ютер 3) потім у [відповідній гілці |#Структура документації] внесіть зміни -4) перевірте зайві пробіли в тексті за допомогою інструменту [Code-Checker |code-checker:] +4) перевірте зайві пробіли в тексті за допомогою інструменту [Code-Checker |tools:code-checker] 4) збережіть зміни (зробіть коміт) 6) якщо ви задоволені змінами, надішліть (push) їх на GitHub у ваш форк 7) звідти надішліть їх до репозиторію `nette/docs`, створивши [pull request|https://help.github.com/articles/creating-a-pull-request] (PR) diff --git a/database/bg/@left-menu.texy b/database/bg/@left-menu.texy index 928b1f73ea..d0fed337a9 100644 --- a/database/bg/@left-menu.texy +++ b/database/bg/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Трансакции |transactions] - [Изключения |exceptions] - [Рефлексия |reflection] -- [Мапинг |mapping] +- [Мапинг |type-conversion] - [Конфигурация |configuration] - [Рискове за сигурността |security] - [Надграждане |en:upgrading] diff --git a/database/bg/mapping.texy b/database/bg/type-conversion.texy similarity index 100% rename from database/bg/mapping.texy rename to database/bg/type-conversion.texy diff --git a/database/cs/@left-menu.texy b/database/cs/@left-menu.texy index 6cb0892efa..1f70db2700 100644 --- a/database/cs/@left-menu.texy +++ b/database/cs/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transakce |transactions] - [Výjimky |exceptions] - [Reflexe |reflection] -- [Mapování |mapping] +- [Konverze typů |type-conversion] - [Konfigurace |configuration] - [Bezpečnostní rizika |security] - [Upgrade |upgrading] diff --git a/database/cs/exceptions.texy b/database/cs/exceptions.texy index e78dd0108d..f06d44a561 100644 --- a/database/cs/exceptions.texy +++ b/database/cs/exceptions.texy @@ -10,11 +10,14 @@ Nette Database používá hierarchii výjimek. Základní třídou je `Nette\Dat Z `DriverException` dědí následující specializované výjimky: - `ConnectionException` - signalizuje selhání připojení k databázovému serveru + - `ConnectionLostException` .{data-version:3.2.9} - spojení bylo ztraceno během operace (restart serveru, výpadek sítě, idle timeout); před dalším použitím je potřeba se znovu připojit - `ConstraintViolationException` - základní třída pro porušení databázových omezení, ze které dědí: - `ForeignKeyConstraintViolationException` - porušení cizího klíče - `NotNullConstraintViolationException` - porušení NOT NULL omezení - `UniqueConstraintViolationException` - porušení unikátnosti hodnoty - + - `CheckConstraintViolationException` .{data-version:3.2.9} - porušení CHECK omezení +- `DeadlockException` .{data-version:3.2.9} - deadlock nebo serializační konflikt zjištěný serverem; transakce byla zrušena a operaci lze zopakovat +- `LockTimeoutException` .{data-version:3.2.9} - vypršel časový limit při čekání na zámek; příkaz byl přerušen, okolní transakce obvykle zůstává otevřená Příklad zachytávání výjimky `UniqueConstraintViolationException`, která nastane, když se snažíme vložit uživatele s emailem, který už v databázi existuje (za předpokladu, že sloupec email má unikátní index). diff --git a/database/cs/explorer.texy b/database/cs/explorer.texy index 24044ef827..646e033f48 100644 --- a/database/cs/explorer.texy +++ b/database/cs/explorer.texy @@ -263,7 +263,7 @@ Usnadňuje stránkování výsledků. Přijímá číslo stránky (počítané o ```php $numOfPages = null; -$table->page(page: 3, itemsPerPage: 10, $numOfPages); +$table->page(page: 3, itemsPerPage: 10, numOfPages: $numOfPages); echo "Celkem stránek: $numOfPages"; ``` diff --git a/database/cs/mapping.texy b/database/cs/type-conversion.texy similarity index 100% rename from database/cs/mapping.texy rename to database/cs/type-conversion.texy diff --git a/database/de/@left-menu.texy b/database/de/@left-menu.texy index a174fb97e9..b52d2535b7 100644 --- a/database/de/@left-menu.texy +++ b/database/de/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transaktionen |transactions] - [Ausnahmen |exceptions] - [Reflexion |reflection] -- [Mapping |mapping] +- [Mapping |type-conversion] - [Konfiguration |configuration] - [Sicherheitsrisiken |security] - [Upgrade |en:upgrading] diff --git a/database/de/mapping.texy b/database/de/type-conversion.texy similarity index 100% rename from database/de/mapping.texy rename to database/de/type-conversion.texy diff --git a/database/el/@left-menu.texy b/database/el/@left-menu.texy index 2bfe03617b..d6e6721261 100644 --- a/database/el/@left-menu.texy +++ b/database/el/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Συναλλαγές |transactions] - [Εξαιρέσεις |exceptions] - [Reflection |reflection] -- [Αντιστοίχιση |mapping] +- [Αντιστοίχιση |type-conversion] - [Διαμόρφωση |configuration] - [Κίνδυνοι ασφαλείας |security] - [Αναβάθμιση |en:upgrading] diff --git a/database/el/mapping.texy b/database/el/type-conversion.texy similarity index 100% rename from database/el/mapping.texy rename to database/el/type-conversion.texy diff --git a/database/en/@left-menu.texy b/database/en/@left-menu.texy index f865f8027e..83c1eb8a7a 100644 --- a/database/en/@left-menu.texy +++ b/database/en/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transactions] - [Exceptions] - [Reflection] -- [Mapping] +- [Type Conversion |type-conversion] - [Configuration] - [Security Risks |security] - [Upgrading] diff --git a/database/en/exceptions.texy b/database/en/exceptions.texy index d3780dcacc..dca25c556e 100644 --- a/database/en/exceptions.texy +++ b/database/en/exceptions.texy @@ -10,11 +10,14 @@ Nette Database uses an exception hierarchy. The base class is `Nette\Database\Dr The `DriverException` class is extended by the following specialized exceptions: - `ConnectionException` – indicates a failure to connect to the database server. + - `ConnectionLostException` .{data-version:3.2.9} – the connection was dropped during an operation (server restart, network failure, idle timeout); a reconnect is required before further use. - `ConstraintViolationException` – the base class for database constraint violations, from which the following exceptions inherit: - `ForeignKeyConstraintViolationException` – violation of a foreign key constraint. - `NotNullConstraintViolationException` – violation of a NOT NULL constraint. - `UniqueConstraintViolationException` – violation of a uniqueness constraint. - + - `CheckConstraintViolationException` .{data-version:3.2.9} – violation of a CHECK constraint. +- `DeadlockException` .{data-version:3.2.9} – a deadlock or serialization failure detected by the server; the transaction was rolled back and may be retried. +- `LockTimeoutException` .{data-version:3.2.9} – a lock-wait timeout was exceeded; the statement was aborted, but the surrounding transaction typically remains open. The following example demonstrates how to catch a `UniqueConstraintViolationException`, which occurs when trying to insert a user with an email that already exists in the database (assuming the `email` column has a unique index): diff --git a/database/en/explorer.texy b/database/en/explorer.texy index dc5e7ef7af..d08f43a51e 100644 --- a/database/en/explorer.texy +++ b/database/en/explorer.texy @@ -263,7 +263,7 @@ Facilitates pagination of results. It accepts the page number (starting from 1) ```php $numOfPages = null; -$table->page(page: 3, itemsPerPage: 10, $numOfPages); +$table->page(page: 3, itemsPerPage: 10, numOfPages: $numOfPages); echo "Total pages: $numOfPages"; ``` diff --git a/database/en/mapping.texy b/database/en/type-conversion.texy similarity index 100% rename from database/en/mapping.texy rename to database/en/type-conversion.texy diff --git a/database/es/@left-menu.texy b/database/es/@left-menu.texy index 334a1f0ecd..ac119a7204 100644 --- a/database/es/@left-menu.texy +++ b/database/es/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transacciones |transactions] - [Excepciones |exceptions] - [Reflexión |reflection] -- [Mapeo |mapping] +- [Mapeo |type-conversion] - [Configuración |configuration] - [Riesgos de seguridad |security] - [Actualización |en:upgrading] diff --git a/database/es/mapping.texy b/database/es/type-conversion.texy similarity index 100% rename from database/es/mapping.texy rename to database/es/type-conversion.texy diff --git a/database/fr/@left-menu.texy b/database/fr/@left-menu.texy index bf2b375e4d..b54d7daab7 100644 --- a/database/fr/@left-menu.texy +++ b/database/fr/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transactions |transactions] - [Exceptions |exceptions] - [Réflexion |reflection] -- [Mapping |mapping] +- [Mapping |type-conversion] - [Configuration |configuration] - [Risques de sécurité |security] - [Mise à niveau |en:upgrading] diff --git a/database/fr/mapping.texy b/database/fr/type-conversion.texy similarity index 100% rename from database/fr/mapping.texy rename to database/fr/type-conversion.texy diff --git a/database/hu/@left-menu.texy b/database/hu/@left-menu.texy index 6bf3ca54b9..2b9f11fd5e 100644 --- a/database/hu/@left-menu.texy +++ b/database/hu/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Tranzakciók |transactions] - [Kivételek |exceptions] - [Reflexió |reflection] -- [Leképezés |mapping] +- [Leképezés |type-conversion] - [Konfiguráció |configuration] - [Biztonsági kockázatok |security] - [Frissítés |en:upgrading] diff --git a/database/hu/mapping.texy b/database/hu/type-conversion.texy similarity index 100% rename from database/hu/mapping.texy rename to database/hu/type-conversion.texy diff --git a/database/it/@left-menu.texy b/database/it/@left-menu.texy index 58127bb77b..421ffa9bce 100644 --- a/database/it/@left-menu.texy +++ b/database/it/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transazioni |transactions] - [Eccezioni |exceptions] - [Riflessione |reflection] -- [Mappatura |mapping] +- [Mappatura |type-conversion] - [Configurazione |configuration] - [Rischi per la sicurezza |security] - [Aggiornamento |en:upgrading] diff --git a/database/it/mapping.texy b/database/it/type-conversion.texy similarity index 100% rename from database/it/mapping.texy rename to database/it/type-conversion.texy diff --git a/database/ja/@left-menu.texy b/database/ja/@left-menu.texy index 4b7d6758d8..0103373e5c 100644 --- a/database/ja/@left-menu.texy +++ b/database/ja/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [トランザクション |transactions] - [例外 |exceptions] - [リフレクション |reflection] -- [マッピング |mapping] +- [マッピング |type-conversion] - [設定 |configuration] - [セキュリティリスク |security] - [アップグレード |en:upgrading] diff --git a/database/ja/mapping.texy b/database/ja/type-conversion.texy similarity index 100% rename from database/ja/mapping.texy rename to database/ja/type-conversion.texy diff --git a/database/pl/@left-menu.texy b/database/pl/@left-menu.texy index 635d04210c..65bd87f505 100644 --- a/database/pl/@left-menu.texy +++ b/database/pl/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transakcje |transactions] - [Wyjątki |exceptions] - [Refleksja |reflection] -- [Mapowanie |mapping] +- [Mapowanie |type-conversion] - [Konfiguracja |configuration] - [Zagrożenia bezpieczeństwa |security] - [Aktualizacja |en:upgrading] diff --git a/database/pl/mapping.texy b/database/pl/type-conversion.texy similarity index 100% rename from database/pl/mapping.texy rename to database/pl/type-conversion.texy diff --git a/database/pt/@left-menu.texy b/database/pt/@left-menu.texy index b1a45ab3c0..2d2896d66b 100644 --- a/database/pt/@left-menu.texy +++ b/database/pt/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transações |transactions] - [Exceções |exceptions] - [Reflexão |reflection] -- [Mapeamento |mapping] +- [Mapeamento |type-conversion] - [Configuração |configuration] - [Riscos de segurança |security] - [Atualização |en:upgrading] diff --git a/database/pt/mapping.texy b/database/pt/type-conversion.texy similarity index 100% rename from database/pt/mapping.texy rename to database/pt/type-conversion.texy diff --git a/database/ro/@left-menu.texy b/database/ro/@left-menu.texy index 7e37400986..db1ab4a266 100644 --- a/database/ro/@left-menu.texy +++ b/database/ro/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Tranzacții |transactions] - [Excepții |exceptions] - [Reflecție |reflection] -- [Mapare |mapping] +- [Mapare |type-conversion] - [Configurație |configuration] - [Riscuri de securitate |security] - [Actualizare |en:upgrading] diff --git a/database/ro/mapping.texy b/database/ro/type-conversion.texy similarity index 100% rename from database/ro/mapping.texy rename to database/ro/type-conversion.texy diff --git a/database/ru/@left-menu.texy b/database/ru/@left-menu.texy index 91864ddc35..88521f43d7 100644 --- a/database/ru/@left-menu.texy +++ b/database/ru/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Транзакции |transactions] - [Исключения |exceptions] - [Рефлексия |reflection] -- [Маппинг |mapping] +- [Маппинг |type-conversion] - [Конфигурация |configuration] - [Риски безопасности |security] - [Обновление |en:upgrading] diff --git a/database/ru/mapping.texy b/database/ru/type-conversion.texy similarity index 100% rename from database/ru/mapping.texy rename to database/ru/type-conversion.texy diff --git a/database/sl/@left-menu.texy b/database/sl/@left-menu.texy index 280bbea034..0a5b5c42b2 100644 --- a/database/sl/@left-menu.texy +++ b/database/sl/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Transakcije |transactions] - [Izjeme |exceptions] - [Refleksija |reflection] -- [Preslikava |mapping] +- [Preslikava |type-conversion] - [Konfiguracija |configuration] - [Varnostna tveganja |security] - [Nadgradnja |en:upgrading] diff --git a/database/sl/mapping.texy b/database/sl/type-conversion.texy similarity index 100% rename from database/sl/mapping.texy rename to database/sl/type-conversion.texy diff --git a/database/tr/@left-menu.texy b/database/tr/@left-menu.texy index 5a4cd8355f..ac89e59cd1 100644 --- a/database/tr/@left-menu.texy +++ b/database/tr/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [İşlemler |transactions] - [İstisnalar |exceptions] - [Yansıma |reflection] -- [Eşleme |mapping] +- [Eşleme |type-conversion] - [Yapılandırma |configuration] - [Güvenlik Riskleri |security] - [Yükseltme |en:upgrading] diff --git a/database/tr/mapping.texy b/database/tr/type-conversion.texy similarity index 100% rename from database/tr/mapping.texy rename to database/tr/type-conversion.texy diff --git a/database/uk/@left-menu.texy b/database/uk/@left-menu.texy index f8a09afcd7..8425fd5b2d 100644 --- a/database/uk/@left-menu.texy +++ b/database/uk/@left-menu.texy @@ -6,7 +6,7 @@ Nette Database - [Транзакції |transactions] - [Винятки |exceptions] - [Рефлексія |reflection] -- [Мапування |mapping] +- [Мапування |type-conversion] - [Конфігурація |configuration] - [Ризики безпеки |security] - [Оновлення |en:upgrading] diff --git a/database/uk/mapping.texy b/database/uk/type-conversion.texy similarity index 100% rename from database/uk/mapping.texy rename to database/uk/type-conversion.texy diff --git a/dependency-injection/bg/configuration.texy b/dependency-injection/bg/configuration.texy index 3f6bf580ca..fc5cf4c0db 100644 --- a/dependency-injection/bg/configuration.texy +++ b/dependency-injection/bg/configuration.texy @@ -8,7 +8,7 @@ Конфигурационен файл ==================== -Nette DI контейнерът се управлява лесно с помощта на конфигурационни файлове. Те обикновено се записват във [формат NEON|neon:format]. За редактиране препоръчваме [редактори с поддръжка |best-practices:editors-and-tools#IDE редактор] на този формат. +Nette DI контейнерът се управлява лесно с помощта на конфигурационни файлове. Те обикновено се записват във [формат NEON|neon:format]. За редактиране препоръчваме [редактори с поддръжка |tools:ide] на този формат.
 "decorator .[prism-token prism-atrule]":[#Decorator]: 	"Декоратор .[prism-token prism-comment]"
diff --git a/dependency-injection/cs/configuration.texy b/dependency-injection/cs/configuration.texy index d89e0ab829..07c89b97b0 100644 --- a/dependency-injection/cs/configuration.texy +++ b/dependency-injection/cs/configuration.texy @@ -8,7 +8,7 @@ Přehled konfiguračních voleb pro Nette DI kontejner. Konfigurační soubor =================== -Nette DI kontejner se snadno ovládá pomocí konfiguračních souborů. Ty se obvykle zapisují ve [formátu NEON|neon:format]. K editaci doporučujeme [editory s podporou |best-practices:editors-and-tools#IDE editor] tohoto formátu. +Nette DI kontejner se snadno ovládá pomocí konfiguračních souborů. Ty se obvykle zapisují ve [formátu NEON|neon:format]. K editaci doporučujeme [editory s podporou |tools:ide] tohoto formátu.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Dekorátor .[prism-token prism-comment]"
diff --git a/dependency-injection/cs/faq.texy b/dependency-injection/cs/faq.texy index e9842c0bba..a64b806cbe 100644 --- a/dependency-injection/cs/faq.texy +++ b/dependency-injection/cs/faq.texy @@ -88,7 +88,7 @@ Mějme na paměti [Pravidlo č. 1: nech si to předat |introduction#Pravidlo č. V této ukázce je `%myParameter%` zástupný symbol pro hodnotu parametru `myParameter`, který se předá do konstruktoru třídy `MyClass`: -```php +```neon # config.neon parameters: myParameter: Some value diff --git a/dependency-injection/cs/global-state.texy b/dependency-injection/cs/global-state.texy index d152d69973..2f7ddf5caf 100644 --- a/dependency-injection/cs/global-state.texy +++ b/dependency-injection/cs/global-state.texy @@ -93,7 +93,7 @@ Musíte podrobně procházet kód, abyste zjistili, že objekt `PaymentGateway` ```php $db = new DB('mysql:', 'user', 'password'); -$gateway = new PaymentGateway($db, ...); +$gateway = new PaymentGateway($db, /* ... */); ``` Podobný problém se objevuje i při použití globálního přístupu k databázovému spojení: diff --git a/dependency-injection/cs/services.texy b/dependency-injection/cs/services.texy index 8a86b230e9..6f4ec1bacb 100644 --- a/dependency-injection/cs/services.texy +++ b/dependency-injection/cs/services.texy @@ -433,8 +433,14 @@ services: application.application: create: MyApplication alteration: true - setup: - - '$onStartup[]' = [@resource, init] +``` + +Službu nemusíte identifikovat interním názvem, můžete na ni odkázat i jejím typem. Předchozí příklad tak lze zapsat i takto: + +```neon +services: + @Nette\Application\Application: + create: MyApplication ``` Při přepisování služby můžeme chtít odstranit původní argumenty, položky setup nebo tagy, k čemuž slouží `reset`: diff --git a/dependency-injection/de/configuration.texy b/dependency-injection/de/configuration.texy index 27e564e3b5..5eeed62bf7 100644 --- a/dependency-injection/de/configuration.texy +++ b/dependency-injection/de/configuration.texy @@ -8,7 +8,7 @@ Konfiguration des DI-Containers Konfigurationsdatei =================== -Der Nette DI Container lässt sich leicht über Konfigurationsdateien steuern. Diese werden normalerweise im [NEON-Format|neon:format] geschrieben. Zur Bearbeitung empfehlen wir [Editoren mit Unterstützung |best-practices:editors-and-tools#IDE-Editor] für dieses Format. +Der Nette DI Container lässt sich leicht über Konfigurationsdateien steuern. Diese werden normalerweise im [NEON-Format|neon:format] geschrieben. Zur Bearbeitung empfehlen wir [Editoren mit Unterstützung |tools:ide] für dieses Format.
 "decorator .[prism-token prism-atrule]":[#Decorator]: 	"Decorator .[prism-token prism-comment]"
diff --git a/dependency-injection/el/configuration.texy b/dependency-injection/el/configuration.texy index 03e6ecb64d..a90b11cf1f 100644 --- a/dependency-injection/el/configuration.texy +++ b/dependency-injection/el/configuration.texy @@ -8,7 +8,7 @@ Αρχείο διαμόρφωσης ================== -Το Nette DI Container ελέγχεται εύκολα μέσω αρχείων διαμόρφωσης. Αυτά συνήθως γράφονται σε [μορφή NEON |neon:format]. Για την επεξεργασία, συνιστούμε [editors με υποστήριξη |best-practices:editors-and-tools#IDE editor] αυτής της μορφής. +Το Nette DI Container ελέγχεται εύκολα μέσω αρχείων διαμόρφωσης. Αυτά συνήθως γράφονται σε [μορφή NEON |neon:format]. Για την επεξεργασία, συνιστούμε [editors με υποστήριξη |tools:ide] αυτής της μορφής.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Decorator .[prism-token prism-comment]"
diff --git a/dependency-injection/en/configuration.texy b/dependency-injection/en/configuration.texy index 7f42e4bc97..ba876eb354 100644 --- a/dependency-injection/en/configuration.texy +++ b/dependency-injection/en/configuration.texy @@ -8,7 +8,7 @@ Overview of configuration options for the Nette DI container. Configuration File ================== -The Nette DI container is easily controlled using configuration files. These are usually written in the [NEON format|neon:format]. We recommend using [editors with support |best-practices:editors-and-tools#IDE Editor] for this format. +The Nette DI container is easily controlled using configuration files. These are usually written in the [NEON format|neon:format]. We recommend using [editors with support |tools:ide] for this format.
 "decorator .[prism-token prism-atrule]":[#Decorator]: 	"Decorator .[prism-token prism-comment]"
diff --git a/dependency-injection/en/faq.texy b/dependency-injection/en/faq.texy index b7f65321ba..6f8b836dc9 100644 --- a/dependency-injection/en/faq.texy +++ b/dependency-injection/en/faq.texy @@ -88,7 +88,7 @@ Keep in mind [Rule #1: Let It Be Passed to You |introduction#Rule #1: Let It Be In this example, `%myParameter%` is a placeholder for the value of the `myParameter` parameter, which will be passed to the `MyClass` constructor: -```php +```neon # config.neon parameters: myParameter: Some value diff --git a/dependency-injection/en/global-state.texy b/dependency-injection/en/global-state.texy index f626392831..794f2814b3 100644 --- a/dependency-injection/en/global-state.texy +++ b/dependency-injection/en/global-state.texy @@ -93,7 +93,7 @@ You must meticulously trace the code to discover that the `PaymentGateway` objec ```php $db = new DB('mysql:', 'user', 'password'); -$gateway = new PaymentGateway($db, ...); +$gateway = new PaymentGateway($db, /* ... */); ``` A similar problem arises when using global access to a database connection: diff --git a/dependency-injection/en/services.texy b/dependency-injection/en/services.texy index d724a229cf..8da30d74ed 100644 --- a/dependency-injection/en/services.texy +++ b/dependency-injection/en/services.texy @@ -433,8 +433,14 @@ services: application.application: create: MyApplication alteration: true - setup: - - '$onStartup[]' = [@resource, init] +``` + +You don't have to identify a service by its internal name — you can refer to it by type instead. The previous example can also be written as: + +```neon +services: + @Nette\Application\Application: + create: MyApplication ``` When modifying a service, we might want to remove original arguments, setup items, or tags, using the `reset` key: diff --git a/dependency-injection/es/configuration.texy b/dependency-injection/es/configuration.texy index 8d3c0151ae..c4ab65c181 100644 --- a/dependency-injection/es/configuration.texy +++ b/dependency-injection/es/configuration.texy @@ -8,7 +8,7 @@ Resumen de las opciones de configuración para el contenedor Nette DI. Archivo de configuración ======================== -El contenedor Nette DI se controla fácilmente mediante archivos de configuración. Normalmente se escriben en [formato NEON |neon:format]. Para la edición, recomendamos [editores con soporte |best-practices:editors-and-tools#Editor IDE] para este formato. +El contenedor Nette DI se controla fácilmente mediante archivos de configuración. Normalmente se escriben en [formato NEON |neon:format]. Para la edición, recomendamos [editores con soporte |tools:ide] para este formato.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Decorador .[prism-token prism-comment]"
diff --git a/dependency-injection/fr/configuration.texy b/dependency-injection/fr/configuration.texy index a5167ac052..8b37bad212 100644 --- a/dependency-injection/fr/configuration.texy +++ b/dependency-injection/fr/configuration.texy @@ -8,7 +8,7 @@ Aperçu des options de configuration pour le conteneur Nette DI. Fichier de configuration ======================== -Le conteneur Nette DI est facilement contrôlé à l'aide de fichiers de configuration. Ceux-ci sont généralement écrits au [format NEON |neon:format]. Pour l'édition, nous recommandons des [éditeurs avec support |best-practices:editors-and-tools#Éditeur IDE] pour ce format. +Le conteneur Nette DI est facilement contrôlé à l'aide de fichiers de configuration. Ceux-ci sont généralement écrits au [format NEON |neon:format]. Pour l'édition, nous recommandons des [éditeurs avec support |tools:ide] pour ce format.
 "decorator .[prism-token prism-atrule]":[#Decorator]: 	"Décorateur .[prism-token prism-comment]"
diff --git a/dependency-injection/hu/configuration.texy b/dependency-injection/hu/configuration.texy index a4f889fa85..86547cb880 100644 --- a/dependency-injection/hu/configuration.texy +++ b/dependency-injection/hu/configuration.texy @@ -8,7 +8,7 @@ A Nette DI konténer konfigurációs opcióinak áttekintése. Konfigurációs fájl ================== -A Nette DI konténer könnyen vezérelhető konfigurációs fájlok segítségével. Ezek általában [NEON formátumban|neon:format] íródnak. A szerkesztéshez [támogatással rendelkező szerkesztőket |best-practices:editors-and-tools#IDE szerkesztő] ajánlunk ehhez a formátumhoz. +A Nette DI konténer könnyen vezérelhető konfigurációs fájlok segítségével. Ezek általában [NEON formátumban|neon:format] íródnak. A szerkesztéshez [támogatással rendelkező szerkesztőket |tools:ide] ajánlunk ehhez a formátumhoz.
 "decorator .[prism-token prism-atrule]":[#Decorator]: 	"Dekorátor .[prism-token prism-comment]"
diff --git a/dependency-injection/it/configuration.texy b/dependency-injection/it/configuration.texy index 7155ff7ebf..2b484c11b2 100644 --- a/dependency-injection/it/configuration.texy +++ b/dependency-injection/it/configuration.texy @@ -8,7 +8,7 @@ Panoramica delle opzioni di configurazione per il container Nette DI. File di configurazione ====================== -Il container Nette DI è facilmente controllabile tramite file di configurazione. Questi sono solitamente scritti nel [formato NEON|neon:format]. Per la modifica, consigliamo [editor con supporto |best-practices:editors-and-tools#Editor IDE] per questo formato. +Il container Nette DI è facilmente controllabile tramite file di configurazione. Questi sono solitamente scritti nel [formato NEON|neon:format]. Per la modifica, consigliamo [editor con supporto |tools:ide] per questo formato.
 "decorator .[prism-token prism-atrule]":[#Decorator]: 	"Decorator .[prism-token prism-comment]"
diff --git a/dependency-injection/ja/configuration.texy b/dependency-injection/ja/configuration.texy index b9510329cf..f6c4f5403e 100644 --- a/dependency-injection/ja/configuration.texy +++ b/dependency-injection/ja/configuration.texy @@ -8,7 +8,7 @@ Nette DIコンテナの設定オプションの概要。 設定ファイル ====== -Nette DIコンテナは、設定ファイルを使用して簡単に制御できます。これらは通常、[NEON形式|neon:format]で記述されます。編集には、この形式を[サポートするエディタ |best-practices:editors-and-tools#IDEエディタ]をお勧めします。 +Nette DIコンテナは、設定ファイルを使用して簡単に制御できます。これらは通常、[NEON形式|neon:format]で記述されます。編集には、この形式を[サポートするエディタ |tools:ide]をお勧めします。
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"デコレータ .[prism-token prism-comment]"
diff --git a/dependency-injection/pl/configuration.texy b/dependency-injection/pl/configuration.texy index d56a300da7..f487322922 100644 --- a/dependency-injection/pl/configuration.texy +++ b/dependency-injection/pl/configuration.texy @@ -8,7 +8,7 @@ Przegląd opcji konfiguracyjnych dla kontenera Nette DI. Plik konfiguracyjny =================== -Kontener Nette DI łatwo się kontroluje za pomocą plików konfiguracyjnych. Zazwyczaj są one zapisywane w [formacie NEON|neon:format]. Do edycji polecamy [edytory z obsługą |best-practices:editors-and-tools#Edytor IDE] tego formatu. +Kontener Nette DI łatwo się kontroluje za pomocą plików konfiguracyjnych. Zazwyczaj są one zapisywane w [formacie NEON|neon:format]. Do edycji polecamy [edytory z obsługą |tools:ide] tego formatu.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Dekorator .[prism-token prism-comment]"
diff --git a/dependency-injection/pt/configuration.texy b/dependency-injection/pt/configuration.texy index e22c943046..000779a38b 100644 --- a/dependency-injection/pt/configuration.texy +++ b/dependency-injection/pt/configuration.texy @@ -8,7 +8,7 @@ Visão geral das opções de configuração para o contêiner Nette DI. Arquivo de Configuração ======================= -O contêiner Nette DI é facilmente controlado por meio de arquivos de configuração. Eles geralmente são escritos no [formato NEON|neon:format]. Para edição, recomendamos [editores com suporte |best-practices:editors-and-tools#Editor IDE] para este formato. +O contêiner Nette DI é facilmente controlado por meio de arquivos de configuração. Eles geralmente são escritos no [formato NEON|neon:format]. Para edição, recomendamos [editores com suporte |tools:ide] para este formato.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Decorador .[prism-token prism-comment]"
diff --git a/dependency-injection/ro/configuration.texy b/dependency-injection/ro/configuration.texy index c78aeade7a..250662de49 100644 --- a/dependency-injection/ro/configuration.texy +++ b/dependency-injection/ro/configuration.texy @@ -8,7 +8,7 @@ Prezentare generală a opțiunilor de configurare pentru containerul Nette DI. Fișier de configurare ===================== -Containerul Nette DI este ușor de controlat folosind fișiere de configurare. Acestea sunt de obicei scrise în [formatul NEON |neon:format]. Pentru editare, recomandăm [editoare cu suport |best-practices:editors-and-tools#Editor IDE] pentru acest format. +Containerul Nette DI este ușor de controlat folosind fișiere de configurare. Acestea sunt de obicei scrise în [formatul NEON |neon:format]. Pentru editare, recomandăm [editoare cu suport |tools:ide] pentru acest format.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Decorator .[prism-token prism-comment]"
diff --git a/dependency-injection/ru/configuration.texy b/dependency-injection/ru/configuration.texy index bc18331de9..c7fad100ee 100644 --- a/dependency-injection/ru/configuration.texy +++ b/dependency-injection/ru/configuration.texy @@ -8,7 +8,7 @@ Файл конфигурации ================= -DI-контейнер Nette легко управляется с помощью файлов конфигурации. Они обычно записываются в [формате NEON |neon:format]. Для редактирования рекомендуем [редакторы с поддержкой |best-practices:editors-and-tools#IDE редактор] этого формата. +DI-контейнер Nette легко управляется с помощью файлов конфигурации. Они обычно записываются в [формате NEON |neon:format]. Для редактирования рекомендуем [редакторы с поддержкой |tools:ide] этого формата.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Декоратор .[prism-token prism-comment]"
diff --git a/dependency-injection/sl/configuration.texy b/dependency-injection/sl/configuration.texy index d4b773c1a5..f025ad8f51 100644 --- a/dependency-injection/sl/configuration.texy +++ b/dependency-injection/sl/configuration.texy @@ -8,7 +8,7 @@ Pregled konfiguracijskih možnosti za Nette DI vsebnik. Konfiguracijska datoteka ======================== -Nette DI vsebnik se enostavno upravlja s konfiguracijskimi datotekami. Te se običajno zapisujejo v [formatu NEON|neon:format]. Za urejanje priporočamo [urejevalnike s podporo |best-practices:editors-and-tools#IDE urejevalnik] za ta format. +Nette DI vsebnik se enostavno upravlja s konfiguracijskimi datotekami. Te se običajno zapisujejo v [formatu NEON|neon:format]. Za urejanje priporočamo [urejevalnike s podporo |tools:ide] za ta format.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Dekorator .[prism-token prism-comment]"
diff --git a/dependency-injection/tr/configuration.texy b/dependency-injection/tr/configuration.texy index 41b28cddb2..4745a572c6 100644 --- a/dependency-injection/tr/configuration.texy +++ b/dependency-injection/tr/configuration.texy @@ -8,7 +8,7 @@ Nette DI konteyneri için yapılandırma seçeneklerine genel bakış. Yapılandırma Dosyası ==================== -Nette DI konteyneri, yapılandırma dosyaları aracılığıyla kolayca kontrol edilir. Bunlar genellikle [NEON formatı |neon:format] kullanılarak yazılır. Düzenleme için bu formatı [destekleyen düzenleyiciler |best-practices:editors-and-tools#IDE Editörü] öneririz. +Nette DI konteyneri, yapılandırma dosyaları aracılığıyla kolayca kontrol edilir. Bunlar genellikle [NEON formatı |neon:format] kullanılarak yazılır. Düzenleme için bu formatı [destekleyen düzenleyiciler |tools:ide] öneririz.
 "decorator .[prism-token prism-atrule]":[#Dekoratör Decorator]: 	"Dekoratör .[prism-token prism-comment]"
diff --git a/dependency-injection/uk/configuration.texy b/dependency-injection/uk/configuration.texy index be8b7c4869..fecac3fb0c 100644 --- a/dependency-injection/uk/configuration.texy +++ b/dependency-injection/uk/configuration.texy @@ -8,7 +8,7 @@ Конфігураційний файл ==================== -Nette DI-контейнер легко керується за допомогою конфігураційних файлів. Вони зазвичай записуються у [форматі NEON|neon:format]. Для редагування рекомендуємо [редактори з підтримкою |best-practices:editors-and-tools#IDE редактор] цього формату. +Nette DI-контейнер легко керується за допомогою конфігураційних файлів. Вони зазвичай записуються у [форматі NEON|neon:format]. Для редагування рекомендуємо [редактори з підтримкою |tools:ide] цього формату.
 "decorator .[prism-token prism-atrule]":[#decorator]: 	"Декоратор .[prism-token prism-comment]"
diff --git a/forms/cs/in-presenter.texy b/forms/cs/in-presenter.texy index 2c827d31f7..d49fa4168e 100644 --- a/forms/cs/in-presenter.texy +++ b/forms/cs/in-presenter.texy @@ -359,7 +359,7 @@ Zmíněný CSRF útok spočívá v tom, že útočník naláká oběť na strán $form->allowCrossOrigin(); // POZOR! Vypne ochranu! ``` -Tato ochrana využívá SameSite cookie pojmenovanou `_nss`. Ochrana pomocí SameSite cookie nemusí být 100% spolehlivá, proto je vhodné zapnout ještě ochranu pomocí tokenu: +Tato ochrana se opírá o hlavičky `Sec-Fetch-*` (Fetch Metadata), které prohlížeč posílá automaticky. Starší prohlížeče, které je neposílají, nejsou pokryté, proto je vhodné zapnout ještě ochranu pomocí tokenu: ```php $form->addProtection(); diff --git a/forms/cs/standalone.texy b/forms/cs/standalone.texy index 1b980ceeda..51153c9d33 100644 --- a/forms/cs/standalone.texy +++ b/forms/cs/standalone.texy @@ -304,9 +304,9 @@ Zmíněný CSRF útok spočívá v tom, že útočník naláká oběť na strán $form->allowCrossOrigin(); // POZOR! Vypne ochranu! ``` -Tato ochrana využívá SameSite cookie pojmenovanou `_nss`. Vytvářejte proto objekt formuláře ještě před odesláním prvního výstupu, aby bylo možné cookie odeslat. +Tato ochrana se opírá o hlavičky `Sec-Fetch-*` (Fetch Metadata), které prohlížeč posílá automaticky s požadavkem. -Ochrana pomocí SameSite cookie nemusí být 100% spolehlivá, proto je vhodné zapnout ještě ochranu pomocí tokenu: +Starší prohlížeče, které tyto hlavičky neposílají, nejsou pokryté, proto je vhodné zapnout ještě ochranu pomocí tokenu: ```php $form->addProtection(); diff --git a/forms/en/in-presenter.texy b/forms/en/in-presenter.texy index b4cde43641..1dd522dc93 100644 --- a/forms/en/in-presenter.texy +++ b/forms/en/in-presenter.texy @@ -359,7 +359,7 @@ The mentioned CSRF attack involves an attacker luring a victim to a page that si $form->allowCrossOrigin(); // WARNING! Disables protection! ``` -This protection uses a SameSite cookie named `_nss`. SameSite cookie protection might not be 100% reliable, so it's advisable to also enable token protection: +This protection relies on the browser's `Sec-Fetch-*` headers (Fetch Metadata), which it sends automatically. Older browsers that don't send them are not covered, so it's advisable to also enable token protection: ```php $form->addProtection(); diff --git a/forms/en/standalone.texy b/forms/en/standalone.texy index 0260668a0e..8cb60618aa 100644 --- a/forms/en/standalone.texy +++ b/forms/en/standalone.texy @@ -304,9 +304,9 @@ The mentioned CSRF attack involves an attacker luring a victim to a page that si $form->allowCrossOrigin(); // WARNING! Disables protection! ``` -This protection uses a SameSite cookie named `_nss`. Therefore, create the form object before sending the first output so that the cookie can be sent. +This protection relies on the browser's `Sec-Fetch-*` headers (Fetch Metadata), which it sends automatically with the request. -SameSite cookie protection may not be 100% reliable, so it's advisable to also enable token protection: +Older browsers that don't send these headers are not covered, so it's advisable to also enable token protection: ```php $form->addProtection(); diff --git a/http/cs/@home.texy b/http/cs/@home.texy index 47814c400d..8442d4fdbb 100644 --- a/http/cs/@home.texy +++ b/http/cs/@home.texy @@ -2,7 +2,14 @@ Nette HTTP ********** .[perex] -Balíček `nette/http` zapouzdřuje [HTTP request|request] & [response], práci se [sessions] a [parsování a skládání URL |urls]. +Balíček `nette/http` je vaším pomocníkem pro veškerou komunikaci přes HTTP. Poskytuje srozumitelné objektové API nad příchozím požadavkem a odchozí odpovědí, usnadňuje práci se sessions i s URL adresami a navíc se postará o bezpečnost. Co v něm najdete: + +| [HTTP request |request] | příchozí požadavek a sanitizace vstupů +| [HTTP response |response] | odchozí odpověď, hlavičky a cookies +| [Sessions] | bezpečné uchování stavu mezi požadavky +| [Práce s URL |urls] | parsování a skládání URL adres +| [Ochrana proti SSRF |ssrf] | obrana proti útokům Server-Side Request Forgery +| [Konfigurace |configuration] | konfigurační volby balíčku Instalace diff --git a/http/cs/@left-menu.texy b/http/cs/@left-menu.texy index 8753fc54a5..59dfcdcb47 100644 --- a/http/cs/@left-menu.texy +++ b/http/cs/@left-menu.texy @@ -4,5 +4,6 @@ Nette HTTP - [HTTP request|request] - [HTTP response|response] - [Sessions] -- [URL utilities |urls] +- [Práce s URL |urls] +- [Ochrana proti SSRF |ssrf] - [Konfigurace |configuration] diff --git a/http/cs/configuration.texy b/http/cs/configuration.texy index 4d9bc137d9..cd73811488 100644 --- a/http/cs/configuration.texy +++ b/http/cs/configuration.texy @@ -108,6 +108,18 @@ http: ``` +Vynucení HTTPS .{data-version:3.3.4} +------------------------------------ + +Bezpodmínečně vynutí HTTPS schéma požadavku. Hodí se pro weby běžící výhradně na HTTPS za load balancerem nebo reverzní proxy, která terminuje TLS, ale neposílá hlavičku `X-Forwarded-Proto`, takže by standardní detekce HTTPS (ani s nastavenou [#HTTP proxy]) nezabrala. + +```neon +http: + # vynutí HTTPS schéma u všech požadavků + forceHttps: true # (bool) výchozí je false +``` + + Session ======= diff --git a/http/cs/request.texy b/http/cs/request.texy index 1827f489e0..f47f8e0a33 100644 --- a/http/cs/request.texy +++ b/http/cs/request.texy @@ -146,9 +146,41 @@ isSecured(): bool .[method] Je spojení šifrované (HTTPS)? Pro správnou funkčnost může být potřeba [nastavit proxy |configuration#HTTP proxy]. -isSameSite(): bool .[method] ----------------------------- -Přichází požadavek ze stejné (sub)domény a je iniciován kliknutím na odkaz? Nette k detekci používá cookie `_nss` (dříve `nette-samesite`). +isSameSite(): bool .[method deprecated] +--------------------------------------- +Přišel požadavek ze stejné stránky (same-site)? Od verze 3.4 ji nahrazuje schopnější metoda [isFrom() |#isFrom]. + + +isFrom(FetchSite|array $site, FetchDest|array|null $dest=null, ?bool $user=null): bool .[method]{data-version:3.4} +------------------------------------------------------------------------------------------------------------------ +Řekne vám, odkud požadavek přišel a jak ho prohlížeč vytvořil, na základě hlaviček `Sec-Fetch-*` (tzv. [Fetch Metadata |https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header]), které prohlížeč nastavuje sám a stránka běžící v prohlížeči oběti je nedokáže zfalšovat ani odstranit. Nette ji interně používá k automatické ochraně formulářů a signálů před útoky [Cross-Site Request Forgery |nette:glossary#Cross-Site Request Forgery CSRF] (CSRF). Hodí se, když chcete ochránit vlastní citlivé akce, jako jsou API endpointy nebo destruktivní odkazy. + +Metoda vrátí `true` pouze tehdy, když požadavek splňuje **všechny** zadané podmínky. První parametr `$site` popisuje vztah mezi stránkou, která požadavek vyvolala, a vaším webem (hlavička `Sec-Fetch-Site`). Přijímá jednu hodnotu nebo pole těchto hodnot výčtu `FetchSite`: + +- `FetchSite::SameOrigin` – ze zcela stejného původu (schéma, host i port) +- `FetchSite::SameSite` – ze stejného webu, případně z jiné subdomény +- `FetchSite::CrossSite` – z cizího webu +- `FetchSite::None` – uživatel jej vyvolal přímo, např. zadáním URL nebo otevřením záložky + +```php +// přišel požadavek z našich vlastních stránek? +if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) { + // akci zablokujeme +} +``` + +Volitelný parametr `$dest` (hlavička `Sec-Fetch-Dest`) udává, jaký druh zdroje prohlížeč načítá, např. `FetchDest::Document` pro navigaci na stránku nebo `FetchDest::Empty` pro požadavek z JavaScriptu. Volitelný parametr `$user` (hlavička `Sec-Fetch-User`) říká, zda navigaci vyvolala skutečná akce uživatele, jako kliknutí na odkaz či odeslání formuláře; hodnotou `true` ji vyžadujete. + +Kontrola, že je akce dostupná pouze z vlastních stránek a jen skutečnou akcí uživatele, pak vypadá takto: + +```php +if (!$httpRequest->isFrom(FetchSite::SameOrigin, FetchDest::Document, user: true)) { + $this->error(); +} +``` + +.[note] +Starší prohlížeče (Safari před 16.4) hlavičky `Sec-Fetch-*` neposílají. Pro ně Nette použije záložně cookie `SameSite=Strict`, která dokazuje pouze to, že požadavek není cross-site. Kontrolu, která navíc vyžaduje `$dest` nebo `$user`, tak nelze tímto způsobem ověřit a v těchto prohlížečích vrátí `false` – pokud je to příliš striktní, testujte jen `$site`. isAjax(): bool .[method] @@ -236,6 +268,7 @@ RequestFactory lze před zavoláním `fromGlobals()` konfigurovat: - metodou `$factory->setBinary()` vypnete automatické čištění vstupních parametrů od kontrolních znaků a neplatných UTF-8 sekvencí. - metodou `$factory->setProxy(...)` uvedete IP adresu [proxy serveru |configuration#HTTP proxy], což je nezbytné pro správnou detekci IP adresy uživatele. +- metodou `$factory->setForceHttps()` .{data-version:3.3.4} vynutíte HTTPS schéma požadavku bez ohledu na prostředí serveru. RequestFactory umožňuje definovat filtry, které automaticky transformují části URL požadavku. Tyto filtry odstraňují nežádoucí znaky z URL, které tam mohou být vloženy například nesprávnou implementací komentářových systémů na různých webech: diff --git a/http/cs/response.texy b/http/cs/response.texy index 4732bc7a76..3ad5c46192 100644 --- a/http/cs/response.texy +++ b/http/cs/response.texy @@ -115,15 +115,16 @@ $httpResponse->sendAsFile('faktura.pdf'); ``` -setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite='Lax') .[method] --------------------------------------------------------------------------------------------------------------------------------------------------------------------- +setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, SameSite|string $sameSite='Lax', bool $partitioned=false) .[method] +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Odešle cookie. Výchozí hodnoty parametrů: -| `$path` | `'/'` | cookie má dosah na všechny cesty v (sub)doméně *(konfigurovatelné)* -| `$domain` | `null` | což znamená s dosahem na aktuální (sub)doménu, ale nikoliv její subdomény *(konfigurovatelné)* -| `$secure` | `true` | pokud web běží na HTTPS, jinak `false` *(konfigurovatelné)* -| `$httpOnly` | `true` | cookie je pro JavaScript nepřístupná -| `$sameSite` | `'Lax'` | cookie nemusí být odeslána při [přístupu z jiné domény |nette:glossary#SameSite cookie] +| `$path` | `'/'` | cookie má dosah na všechny cesty v (sub)doméně *(konfigurovatelné)* +| `$domain` | `null` | což znamená s dosahem na aktuální (sub)doménu, ale nikoliv její subdomény *(konfigurovatelné)* +| `$secure` | `true` | pokud web běží na HTTPS, jinak `false` *(konfigurovatelné)* +| `$httpOnly` | `true` | cookie je pro JavaScript nepřístupná +| `$sameSite` | `'Lax'` | cookie nemusí být odeslána při [přístupu z jiné domény |nette:glossary#SameSite cookie] +| `$partitioned` | `false` | zda je cookie partitioned, viz níže *(od verze 3.4)* Výchozí hodnoty parametrů `$path`, `$domain` a `$secure` můžete změnit v [konfiguraci |configuration#HTTP cookie]. @@ -135,7 +136,14 @@ $httpResponse->setCookie('lang', 'cs', '100 days'); Parametr `$domain` určuje, které domény mohou cookie přijímat. Není-li uveden, cookie přijímá stejná (sub)doména, jako ji nastavila, ale nikoliv její subdomény. Pokud je `$domain` zadaný, jsou zahrnuty i subdomény. Proto je uvedení `$domain` méně omezující než vynechání. Například při `$domain = 'nette.org'` jsou cookies dostupné i na všech subdoménách jako `doc.nette.org`. -Pro hodnotu `$sameSite` můžete použít konstanty `Response::SameSiteLax`, `SameSiteStrict` a `SameSiteNone`. +Hodnotu `$sameSite` můžete předat jako enum `Nette\Http\SameSite` – `SameSite::Lax`, `SameSite::Strict` nebo `SameSite::None` (fungují i řetězce `'Lax'`, `'Strict'`, `'None'`). Pokud ji nastavíte na `SameSite::None`, automaticky se zapne atribut `$secure`, protože prohlížeče cookie se `SameSite=None` bez něj odmítají. + +.{data-version:3.4} +Partitioned cookies (CHIPS) dávají cookie samostatné úložiště pro každý web nejvyšší úrovně. Když tedy služba třetí strany (například vložený widget) nastaví partitioned cookie, prohlížeč pro každý web, na kterém se widget objeví, uchovává oddělenou kopii a tyto kopie nelze vzájemně propojit pro sledování napříč weby. Zapnete je nastavením `$partitioned` na `true`; to zároveň vyžaduje atribut `$secure`, takže se zapne automaticky. + +```php +$httpResponse->setCookie('theme', 'dark', '1 year', sameSite: SameSite::None, partitioned: true); +``` deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method] diff --git a/http/cs/sessions.texy b/http/cs/sessions.texy index de10e7715f..c004573654 100644 --- a/http/cs/sessions.texy +++ b/http/cs/sessions.texy @@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method] Nastaví dobu neaktivity po které session vyexpiruje. -setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method] ---------------------------------------------------------------------------------------------------------------------- +setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, SameSite|string|null $samesite=null): static .[method] +---------------------------------------------------------------------------------------------------------------------------------- Nastavení parametrů pro cookie. Výchozí hodnoty parametrů můžete změnit v [konfiguraci |configuration#Session cookie]. diff --git a/http/cs/ssrf.texy b/http/cs/ssrf.texy new file mode 100644 index 0000000000..375a90f662 --- /dev/null +++ b/http/cs/ssrf.texy @@ -0,0 +1,183 @@ +Ochrana proti SSRF +****************** + +.[perex] +Když vaše aplikace stahuje URL zadanou uživatelem, může toho útočník zneužít a dostat se do vaší interní sítě. Třídy [#UrlValidator] a [#IPAddress] vám pomohou bránit se těmto útokům Server-Side Request Forgery (SSRF). + +→ [Instalace a požadavky |@home#Instalace] + + +Co je SSRF? +=========== + +Představte si funkci, kde uživatel zadá URL a váš server ji stáhne – avatar ze vzdálené adresy, cíl webhooku, náhled odkazu. Vypadá to neškodně, ale na adresu se připojuje server, ne prohlížeč uživatele. A server vidí místa, kam útočník nedosáhne: loopback rozhraní, privátní síť, cloudové služby. + +Útočník proto pošle URL, která místo na veřejný internet míří dovnitř. Typickými cíli jsou: + +- cloudová metadata na `http://169.254.169.254/`, která mohou prozradit přístupové klíče +- interní administrace a routery jako `http://192.168.1.1/` +- služby bez autentizace, například Redis na `http://localhost:6379/` + +Tato třída zranitelností je tak rozšířená, že patří mezi [OWASP Top 10 |https://owasp.org/Top10/]. Obranou je ověřit URL **dříve**, než ji stáhnete, a odmítnout vše, co se přeloží na neveřejnou adresu. + + +UrlValidator +============ + +[api:Nette\Http\UrlValidator] ověřuje URL proti konfigurovatelné politice: schéma, port, host, userinfo a IP adresy, na které se host přeloží. Základní použití je jediné volání: + +```php +use Nette\Http\UrlValidator; + +if (!(new UrlValidator)->allows($userUrl)) { + return; // nebezpečná URL, nestahujte ji +} +``` + +Výchozí politika je záměrně přísná – akceptuje pouze `https` na portu 443 mířící na veřejnou IP adresu. Vše ostatní (loopback, privátní rozsahy, link-local včetně cloudových metadat, rezervované rozsahy) je odmítnuto a multicast je odmítnut bezpodmínečně. To je správný výchozí bod pro stahování libovolných URL zadaných uživatelem. + + +Konfigurace politiky +-------------------- + +Politiku tvarujete přes konstruktor. Například chcete-li povolit prosté `http` na libovolném portu a dosáhnout na privátní adresy (užitečné uvnitř důvěryhodné sítě): + +```php +$validator = new UrlValidator( + schemes: ['http', 'https'], + ports: null, // libovolný port + allowPrivateIps: true, +); +``` + +Častým vzorem je omezit stahování na pevnou sadu partnerských domén pomocí allowlistu hostů. Prefix `*.` odpovídá libovolné hloubce subdomény, ale ne samotné doméně – pokud ji potřebujete, uveďte oba tvary: + +```php +$validator = new UrlValidator( + hostAllowlist: ['example.com', '*.example.com'], +); +``` + +Kompletní sada možností konstruktoru: + +| Parametr | Výchozí | Význam +|--------------------- +| `schemes` | `['https']` | povolená schémata; `[]` odmítne vše +| `ports` | `[443]` | povolené porty, `null` = libovolný; implicitní port ze schématu je respektován +| `allowPrivateIps` | `false` | povolit privátní rozsahy (10/8, 172.16/12, 192.168/16, fc00::/7) +| `allowLoopback` | `false` | povolit loopback (127.0.0.0/8, ::1) +| `allowLinkLocal` | `false` | povolit link-local vč. cloudových metadat 169.254.169.254 +| `allowReserved` | `false` | povolit rozsahy rezervované IANA +| `allowUserinfo` | `false` | povolit `user:pass@` v URL +| `hostAllowlist` | `null` | pokud je nastaven, host musí odpovídat jednomu vzoru; `[]` odmítne vše +| `hostBlocklist` | `null` | pokud je nastaven, host nesmí odpovídat žádnému vzoru + + +Metody validace +-------------- + +Validátor nabízí tři metody. `allows()` provede plnou kontrolu včetně překladu DNS – host se přeloží a **každá** A/AAAA adresa musí projít IP politikou: + +```php +(new UrlValidator)->allows($url); // bool +``` + +`allowsWithoutDns()` přeskakuje překlad DNS a kontroly IP rozsahů. Použijte ji jako rychlý předfiltr, nebo když je validace DNS delegována na stahovací vrstvu: + +```php +(new UrlValidator)->allowsWithoutDns($url); // bool +``` + +Obě metody přijímají řetězec, objekt [UrlImmutable |urls#UrlImmutable] nebo `null` (které vždy selže). + + +Obrana proti DNS rebindingu +-------------------------- + +Mezi validací a stažením je záludný souboj: útočník může při ověřování hostu vrátit bezpečnou IP a poté pro samotné stažení přepnout DNS na interní IP. K uzavření této díry vrací `getResolvedIPs()` ověřené IP adresy a vy na ně připnete spojení, aby stahování nešlo přesměrovat jinam: + +```php +$ips = (new UrlValidator)->getResolvedIPs($url); +if (!$ips) { + return; // nebezpečná URL +} + +$ch = curl_init($url); +$host = parse_url($url, PHP_URL_HOST); +curl_setopt($ch, CURLOPT_RESOLVE, ["$host:443:" . implode(',', $ips)]); +// ... proveďte požadavek +``` + +Metoda vrací pole IP řetězců (nejprve A záznamy, poté AAAA), které prošly celou politikou, nebo prázdné pole při jakémkoli selhání. Pro IP literál v URL ověří adresu přímo a žádný překlad DNS neprovádí. + + +IPAddress +========= + +[api:Nette\Http\IPAddress] je neměnný hodnotový objekt pro práci s IPv4 a IPv6 adresami. `UrlValidator` jej využívá interně, ale hodí se i samostatně, kdykoli adresy klasifikujete. Konstruktor vyhodí `Nette\InvalidArgumentException` u neplatné adresy: + +```php +use Nette\Http\IPAddress; + +$ip = new IPAddress('169.254.169.254'); +echo $ip; // '169.254.169.254' +``` + +Když nechcete výjimku, použijte tovární metodu `tryFrom()` nebo kontrolu `isValid()`: + +```php +$ip = IPAddress::tryFrom($input); // ?IPAddress +IPAddress::isValid($input); // bool +``` + + +Klasifikace adres +---------------- + +Predikáty říkají, do jaké třídy adresa patří. Klíčový je `isPublic()` – pravdivý jen pro veřejně směrovatelné adresy, což je přesně to, co obrana proti SSRF potřebuje: + +```php +$ip = new IPAddress('169.254.169.254'); +$ip->isPublic(); // false +$ip->isLinkLocal(); // true (rozsah cloudových metadat) +``` + +Kompletní sada predikátů: + +| Metoda | Testuje +|-------------------- +| `isPublic()` | veřejně směrovatelná (žádná z níže uvedených) +| `isPrivate()` | privátní rozsahy RFC 1918 / 4193 +| `isLoopback()` | 127.0.0.0/8, ::1 +| `isLinkLocal()` | 169.254.0.0/16 (vč. cloudových metadat), fe80::/10 +| `isMulticast()` | 224.0.0.0/4, ff00::/8 +| `isReserved()` | rezervováno IANA (dokumentace, CGNAT, budoucí použití, …) + + +Příslušnost k rozsahu +-------------------- + +`isInRange()` testuje, zda adresa spadá do CIDR bloku. Můžete předat síť s prefixem, nebo holou adresu pro přesnou shodu (implicitní /32 pro IPv4, /128 pro IPv6): + +```php +$ip = new IPAddress('192.168.1.50'); +$ip->isInRange('192.168.0.0/16'); // true +$ip->isInRange('10.0.0.1'); // false (přesná shoda) +``` + +Chybný vstup nebo jiná rodina IP vrací `false`. + + +IPv4-mapped IPv6 +---------------- + +Adresy zapsané jako IPv4-mapped IPv6 (například `::ffff:127.0.0.1`) jsou klasickým způsobem, jak proklouznout naivními filtry. `IPAddress` je normalizuje, takže predikáty rozsahů prohlédnou přestrojení: + +```php +$ip = new IPAddress('::ffff:127.0.0.1'); +$ip->isLoopback(); // true +$ip->isIPv4Mapped(); // true +$ip->toIPv4(); // IPAddress('127.0.0.1') +``` + +Metody `isIPv4()` a `isIPv6()` hlásí textový tvar: mapovaná adresa je IPv6, nikoli IPv4. diff --git a/http/en/@home.texy b/http/en/@home.texy index 9ae502ba2d..474b16672b 100644 --- a/http/en/@home.texy +++ b/http/en/@home.texy @@ -2,7 +2,14 @@ Nette HTTP ********** .[perex] -The `nette/http` package encapsulates [HTTP request|request] & [response], working with [sessions] and [URL parsing and building |urls]. +The `nette/http` package is your companion for all HTTP communication. It provides a clear object-oriented API over the incoming request and outgoing response, simplifies working with sessions and URL addresses, and takes care of security on top of that. Here's what you'll find: + +| [HTTP Request |request] | incoming request and input sanitization +| [HTTP Response |response] | outgoing response, headers and cookies +| [Sessions] | secure state persistence between requests +| [URL Utility |urls] | parsing and building URL addresses +| [SSRF Protection |ssrf] | defense against Server-Side Request Forgery attacks +| [Configuration] | configuration options of the package Installation diff --git a/http/en/@left-menu.texy b/http/en/@left-menu.texy index 652706062b..35f6b7d090 100644 --- a/http/en/@left-menu.texy +++ b/http/en/@left-menu.texy @@ -5,4 +5,5 @@ Nette HTTP - [HTTP Response |response] - [Sessions] - [URL Utility |urls] +- [SSRF Protection |ssrf] - [Configuration] diff --git a/http/en/configuration.texy b/http/en/configuration.texy index 64ce01eb2d..1537a3a2c4 100644 --- a/http/en/configuration.texy +++ b/http/en/configuration.texy @@ -108,6 +108,18 @@ http: ``` +Force HTTPS .{data-version:3.3.4} +--------------------------------- + +Unconditionally forces the request scheme to HTTPS. This is useful for HTTPS-only sites running behind a load balancer or reverse proxy that terminates TLS but does not pass the `X-Forwarded-Proto` header, so the standard HTTPS detection (even with [#HTTP Proxy] configured) would not catch it. + +```neon +http: + # force HTTPS scheme for all requests + forceHttps: true # (bool) defaults to false +``` + + Session ======= diff --git a/http/en/request.texy b/http/en/request.texy index 47e0232f54..d4651cf284 100644 --- a/http/en/request.texy +++ b/http/en/request.texy @@ -146,9 +146,41 @@ isSecured(): bool .[method] Is the connection encrypted (HTTPS)? Proper functionality might require [setting up a proxy |configuration#HTTP Proxy]. -isSameSite(): bool .[method] ----------------------------- -Is the request coming from the same (sub)domain and initiated by clicking a link? Nette uses the `_nss` cookie (formerly `nette-samesite`) for detection. +isSameSite(): bool .[method deprecated] +--------------------------------------- +Did the request come from the same site? Since version 3.4 it is replaced by the more capable [isFrom() |#isFrom]. + + +isFrom(FetchSite|array $site, FetchDest|array|null $dest=null, ?bool $user=null): bool .[method]{data-version:3.4} +------------------------------------------------------------------------------------------------------------------ +Tells you where the request came from and how the browser made it, based on the `Sec-Fetch-*` headers (so-called [Fetch Metadata |https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header]) that the browser sets itself and a page running in the victim's browser can neither forge nor remove. Nette uses it internally to automatically protect forms and signals against [Cross-Site Request Forgery |nette:glossary#Cross-Site Request Forgery CSRF] (CSRF). It is useful when you want to guard your own sensitive actions, such as API endpoints or destructive links. + +The method returns `true` only when the request matches **all** the conditions you provide. The first parameter `$site` describes the relationship between the page that initiated the request and your site (the `Sec-Fetch-Site` header). It accepts a single value or a list of these `FetchSite` cases: + +- `FetchSite::SameOrigin` – from the exact same origin (scheme, host, and port) +- `FetchSite::SameSite` – from the same site, possibly a different subdomain +- `FetchSite::CrossSite` – from a foreign site +- `FetchSite::None` – the user initiated it directly, e.g. by typing the URL or opening a bookmark + +```php +// did the request originate from our own pages? +if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) { + // block the action +} +``` + +The optional `$dest` parameter (the `Sec-Fetch-Dest` header) says what kind of resource the browser is fetching, e.g. `FetchDest::Document` for a top-level navigation or `FetchDest::Empty` for a request made from JavaScript. The optional `$user` parameter (the `Sec-Fetch-User` header) indicates whether the navigation was triggered by a genuine user action such as clicking a link or submitting a form; pass `true` to require it. + +A check that an action is reachable only from your own pages and only through a real user action then looks like this: + +```php +if (!$httpRequest->isFrom(FetchSite::SameOrigin, FetchDest::Document, user: true)) { + $this->error(); +} +``` + +.[note] +Older browsers (Safari before 16.4) do not send the `Sec-Fetch-*` headers. For them Nette falls back to a `SameSite=Strict` cookie that only proves the request is not cross-site. A check that additionally requires `$dest` or `$user` cannot be verified this way and returns `false` in those browsers – if that is too strict, test only `$site`. isAjax(): bool .[method] @@ -236,6 +268,7 @@ RequestFactory can be configured before calling `fromGlobals()`: - using the `$factory->setBinary()` method disables automatic cleansing of input parameters from control characters and invalid UTF-8 sequences. - using the `$factory->setProxy(...)` method specifies the IP address of the [proxy server |configuration#HTTP Proxy], which is necessary for correct detection of the user's IP address. +- using the `$factory->setForceHttps()` .{data-version:3.3.4} method forces the request scheme to HTTPS regardless of the server environment. RequestFactory allows defining filters that automatically transform parts of the URL request. These filters remove unwanted characters from URLs that might have been inserted, for example, by incorrect implementations of comment systems on various websites: diff --git a/http/en/response.texy b/http/en/response.texy index 7dbd4dca00..eeffb70588 100644 --- a/http/en/response.texy +++ b/http/en/response.texy @@ -115,15 +115,16 @@ $httpResponse->sendAsFile('invoice.pdf'); ``` -setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, ?string $sameSite='Lax') .[method] --------------------------------------------------------------------------------------------------------------------------------------------------------------------- +setCookie(string $name, string $value, $time, ?string $path=null, ?string $domain=null, ?bool $secure=null, ?bool $httpOnly=null, SameSite|string $sameSite='Lax', bool $partitioned=false) .[method] +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sends a cookie. Default parameter values: -| `$path` | `'/'` | cookie is available for all paths within the (sub)domain *(configurable)* -| `$domain` | `null` | meaning available for the current (sub)domain, but not its subdomains *(configurable)* -| `$secure` | `true` | if the site is running on HTTPS, otherwise `false` *(configurable)* -| `$httpOnly` | `true` | cookie is inaccessible to JavaScript -| `$sameSite` | `'Lax'` | cookie might not be sent during [cross-origin access |nette:glossary#SameSite cookie] +| `$path` | `'/'` | cookie is available for all paths within the (sub)domain *(configurable)* +| `$domain` | `null` | meaning available for the current (sub)domain, but not its subdomains *(configurable)* +| `$secure` | `true` | if the site is running on HTTPS, otherwise `false` *(configurable)* +| `$httpOnly` | `true` | cookie is inaccessible to JavaScript +| `$sameSite` | `'Lax'` | cookie might not be sent during [cross-origin access |nette:glossary#SameSite cookie] +| `$partitioned` | `false` | whether the cookie is partitioned, see below *(since v3.4)* You can change the default values of the `$path`, `$domain`, and `$secure` parameters in the [configuration |configuration#HTTP Cookie]. @@ -135,7 +136,14 @@ $httpResponse->setCookie('lang', 'en', '100 days'); The `$domain` parameter determines which domains can accept the cookie. If not specified, the cookie is accepted by the same (sub)domain that set it, but not its subdomains. If `$domain` is specified, subdomains are also included. Therefore, specifying `$domain` is less restrictive than omitting it. For example, with `$domain = 'nette.org'`, cookies are also available on all subdomains like `doc.nette.org`. -You can use the constants `Response::SameSiteLax`, `Response::SameSiteStrict`, and `Response::SameSiteNone` for the `$sameSite` value. +You can pass the `$sameSite` value as a `Nette\Http\SameSite` enum – `SameSite::Lax`, `SameSite::Strict`, or `SameSite::None` (the string values `'Lax'`, `'Strict'`, `'None'` work too). If you set it to `SameSite::None`, the `$secure` attribute is enabled automatically, because browsers reject a `SameSite=None` cookie that is not secure. + +.{data-version:3.4} +Partitioned cookies (CHIPS) give a cookie its own separate storage for each top-level site. So when a third-party service (such as an embedded widget) sets a partitioned cookie, the browser keeps a distinct copy for every site the widget appears on, and these copies cannot be linked together for cross-site tracking. Turn it on by setting `$partitioned` to `true`; this also requires the `$secure` attribute, so it is enabled automatically. + +```php +$httpResponse->setCookie('theme', 'dark', '1 year', sameSite: SameSite::None, partitioned: true); +``` deleteCookie(string $name, ?string $path=null, ?string $domain=null, ?bool $secure=null): void .[method] diff --git a/http/en/sessions.texy b/http/en/sessions.texy index f0831458d5..41d00779ae 100644 --- a/http/en/sessions.texy +++ b/http/en/sessions.texy @@ -183,8 +183,8 @@ setExpiration(?string $time): static .[method] Sets the inactivity time after which the session expires. -setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static .[method] ---------------------------------------------------------------------------------------------------------------------- +setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, SameSite|string|null $samesite=null): static .[method] +---------------------------------------------------------------------------------------------------------------------------------- Sets parameters for cookies. You can change the default parameter values in the [configuration |configuration#Session Cookie]. diff --git a/http/en/ssrf.texy b/http/en/ssrf.texy new file mode 100644 index 0000000000..72d7251719 --- /dev/null +++ b/http/en/ssrf.texy @@ -0,0 +1,183 @@ +SSRF Protection +*************** + +.[perex] +When your application downloads a URL supplied by a user, an attacker can abuse it to reach your internal network. The [#UrlValidator] and [#IPAddress] classes help you guard against these Server-Side Request Forgery (SSRF) attacks. + +→ [Installation and requirements |@home#Installation] + + +What is SSRF? +============= + +Imagine a feature where the user enters a URL and your server downloads it – an avatar from a remote address, a webhook target, a link preview. It looks harmless, but the server reaches the address, not the user's browser. And the server can see places the attacker can't: the loopback interface, the private network, cloud services. + +An attacker therefore submits a URL that points inward instead of to the public internet. Typical targets are: + +- cloud metadata at `http://169.254.169.254/`, which can leak access keys +- internal admin panels and routers like `http://192.168.1.1/` +- services with no authentication, such as Redis on `http://localhost:6379/` + +This class of vulnerability is so common it ranks among the [OWASP Top 10 |https://owasp.org/Top10/]. The defense is to validate the URL **before** you fetch it and to refuse anything that resolves to a non-public address. + + +UrlValidator +============ + +[api:Nette\Http\UrlValidator] checks a URL against a configurable policy: the scheme, port, host, userinfo, and the IP addresses the host resolves to. The basic usage is a single call: + +```php +use Nette\Http\UrlValidator; + +if (!(new UrlValidator)->allows($userUrl)) { + return; // unsafe URL, do not fetch it +} +``` + +The default policy is deliberately strict – it only accepts `https` on port 443 pointing to a public IP address. Everything else (loopback, private ranges, link-local including cloud metadata, reserved ranges) is rejected, and multicast is rejected unconditionally. This is the right starting point for fetching arbitrary user-supplied URLs. + + +Configuring the Policy +---------------------- + +You shape the policy through the constructor. For example, to allow plain `http` on any port and reach private addresses (useful inside a trusted network): + +```php +$validator = new UrlValidator( + schemes: ['http', 'https'], + ports: null, // any port + allowPrivateIps: true, +); +``` + +A common pattern is to restrict fetching to a fixed set of partner domains using a host allowlist. The `*.` prefix matches any subdomain depth but not the apex – list both forms if you need it: + +```php +$validator = new UrlValidator( + hostAllowlist: ['example.com', '*.example.com'], +); +``` + +The full set of constructor options: + +| Parameter | Default | Meaning +|--------------------- +| `schemes` | `['https']` | allowed schemes; `[]` rejects everything +| `ports` | `[443]` | allowed ports, `null` = any; the implicit port from the scheme is honored +| `allowPrivateIps` | `false` | allow private ranges (10/8, 172.16/12, 192.168/16, fc00::/7) +| `allowLoopback` | `false` | allow loopback (127.0.0.0/8, ::1) +| `allowLinkLocal` | `false` | allow link-local incl. cloud metadata 169.254.169.254 +| `allowReserved` | `false` | allow IANA-reserved ranges +| `allowUserinfo` | `false` | allow `user:pass@` in the URL +| `hostAllowlist` | `null` | if set, host must match one pattern; `[]` rejects all +| `hostBlocklist` | `null` | if set, host must not match any pattern + + +Validation Methods +------------------ + +The validator offers three methods. `allows()` runs the full check including DNS resolution – the host is resolved and **every** A/AAAA address must pass the IP policy: + +```php +(new UrlValidator)->allows($url); // bool +``` + +`allowsWithoutDns()` skips DNS resolution and the IP-range checks. Use it as a fast pre-filter, or when DNS validation is delegated to the fetch layer: + +```php +(new UrlValidator)->allowsWithoutDns($url); // bool +``` + +Both methods accept a string, a [UrlImmutable |urls#UrlImmutable] object, or `null` (which always fails). + + +Defeating DNS Rebinding +----------------------- + +There is a subtle race between validation and fetching: an attacker can return a safe IP when you validate the host, then switch DNS to an internal IP for the actual download. To close this hole, `getResolvedIPs()` returns the validated IP addresses, and you pin the connection to them so the fetch can't be redirected elsewhere: + +```php +$ips = (new UrlValidator)->getResolvedIPs($url); +if (!$ips) { + return; // unsafe URL +} + +$ch = curl_init($url); +$host = parse_url($url, PHP_URL_HOST); +curl_setopt($ch, CURLOPT_RESOLVE, ["$host:443:" . implode(',', $ips)]); +// ... execute the request +``` + +The method returns an array of IP strings (A records first, then AAAA) that passed the full policy, or an empty array on any failure. For an IP literal in the URL it validates the address directly and performs no DNS lookup. + + +IPAddress +========= + +[api:Nette\Http\IPAddress] is an immutable value object for working with IPv4 and IPv6 addresses. `UrlValidator` uses it internally, but it's handy on its own whenever you classify addresses. The constructor throws `Nette\InvalidArgumentException` for an invalid address: + +```php +use Nette\Http\IPAddress; + +$ip = new IPAddress('169.254.169.254'); +echo $ip; // '169.254.169.254' +``` + +When you don't want an exception, use the `tryFrom()` factory or the `isValid()` checker: + +```php +$ip = IPAddress::tryFrom($input); // ?IPAddress +IPAddress::isValid($input); // bool +``` + + +Address Classification +---------------------- + +The predicates tell you which class an address belongs to. The key one is `isPublic()` – true only for publicly routable addresses, which is exactly what an SSRF guard wants: + +```php +$ip = new IPAddress('169.254.169.254'); +$ip->isPublic(); // false +$ip->isLinkLocal(); // true (cloud metadata range) +``` + +The full set of predicates: + +| Method | Tests for +|-------------------- +| `isPublic()` | publicly routable (none of the below) +| `isPrivate()` | RFC 1918 / 4193 private ranges +| `isLoopback()` | 127.0.0.0/8, ::1 +| `isLinkLocal()` | 169.254.0.0/16 (incl. cloud metadata), fe80::/10 +| `isMulticast()` | 224.0.0.0/4, ff00::/8 +| `isReserved()` | IANA-reserved (documentation, CGNAT, future-use, …) + + +Range Membership +---------------- + +`isInRange()` tests whether the address falls within a CIDR block. You can pass a network with a prefix, or a bare address for an exact match (implicit /32 for IPv4, /128 for IPv6): + +```php +$ip = new IPAddress('192.168.1.50'); +$ip->isInRange('192.168.0.0/16'); // true +$ip->isInRange('10.0.0.1'); // false (exact match) +``` + +Malformed input or a different IP family returns `false`. + + +IPv4-mapped IPv6 +---------------- + +Addresses written as IPv4-mapped IPv6 (such as `::ffff:127.0.0.1`) are a classic way to slip past naive filters. `IPAddress` normalizes them, so the range predicates see through the disguise: + +```php +$ip = new IPAddress('::ffff:127.0.0.1'); +$ip->isLoopback(); // true +$ip->isIPv4Mapped(); // true +$ip->toIPv4(); // IPAddress('127.0.0.1') +``` + +The `isIPv4()` and `isIPv6()` methods report the textual form: a mapped address is IPv6, not IPv4. diff --git a/http/en/urls.texy b/http/en/urls.texy index 608fa0064f..6c80b9485a 100644 --- a/http/en/urls.texy +++ b/http/en/urls.texy @@ -151,7 +151,7 @@ $newUrl = $url ->withPassword('') ->withPath('/en/'); -echo $newUrl; // 'http://john:xyz%2A12@nette.org:8080/en/?name=param#footer' +echo $newUrl; // 'http://nette.org:8080/en/?name=param#footer' ``` The `UrlImmutable` class implements the `JsonSerializable` interface and has a `__toString()` method, so the object can be printed or used in data passed to `json_encode()`. diff --git a/latte/bg/custom-tags.texy b/latte/bg/custom-tags.texy index 46bbf08171..23b5b4e001 100644 --- a/latte/bg/custom-tags.texy +++ b/latte/bg/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Генериран HTML: -```html +```latte Изтриване ``` diff --git a/latte/bg/safety-first.texy b/latte/bg/safety-first.texy index 56a3b9fd91..6c7b2d9e1f 100644 --- a/latte/bg/safety-first.texy +++ b/latte/bg/safety-first.texy @@ -33,7 +33,7 @@ echo '

Резултати от търсенето за ' . $search . 'alert("Hacked!")`. Тъй като изходът не е обработен по никакъв начин, той става част от показаната страница: -```html +```latte

Резултати от търсенето за

``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; На нападателя е достатъчно като описание да вмъкне умело съставен низ `" onload="alert('Hacked!')` и ако изписването не е обработено, резултатният код ще изглежда така: -```html +```latte ``` @@ -91,7 +91,7 @@ echo '' . $imageAlt . ''; Какво точно се разбира под думата контекст? Това е място в документа със собствени правила за обработка на извежданите данни. Зависи от типа на документа (HTML, XML, CSS, JavaScript, plain text, ...) и може да се различава в конкретните му части. Например в HTML документ има цяла редица такива места (контексти), където важат много различни правила. Може би ще се изненадате колко са. Ето първите четири: -```html +```latte

#текст

@@ -108,7 +108,7 @@ echo '' . $imageAlt . ''; Контекстите също могат да се наслояват, което се случва, когато вмъкнем JavaScript или CSS в HTML. Това може да се направи по два различни начина, с елемент и с атрибут: -```html +```latte @@ -132,7 +132,7 @@ echo '' . $imageAlt . ''; Ако го извеждате в HTML текст, точно в този случай не е необходимо да правите никакви замени, защото низът не съдържа нито един знак със специално значение. Друга ситуация възниква, ако го изведете вътре в HTML атрибут, ограден с единични кавички. В такъв случай е необходимо да екранирате кавичките в HTML ентичности: -```html +```latte
``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Ако този код вмъкнем в HTML документ с помощта на ` ``` Ако обаче искахме да го вмъкнем в HTML атрибут, трябва още да екранираме кавичките в HTML ентичности: -```html +```latte
``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll И когато този низ изведем в атрибут, ще приложим още екраниране според този контекст и ще заменим `&` с `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Latte вижда шаблона по същия начин като вас. Ра Нападателят като описание на изображението вмъква умело съставен низ `foo onload=alert('Hacked!')`. Вече знаем, че Twig не може да разпознае дали променливата се извежда в потока на HTML текста, вътре в атрибут, HTML коментар и т.н., накратко не разграничава контексти. И само механично преобразува знаците `< > & ' "` в HTML ентичности. Така резултатният код ще изглежда така: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Latte вижда шаблона по същия начин като вас. Ра Latte вижда шаблона по същия начин като вас. За разлика от Twig, разбира HTML и знае, че променливата се извежда като стойност на атрибут, който не е в кавички. Затова ги допълва. Когато нападателят вмъкне същото описание, резултатният код ще изглежда така: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/cs/cookbook/grouping.texy b/latte/cs/cookbook/grouping.texy index bdb563efb5..34e1a2cff8 100644 --- a/latte/cs/cookbook/grouping.texy +++ b/latte/cs/cookbook/grouping.texy @@ -2,15 +2,17 @@ Všechno, co jste kdy chtěli vědět o seskupování *********************************************** .[perex] -Při práci s daty ve šablonách můžete často narazit na potřebu jejich seskupování nebo specifického zobrazení podle určitých kritérií. Latte pro tento účel nabízí hned několik silných nástrojů. +Při práci s daty ve šablonách často potřebujete položky seskupit, rozdělit do dávek nebo je procházet podle podmínky. Latte k tomu nabízí tři nástroje, z nichž každý se hodí na trochu jinou situaci. -Filtr a funkce `|group` umožňují efektivní seskupení dat podle zadaného kritéria, filtr `|batch` zase usnadňuje rozdělení dat do pevně daných dávek a značka `{iterateWhile}` poskytuje možnost složitějšího řízení průběhu cyklů s podmínkami. Každá z těchto značek nabízí specifické možnosti pro práci s daty, čímž se stávají nepostradatelnými nástroji pro dynamické a strukturované zobrazení informací v Latte šablonách. +Filtr `|group` a funkce `group()` seskupí položky podle zadaného kritéria, filtr `|batch` je rozdělí do dávek pevné velikosti a značka `{iterateWhile}` prochází data postupně a sama si určuje, kdy přerušit vnitřní smyčku. V textu si je postupně projdeme. Filtr a funkce `group` .{data-version:3.0.16} ============================================= -Představte si databázovou tabulku `items` s položkami rozdělenou do kategorií: +Nástroj lze používat ve dvou tvarech: jako filtr `$items|group: …` nebo jako funkci `group($items, …)`. Sémanticky jsou ekvivalentní, vyberte si podle čitelnosti. + +Představte si databázovou tabulku `items`, jejíž položky patří do různých kategorií: | id | categoryId | name |------------------ @@ -62,19 +64,17 @@ Pokud bychom ale chtěli, aby položky byly uspořádány do skupin podle katego {/foreach} ``` -Filtr lze v Latte použít i jako funkci, což nám dává alternativní syntaxi: `{foreach group($items, categoryId) ...}`. - -Chcete-li seskupovat položky podle složitějších kritérií, můžete v parametru filtru použít funkci. Například, seskupení položek podle délky názvu by vypadalo takto: +Chcete-li seskupovat položky podle složitějších kritérií, můžete v parametru filtru použít funkci. Klíčem každé skupiny pak bude návratová hodnota funkce — například při seskupení podle délky názvu to bude počet znaků: ```latte -{foreach ($items|group: fn($item) => strlen($item->name)) as $items} +{foreach ($items|group: fn($item) => strlen($item->name)) as $length => $group} ... {/foreach} ``` -Je důležité si uvědomit, že `$categoryItems` není běžné pole, ale objekt, který se chová jako iterátor. Pro přístup k první položce skupiny můžete použít funkci [`first()` |latte:functions#first]. +Je důležité si uvědomit, že každá skupina (tedy i `$categoryItems`) není běžné pole, ale objekt chovající se jako iterátor — nelze proto použít `$categoryItems[0]` ani `count($categoryItems)`. Pro přístup k první položce skupiny použijte funkci [`first()` |latte:functions#first]. -Tato flexibilita v seskupování dat činí `group` výjimečně užitečným nástrojem pro prezentaci dat v šablonách Latte. +Tato flexibilita činí `|group` výjimečně užitečným nástrojem pro prezentaci dat. Vnořené smyčky @@ -97,8 +97,8 @@ Představme si, že máme databázovou tabulku s dalším sloupcem `subcategoryI ``` -Spojení s Nette Database ------------------------- +Společně s Nette Database +------------------------- Pojďme si ukázat, jak efektivně využít seskupování dat v kombinaci s Nette Database. Předpokládejme, že pracujeme s tabulkou `items` z úvodního příkladu, která je prostřednictvím sloupce `categoryId` spojená s touto tabulkou `categories`: @@ -121,24 +121,24 @@ Data z tabulky `items` načteme pomocí Nette Database Explorer příkazem `$ite {/foreach} ``` -V tomto případě používáme filtr `|group` k seskupení podle propojeného řádku `$item->category`, nikoliv jen dle sloupce `categoryId`. Díky tomu v proměnné klíči přímo `ActiveRow` dané kategorie, což nám umožňuje přímo vypisovat její název pomocí `{$category->name}`. Toto je praktický příklad, jak může seskupování zpřehlednit šablony a usnadnit práci s daty. +V tomto případě používáme filtr `|group` k seskupení podle propojeného řádku `$item->category`, nikoliv jen dle sloupce `categoryId`. Díky tomu je v klíči (`$category`) rovnou `ActiveRow` dané kategorie, což nám umožňuje vypisovat její název pomocí `{$category->name}` a přistupovat k libovolnému dalšímu sloupci, aniž bychom museli dělat zvláštní dotaz na `categories`. Filtr `|batch` ============== -Filtr umožňuje rozdělit seznam prvků do skupin s předem určeným počtem prvků. Tento filtr je ideální pro situace, kdy chcete data prezentovat ve více menších skupinách, například pro lepší přehlednost nebo vizuální uspořádání na stránce. +Filtr rozdělí seznam prvků do dávek o pevně daném počtu. Hodí se třeba pro grid layout, sloupcové rozložení nebo jakékoli vizuální seskupení. -Představme si, že máme seznam položek a chceme je zobrazit v seznamech, kde každý obsahuje maximálně tři položky. Použití filtru `|batch` je v takovém případě velmi praktické: +Představme si, že chceme zobrazit položky v seznamech, kde každý obsahuje maximálně tři položky: ```latte -
    {foreach ($items|batch: 3) as $batch} - {foreach $batch as $item} -
  • {$item->name}
  • - {/foreach} +
      + {foreach $batch as $item} +
    • {$item->name}
    • + {/foreach} +
    {/foreach} -
``` V tomto příkladu je seznam `$items` rozdělen do menších skupin, přičemž každá skupina (`$batch`) obsahuje až tři položky. Každá skupina je poté zobrazena v samostatném `
    ` seznamu. @@ -155,9 +155,9 @@ Pokud poslední skupina neobsahuje dostatek prvků k dosažení požadovaného p Značka `{iterateWhile}` ======================= -Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `group` nejprve zpracuje a seskupí všechna vstupní data, zatímco `{iterateWhile}` řídí průběhu cyklů s podmínkami, takže iterace probíhá postupně. +Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `|group` nejprve zpracuje a seskupí všechna vstupní data, zatímco `{iterateWhile}` řídí průběh cyklu pomocí podmínky a iterace probíhá postupně. -Nejprve vykreslíme tabulku s kategoriemi pomocí iterateWhile: +Nejprve vykreslíme tabulku s kategoriemi pomocí `{iterateWhile}`: ```latte {foreach $items as $item} @@ -169,7 +169,7 @@ Nejprve vykreslíme tabulku s kategoriemi pomocí iterateWhile: {/foreach} ``` -Zatímco `{foreach}` označuje vnější část cyklu, tedy vykreslování seznamů pro každou kategorii, tak značka `{iterateWhile}` označuje vnitřní část, tedy jednotlivé položky. Podmínka v koncové značce říká, že opakování bude probíhat do té doby, dokud aktuální i následující prvek patří do stejné kategorie (`$iterator->nextValue` je [následující položka |/tags#iterator]). +Zatímco `{foreach}` označuje vnější část cyklu, tedy vykreslování seznamů pro každou kategorii, tak značka `{iterateWhile}` označuje vnitřní část, tedy jednotlivé položky. Podmínka v koncové značce říká, že opakování bude probíhat do té doby, dokud aktuální i následující prvek patří do stejné kategorie (`$iterator->nextValue` je [následující položka |/tags#iterator]; u posledního prvku je `null` a porovnání pak vyjde false, takže vnitřní cyklus přirozeně skončí). Kdyby podmínka byla splněná vždy, tak se ve vnitřním cyklu vykreslí všechny prvky: @@ -196,11 +196,11 @@ Výsledek bude vypadat takto:
``` -K čemu je takové použití iterateWhile dobré? Když bude tabulka prázdná a nebude obsahovat žádné prvky, nevypíše se prázdné `
    `. +K čemu je takové použití `{iterateWhile}` dobré? Tím, že je `
      ` uvnitř vnějšího `{foreach}`, se při prázdném vstupu nevykreslí vůbec nic — žádný osamělý `
        `. Bez `{iterateWhile}` byste totéž museli ošetřit `{if}` před otevřením tagu nebo přes `{foreachelse}`. Pokud uvedeme podmínku v otevírací značce `{iterateWhile}`, tak se chování změní: podmínka (a přechod na další prvek) se vykoná už na začátku vnitřního cyklu, nikoliv na konci. Tedy zatímco do `{iterateWhile}` bez podmínky se vstoupí vždy, do `{iterateWhile $cond}` jen při splnění podmínky `$cond`. A zároveň se s tím do `$item` zapíše následující prvek. -Což se hodí například v situaci, kdy budeme chtít první prvek v každé kategorii vykreslit jiným způsobem, například takto: +Hodí se to v situaci, kdy chceme první prvek v každé kategorii vykreslit jiným způsobem než ty ostatní, například takto: ```latte

        Apple

        @@ -219,6 +219,8 @@ Což se hodí například v situaci, kdy budeme chtít první prvek v každé ka
      ``` +(Prázdné `
        ` u kategorie PHP je tu jen ilustrací mechaniky — v reálném kódu byste vykreslení `
          ` ošetřili `{if}`.) + Původní kód upravíme tak, že nejprve vykreslíme první položku a poté ve vnitřním cyklu `{iterateWhile}` vykreslíme další položky ze stejné kategorie: ```latte @@ -232,9 +234,9 @@ Původní kód upravíme tak, že nejprve vykreslíme první položku a poté ve {/foreach} ``` -V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Takto by se daly seskupovat třeba podkategorie atd. +V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Tímto způsobem lze seskupovat na více úrovních současně — třeba podkategorie pod kategoriemi. -Dejme tomu, že v tabulce bude ještě další sloupec `subcategoryId` a kromě toho, že každá kategorie bude v samostatném `
            `, každá každý podkategorie samostatném `
              `: +Dejme tomu, že v tabulce bude ještě další sloupec `subcategoryId` a kromě toho, že každá kategorie bude v samostatném `
                `, každá podkategorie bude v samostatném `
                  `: ```latte {foreach $items as $item} diff --git a/latte/cs/custom-filters.texy b/latte/cs/custom-filters.texy index 7f7cab0c0c..299d9c1aae 100644 --- a/latte/cs/custom-filters.texy +++ b/latte/cs/custom-filters.texy @@ -84,7 +84,7 @@ Registrace pomocí rozšíření Pro lepší organizaci, zejména při vytváření znovupoužitelných sad filtrů nebo jejich sdílení jako balíčky, je doporučeným způsobem registrovat je v rámci [rozšíření Latte |extending-latte#Latte Extension]: ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; @@ -111,7 +111,7 @@ class MyLatteExtension extends Extension // Registrace $latte = new Latte\Engine; -$latte->addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new MyLatteExtension); ``` Tento přístup udrží logiku vašeho filtru zapouzdřenou a registraci jednoduchou. diff --git a/latte/cs/custom-functions.texy b/latte/cs/custom-functions.texy index 8a1e70f188..1bd18de0e3 100644 --- a/latte/cs/custom-functions.texy +++ b/latte/cs/custom-functions.texy @@ -67,7 +67,7 @@ Registrace pomocí rozšíření Pro lepší organizaci a znovupoužitelnost registrujte funkce v rámci [Latte rozšíření |extending-latte#Latte Extension]. Tento přístup je doporučen pro složitější aplikace nebo sdílené knihovny. ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; use Nette\Security\Authorizator; @@ -95,7 +95,7 @@ class MyLatteExtension extends Extension } // Registrace (předpokládáme, že $container obsahuje DIC) -$extension = $container->getByType(App\Latte\MyLatteExtension::class); +$extension = $container->getByType(MyLatteExtension::class); $latte = new Latte\Engine; $latte->addExtension($extension); ``` diff --git a/latte/cs/custom-tags.texy b/latte/cs/custom-tags.texy index 7d41e7799d..4c35f4c796 100644 --- a/latte/cs/custom-tags.texy +++ b/latte/cs/custom-tags.texy @@ -117,7 +117,7 @@ Vytvořte soubor (např. `DatetimeNode.php`) a definujte třídu: ```php format()`, která sestavuje výsledný řetězec PHP kódu pro kompilovanou šablonu. První argument, `'echo date('Y-m-d H:i:s') %line;'`, je maska, do které jsou doplněny následující parametry. Zástupný symbol `%line` říká metodě `format()`, aby použila druhý argument, kterým je `$this->position`, a vložila komentář jako `/* line 15 */`, který propojuje vygenerovaný PHP kód zpět na původní řádek šablony, což je klíčové pro ladění. -Vlastnost `$this->position` je zděděna ze základní třídy `Node` a je automaticky nastavena parserem Latte. Obsahuje objekt [api:Latte\Compiler\Position], který indikuje, kde byl tag nalezen ve zdrojovém souboru `.latte`. +Vlastnost `$this->position` je zděděna ze základní třídy `Node` a je automaticky nastavena parserem Latte. Obsahuje objekt [api:Latte\Compiler\Range] (potomek třídy `Position` rozšířený o vlastnost `length` v bajtech), který udává, kde se tag v souboru `.latte` nachází. U párových tagů pokrývá rozsah od otevíracího po uzavírací tag a potomci `StatementNode` navíc nabízejí pole `$this->tagRanges` s objekty `Range` pro každý dílčí tag (otevírací, mezilehlé jako `{else}`/`{case}` i uzavírací). Metoda `getIterator()` je zásadní pro kompilační průchody. Musí poskytovat všechny dětské uzly, ale náš jednoduchý `DatetimeNode` aktuálně nemá žádné argumenty ani obsah, tedy žádné dětské uzly. Nicméně metoda musí stále existovat a být generátorem, tj. klíčové slovo `yield` musí být nějakým způsobem přítomno v těle metody. @@ -173,7 +173,7 @@ Nakonec informujme Latte o novém tagu. Vytvořte [třídu rozšíření |extend ```php addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new App\Templating\MyLatteExtension); ``` Vytvořte šablonu: @@ -255,7 +255,7 @@ S tímto pochopením upravme metodu `create()` v `DatetimeNode` tak, aby parsova ```php addExtension(new App\Latte\MyLatteExtension($isDev)); +$latte->addExtension(new MyLatteExtension($isDev)); ``` A jeho použití v šabloně: @@ -555,7 +555,7 @@ Upravme `DebugNode::create()` tak, aby očekával `{else}`: ```php Smazat ``` @@ -1003,7 +1003,7 @@ Zástupné symboly `PrintContext::format()` - **`%args`**: Argument musí být `Expression\ArrayNode`. Vypíše položky pole formátované jako argumenty pro volání funkce nebo metody (oddělené čárkami, zpracovává pojmenované argumenty, pokud jsou přítomny). - `$argsNode = new ArrayNode([...]);` - `$context->format('myFunc(%args);', $argsNode)` -> `myFunc(1, name: 'Joe');` -- **`%line`**: Argument musí být objekt `Position` (obvykle `$this->position`). Vkládá PHP komentář `/* line X */` indikující číslo řádku zdroje. +- **`%line`**: Argument musí být objekt `Position` (nebo `Range`, obvykle `$this->position`). Vkládá PHP komentář `/* line X */` indikující číslo řádku zdroje. - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42:1 */;` - **`%escape(...)`**: Generuje PHP kód, který *za běhu* escapuje vnitřní výraz pomocí aktuálních kontextově uvědomělých pravidel escapování. - `$context->format('echo %escape(%node);', $variableNode)` @@ -1023,7 +1023,7 @@ Zatímco `parseExpression()`, `parseArguments()`, atd., pokrývají mnoho příp ```php setTempDirectory('/path/to/tempdir'); +$latte->setCacheDirectory('/path/to/tempdir'); $params = [ /* proměnné šablony */ ]; // or $params = new TemplateParameters(/* ... */); @@ -58,6 +58,20 @@ $latte->setAutoRefresh(false); Při nasazení na produkčním serveru může prvotní vygenerování cache, zejména u rozsáhlejších aplikací, pochopitelně chviličku trvat. Latte má vestavěnou prevenci před "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. Jde o situaci, kdy se sejde větší počet souběžných požadavků, které spustí Latte, a protože cache ještě neexistuje, začaly by ji všechny generovat současně. Což by neúměrně zatížilo server. Latte je chytré a při více souběžných požadavcích generuje cache pouze první vlákno, ostatní čekají a následně ji využíjí. +Způsoby rozšíření Latte +======================= + +Latte můžete přizpůsobit hned několika způsoby, od jednoduchých pomocníků až po vlastní jazykové konstrukce. Podrobně se jim věnuje stránka [rozšiřujeme Latte |extending-latte], zde je stručný přehled: + +- **[Vlastní filtry |custom-filters]:** pro formátování nebo transformaci dat ve výstupu šablony (např. `{$var|myFilter}`). +- **[Vlastní funkce |custom-functions]:** pro vlastní logiku, kterou voláte ve výrazech šablony (např. `{myFunction($arg)}`). +- **[Vlastní tagy |custom-tags]:** pro zcela nové jazykové konstrukce (`{mytag}...{/mytag}` nebo `n:mytag`). +- **[Kompilační průchody |compiler-passes]:** funkce, které upravují AST šablony mezi parsováním a generováním PHP kódu (například pro optimalizace nebo bezpečnostní kontroly). +- **[Vlastní loadery |loaders]:** pro změnu způsobu, jakým Latte vyhledává a načítá soubory šablon. + +Pokud chcete svá rozšíření znovu použít v jiných projektech nebo je sdílet s ostatními, zabalte je do třídy [Latte Extension |extending-latte#Latte Extension]. + + Parametry jako třída ==================== @@ -184,18 +198,18 @@ Ve striktním režimu parsování Latte kontroluje, zda nechybí uzavírací HTM ```php $latte = new Latte\Engine; -$latte->setStrictParsing(); +$latte->setFeature(Latte\Feature::StrictParsing); ``` Generování šablon s hlavičkou `declare(strict_types=1)` zapnete takto: ```php $latte = new Latte\Engine; -$latte->setStrictTypes(); +$latte->setFeature(Latte\Feature::StrictTypes); ``` .[note] -Od verze Latte 3.1 jsou strict types povoleny ve výchozím nastavení. Můžete je deaktivovat pomocí `$latte->setStrictTypes(false)`. +Od verze Latte 3.1 jsou strict types povoleny ve výchozím nastavení. Můžete je deaktivovat pomocí `$latte->setFeature(Latte\Feature::StrictTypes, false)`. Migrační varování .{data-version:3.1} @@ -216,6 +230,70 @@ Pokud je toto zapnuto, Latte kontroluje vykreslované atributy a vyvolá uživat Jakmile jsou všechna varování vyřešena, vypněte varování o migraci a **odstraňte všechny** filtry `|accept` ze svých šablon, protože již nejsou potřeba. +Scopované proměnné cyklu .{data-version:3.1.3} +============================================== + +Ve výchozím nastavení zůstávají proměnné definované v cyklu `{foreach}` (jako `$key` a `$value`) dostupné i po jeho skončení – stejně jako v samotném PHP. To může vést k nechtěnému přepsání proměnných, pokud má proměnná cyklu stejný název jako existující proměnná šablony. + +Funkce `ScopedLoopVariables` omezí platnost proměnných na tělo cyklu. Po jeho skončení se obnoví původní hodnota proměnné (pokud existovala), nebo se proměnná odstraní: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::ScopedLoopVariables); +``` + +Příklad rozdílu: + +```latte +{var $item = 'original'} +{foreach [1, 2] as $item}{$item}, {/foreach} +{$item} +``` + +Bez `ScopedLoopVariables`: vypíše `1, 2, 2` (proměnná je přepsána) +Se `ScopedLoopVariables`: vypíše `1, 2, original` (proměnná je obnovena) + +Funguje to i s destrukturováním, např. `{foreach $array as [$a, $b]}`. + +.[note] +Proměnné cyklu používající reference (`{foreach $array as &$value}`) nebo přiřazení do vlastností (`{foreach $array as $obj->prop}`) nejsou scopovány, protože by to narušilo jejich účel. + + +Automatické odsazení (Dedent) .{toc: Dedent}{data-version:3.1.3} +================================================================ + +Při používání párových značek jako `{if}`, `{foreach}` nebo `{block}` se vnořený obsah často odsazuje pro lepší čitelnost. Toto odsazení se ale ve výchozím nastavení přenáší do vygenerovaného výstupu. Funkce `Dedent` ho automaticky odstraní, takže výstup zůstane čistý bez ohledu na úroveň zanoření v šabloně: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::Dedent); +``` + +Příklad: + +```latte +{if true} + Hello + World +{/if} +``` + +Bez `Dedent` by výstup obsahoval odsazení (`\tHello\n\tWorld\n`). S `Dedent` se odsazení odstraní a výstupem je `Hello\nWorld\n`. + +Hlubší odsazení uvnitř bloku zůstává zachováno relativně k základnímu odsazení: + +```latte +{if true} + Hello + Indented +{/if} +``` + +Výstup: `Hello\n\tIndented\n`. + +Odsazení v bloku musí být konzistentní (buď tabulátory, nebo mezery). Pokud se mísí, Latte vyhodí výjimku `Inconsistent indentation`. + + Překládání v šablonách .{toc: TranslatorExtension} ================================================== diff --git a/latte/cs/filters.texy b/latte/cs/filters.texy index bcce55ae3e..5a53e646d0 100644 --- a/latte/cs/filters.texy +++ b/latte/cs/filters.texy @@ -10,6 +10,9 @@ V šablonách můžeme používat funkce, které pomáhají upravit nebo přefor | `breakLines` | [Před konce řádku přidá HTML odřádkování |#breakLines] | `bytes` | [formátuje velikost v bajtech |#bytes] | `clamp` | [ohraničí hodnotu do daného rozsahu |#clamp] +| `column` | [extrahuje jeden sloupec z pole |#column] +| `commas` | [spojí pole čárkami |#commas] +| `limit` | [omezí délku pole, řetězce nebo iterátoru |#limit] | `dataStream` | [konverze pro Data URI protokol |#dataStream] | `date` | [formátuje datum a čas |#date] | `explode` | [rozdělí řetězec na pole podle oddělovače |#explode] @@ -259,6 +262,50 @@ Ohraničí hodnotu do daného inkluzivního rozsahu min a max. Existuje také jako [funkce |functions#clamp]. +column(string|int|null $columnKey, string|int|null $indexKey=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------------------------------------------ +Vrátí z vícerozměrného pole hodnoty jednoho sloupce `$columnKey` jako nové pole. Lze použít i na pole objektů pro získání hodnot vlastností. + +```latte +{var $users = [ + [id: 30, name: 'John', age: 30], + [id: 32, name: 'Jane', age: 25], + [id: 33, age: 35], +]} + +{$users|column: 'name'} +{* vrátí ['John', 'Jane'] *} + +{$users|column: 'name', 'id'} +{* vrátí [30 => 'John', 32 => 'Jane'] *} +``` + +Pokud předáte `null` jako klíč sloupce, přeindexuje pole podle `$indexKey`. + + +commas(?string $lastGlue=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------ +Spojí prvky pole čárkou a mezerou (`', '`). Jde o pohodlnou zkratku pro běžný výpis položek v čitelné podobě. + +```latte +{var $items = ['jablka', 'pomeranče', 'banány']} +{$items|commas} +{* vypíše 'jablka, pomeranče, banány' *} +``` + +Lze zadat i vlastní oddělovač pro poslední dvojici položek: + +```latte +{$items|commas: ' a '} +{* vypíše 'jablka, pomeranče a banány' *} + +{=['PHP', 'JavaScript', 'Python']|commas: ', nebo '} +{* vypíše 'PHP, JavaScript, nebo Python' *} +``` + +Viz také [#implode]. + + dataStream(string $mimetype=detect) .[filter] --------------------------------------------- Konvertuje obsah do data URI scheme. Pomocí něj lze do HTML nebo CSS vkládat obrázky bez nutnosti linkovat externí soubory. @@ -407,6 +454,8 @@ Můžete také použít alias `join`: {=[1, 2, 3]|join} {* vypíše '123' *} ``` +Viz také [#commas], [#explode]. + indent(int $level=1, string $char="\t") .[filter] ------------------------------------------------- @@ -637,19 +686,21 @@ Pamatujte, že skutečný vzhled čísel se může lišit podle nastavení země padLeft(int $length, string $pad=' ') .[filter] ----------------------------------------------- -Doplní řetězec do určité délky jiným řetězcem zleva. +Doplní řetězec nebo číslo do určité délky jiným řetězcem zleva. ```latte {='hello'|padLeft: 10, '123'} {* vypíše '12312hello' *} +{=123|padLeft: 5, '0'} {* vypíše '00123' *} ``` padRight(int $length, string $pad=' ') .[filter] ------------------------------------------------ -Doplní řetězec do určité délky jiným řetězcem zprava. +Doplní řetězec nebo číslo do určité délky jiným řetězcem zprava. ```latte {='hello'|padRight: 10, '123'} {* vypíše 'hello12312' *} +{=123|padRight: 5, '0'} {* vypíše '12300' *} ``` @@ -747,14 +798,14 @@ Viz také [#ceil], [#floor]. slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter] ------------------------------------------------------------------------ -Extrahuje část pole nebo řetězce. +Extrahuje část pole, řetězce nebo iterátoru. ```latte {='hello'|slice: 1, 2} {* vypíše 'el' *} {=['a', 'b', 'c']|slice: 1, 2} {* vypíše ['b', 'c'] *} ``` -Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce s fallbackem na funkci `iconv_substr` v režimu UTF‑8. +Filtr funguje jako funkce PHP `array_slice` pro pole nebo `mb_substr` pro řetězce. Pro iterátory vrací generátor – prvky se čtou z původního zdroje jeden po druhém a po dosažení limitu se čtení zastaví. Celý iterátor se do paměti nenačítá. Pokud je start kladný, posloupnost začné posunutá o tento počet od začátku pole/řetezce. Pokud je záporný posloupnost začné posunutá o tolik od konce. @@ -762,6 +813,21 @@ Pokud je zadaný parametr length a je kladný, posloupnost bude obsahovat tolik Ve výchozím nastavení filtr změní pořadí a resetuje celočíselného klíče pole. Toto chování lze změnit nastavením preserveKeys na true. Řetězcové klíče jsou vždy zachovány, bez ohledu na tento parametr. +Viz také [#limit]. + + +limit(int $length) .[filter]{data-version:3.1.3} +------------------------------------------------ +Omezí délku pole, řetězce nebo iterátoru. U polí a iterátorů zachovává klíče. U řetězců respektuje UTF-8. + +```latte +{foreach ($items|limit: 5) as $item} + ... +{/foreach} + +{$text|limit: 100} +``` + sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter] -------------------------------------------------------------------------------------------------------------- diff --git a/latte/cs/recipes.texy b/latte/cs/recipes.texy index a11d147a0e..172a222a08 100644 --- a/latte/cs/recipes.texy +++ b/latte/cs/recipes.texy @@ -7,7 +7,7 @@ Editory a IDE Pište šablony v editoru nebo IDE, který má podporu pro Latte. Bude to mnohem příjemnější. -- PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/7457-latte] +- PhpStorm: nainstalujte v `Settings > Plugins > Marketplace` [plugin Latte|https://plugins.jetbrains.com/plugin/24218-latte-support] - VS Code: nainstalujte [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte], [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] nebo nejnovější [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode] plugin - NetBeans IDE: nativní podpora Latte je součástí instalace - Sublime Text 3: v Package Control najděte a nainstalujte balíček `Nette` a zvolte Latte ve `View > Syntax` diff --git a/latte/cs/safety-first.texy b/latte/cs/safety-first.texy index e76142ec39..b718215a1b 100644 --- a/latte/cs/safety-first.texy +++ b/latte/cs/safety-first.texy @@ -33,7 +33,7 @@ echo '

                  Výsledky vyhledávání pro ' . $search . '

                  '; Útočník může do vyhledávacího políčka a potažmo do proměnné `$search` zapsat libovolný řetězec, tedy i HTML kód jako ``. Protože výstup není nijak ošetřen, stane se součástí zobrazené stránky: -```html +```latte

                  Výsledky vyhledávání pro

                  ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Útočníkovi stačí jako popisek vložit šikovně sestavený řetězec `" onload="alert('Hacked!')` a když vypsání nebude ošetřeno, výsledný kód bude vypadat takto: -```html +```latte ``` @@ -91,7 +91,7 @@ Kontextově sensitivní escapování Co se přesně myslí slovem kontext? Jde o místo v dokumentu s vlastními pravidly pro ošetřování vypisovaných dat. Odvíjí se od typu dokumentu (HTML, XML, CSS, JavaScript, plain text, ...) a může se lišit v jeho konkrétních částech. Například v HTML dokumentu je takových míst (kontextů), kde platí velmi odlišná pravidla, celá řada. Možná budete překvapeni, kolik jich je. Tady máme první čtveřici: -```html +```latte

                  #text

                  @@ -108,7 +108,7 @@ Zajímavé je to uvnitř HTML komentářů. Tady se totiž k escapování nepou Kontexty se také mohou vrstvit, k čemuž dochází, když vložíme JavaScript nebo CSS do HTML. To lze udělat dvěma odlišnými způsoby, elementem a atributem: -```html +```latte @@ -132,7 +132,7 @@ Mějme řetězec `Rock'n'Roll`. Pokud jej budete vypisovat v HTML textu, zrovna v tomhle případě netřeba dělat žádné záměny, protože řetězec neobsahuje žádný znak se speciálním významem. Jiná situace nastane, pokud jej vypíšete uvnitř HTML atributu uvozeného do jednoduchých uvozovek. V takovém případě je potřeba escapovat uvozovky na HTML entity: -```html +```latte
                  ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Pokud tento kód vložíme do HTML dokumentu pomocí ` ``` Pokud bychom jej však chtěli vložit do HTML atributu, musíme ještě escapovat uvozovky na HTML entity: -```html +```latte
                  ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll A když tento řetězec vypíšeme v atributu, ještě aplikujeme escapování podle tohoto kontextu a nahradíme `&` za `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Všimněte si, že okolo hodnot atributů nejsou uvozovky. Kodér na ně mohl za Útočník jako popisek obrázku vloží šikovně sestavený řetězec `foo onload=alert('Hacked!')`. Už víme, že Twig nemůže poznat, jestli se proměnná vypisuje v toku HTML textu, uvnitř atributu, HTML komentáře, atd., zkrátka nerozlišuje kontexty. A jen mechanicky převádí znaky `< > & ' "` na HTML entity. Takže výsledný kód bude vypadat takto: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Nyní se podíváme, jak si se stejnou šablonou poradí Latte: Latte vidí šablonu stejně jako vy. Na rozdíl od Twigu chápe HTML a ví, že proměnná se vypisuje jako hodnota atributu, který není v uvozovkách. Proto je doplní. Když útočník vloží stejný popisek, výsledný kód bude vypadat takto: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/cs/syntax.texy b/latte/cs/syntax.texy index 1e21ab6dcf..39f1c621de 100644 --- a/latte/cs/syntax.texy +++ b/latte/cs/syntax.texy @@ -218,6 +218,41 @@ Uvnitř značek fungují PHP komentáře: ``` +Řízení bílých znaků +=================== + +Latte zachází s bílými znaky inteligentně. Kód můžete volně odsazovat pro čitelnost a výstup zůstane čistý. Když se tag objeví na řádku sám, celý řádek (odsazení i konec řádku) se z výstupu odstraní: + +```latte +
                    + {foreach $items as $item} +
                  • {$item}
                  • + {/foreach} +
                  +``` + +Vypíše: + +```latte +
                    +
                  • foo
                  • +
                  • bar
                  • +
                  +``` + +A co když tag není na řádku sám, ale je tam i další obsah? Bílé znaky před tagem pak patří *dovnitř* tagu: + +```latte +
                  + {if $foo}hello{/if} +
                  +``` + +Odsazení je tedy fakticky uvnitř `{if}`: pokud je `$foo` false, nevypíše se nic – ani odsazení, ani prázdný řádek. Pokud je `$foo` true, výstup přirozeně obsahuje odsazení. Prostě pište přehledně odsazené šablony a výstup bude vždy čistý. + +Pro ještě čistší výstup lze aktivovat funkci [Dedent |develop#Dedent], která odstraní i odsazení vzniklé zanořením v párových značkách jako `{if}` nebo `{foreach}`. + + Syntaktický cukr ================ diff --git a/latte/cs/tags.texy b/latte/cs/tags.texy index 598b2b73dd..cb8b03378a 100644 --- a/latte/cs/tags.texy +++ b/latte/cs/tags.texy @@ -137,7 +137,7 @@ Jako výraz můžete zapsat cokoliv, co znáte z PHP. Nemusíte se zkrátka uči ```latte -{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION} +{='0' . ($num ?? $num * 3) . ', ' . \PHP_VERSION} ``` Prosím, nehledejte v předchozím příkladu žádný smysl, ale kdybyste tam nějaký našli, napište nám :-) diff --git a/latte/de/custom-tags.texy b/latte/de/custom-tags.texy index 483b5f5820..89089b627d 100644 --- a/latte/de/custom-tags.texy +++ b/latte/de/custom-tags.texy @@ -923,7 +923,7 @@ Jetzt können Sie `n:confirm` auf Links, Schaltflächen oder Formularelementen v Generiertes HTML: -```html +```latte
                  Löschen ``` diff --git a/latte/de/safety-first.texy b/latte/de/safety-first.texy index 2f5b0697a1..bdc0cb85fa 100644 --- a/latte/de/safety-first.texy +++ b/latte/de/safety-first.texy @@ -33,7 +33,7 @@ echo '

                  Suchergebnisse für ' . $search . '

                  '; Ein Angreifer kann in das Suchfeld und somit in die Variable `$search` eine beliebige Zeichenkette eingeben, also auch HTML-Code wie ``. Da die Ausgabe nicht bereinigt wird, wird sie Teil der angezeigten Seite: -```html +```latte

                  Suchergebnisse für

                  ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Dem Angreifer genügt es, als Beschreibung eine geschickt konstruierte Zeichenkette `" onload="alert('Gehackt!')` einzufügen, und wenn die Ausgabe nicht bereinigt wird, sieht der resultierende Code so aus: -```html +```latte ``` @@ -91,7 +91,7 @@ Kontextsensitives Escaping Was genau ist mit dem Wort Kontext gemeint? Es handelt sich um eine Stelle im Dokument mit eigenen Regeln für die Bereinigung ausgegebener Daten. Sie hängt vom Dokumenttyp ab (HTML, XML, CSS, JavaScript, Plain Text, ...) und kann sich in seinen spezifischen Teilen unterscheiden. Beispielsweise gibt es in einem HTML-Dokument eine ganze Reihe solcher Stellen (Kontexte), an denen sehr unterschiedliche Regeln gelten. Vielleicht werden Sie überrascht sein, wie viele es sind. Hier sind die ersten vier: -```html +```latte

                  #text

                  @@ -108,7 +108,7 @@ Interessant ist es innerhalb von HTML-Kommentaren. Hier wird nämlich kein Escap Kontexte können sich auch verschachteln, was passiert, wenn wir JavaScript oder CSS in HTML einbetten. Dies kann auf zwei verschiedene Arten geschehen, mit einem Element und einem Attribut: -```html +```latte @@ -132,7 +132,7 @@ Nehmen wir die Zeichenkette `Rock'n'Roll`. Wenn Sie sie im HTML-Text ausgeben, müssen in diesem Fall keine Ersetzungen vorgenommen werden, da die Zeichenkette kein Zeichen mit besonderer Bedeutung enthält. Eine andere Situation ergibt sich, wenn Sie sie innerhalb eines HTML-Attributs ausgeben, das in einfache Anführungszeichen eingeschlossen ist. In diesem Fall müssen die Anführungszeichen in HTML-Entitäten escapet werden: -```html +```latte
                  ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Wenn wir diesen Code mit ` ``` Wenn wir ihn jedoch in ein HTML-Attribut einfügen wollten, müssten wir die Anführungszeichen noch in HTML-Entitäten escapen: -```html +```latte
                  ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Und wenn wir diese Zeichenkette in einem Attribut ausgeben, wenden wir noch das Escaping gemäß diesem Kontext an und ersetzen `&` durch `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Beachten Sie, dass um die Attributwerte keine Anführungszeichen stehen. Der Pro Ein Angreifer fügt als Bildbeschreibung eine geschickt konstruierte Zeichenkette `foo onload=alert('Gehackt!')` ein. Wir wissen bereits, dass Twig nicht erkennen kann, ob die Variable im Fluss des HTML-Textes, innerhalb eines Attributs, eines HTML-Kommentars usw. ausgegeben wird, kurz gesagt, es unterscheidet keine Kontexte. Und konvertiert nur mechanisch die Zeichen `< > & ' "` in HTML-Entitäten. Der resultierende Code sieht also so aus: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Sehen wir uns nun an, wie Latte mit demselben Template umgeht: Latte sieht das Template genauso wie Sie. Im Gegensatz zu Twig versteht es HTML und weiß, dass die Variable als Wert eines Attributs ausgegeben wird, das nicht in Anführungszeichen steht. Deshalb ergänzt es sie. Wenn ein Angreifer dieselbe Beschreibung einfügt, sieht der resultierende Code so aus: -```html +```latte foo onload=alert('Gehackt!') ``` diff --git a/latte/el/custom-tags.texy b/latte/el/custom-tags.texy index cf69c32588..3c041dd29d 100644 --- a/latte/el/custom-tags.texy +++ b/latte/el/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Παραγόμενο HTML: -```html +```latte Διαγραφή ``` diff --git a/latte/el/safety-first.texy b/latte/el/safety-first.texy index bb4b7c09d7..65985510ef 100644 --- a/latte/el/safety-first.texy +++ b/latte/el/safety-first.texy @@ -33,7 +33,7 @@ echo '

                  Αποτελέσματα αναζήτησης για ' . $search . Ένας εισβολέας μπορεί να γράψει στο πεδίο αναζήτησης και κατ' επέκταση στη μεταβλητή `$search` οποιοδήποτε string, δηλαδή και κώδικα HTML όπως ``. Επειδή η έξοδος δεν επεξεργάζεται με κανέναν τρόπο, γίνεται μέρος της εμφανιζόμενης σελίδας: -```html +```latte

                  Αποτελέσματα αναζήτησης για

                  ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Αρκεί ο εισβολέας να εισάγει ως λεζάντα ένα έξυπνα κατασκευασμένο string `" onload="alert('Hacked!')` και αν η εκτύπωση δεν επεξεργαστεί, ο προκύπτων κώδικας θα μοιάζει ως εξής: -```html +```latte ``` @@ -91,7 +91,7 @@ Context-Aware Escaping Τι ακριβώς εννοούμε με τη λέξη context; Πρόκειται για ένα μέρος στο έγγραφο με τους δικούς του κανόνες για την επεξεργασία των εκτυπωμένων δεδομένων. Εξαρτάται από τον τύπο του εγγράφου (HTML, XML, CSS, JavaScript, plain text, ...) και μπορεί να διαφέρει σε συγκεκριμένα μέρη του. Για παράδειγμα, σε ένα έγγραφο HTML, υπάρχουν πολλά τέτοια μέρη (contexts) όπου ισχύουν πολύ διαφορετικοί κανόνες. Ίσως εκπλαγείτε πόσα είναι. Εδώ έχουμε την πρώτη τετράδα: -```html +```latte

                  #κείμενο

                  @@ -108,7 +108,7 @@ Context-Aware Escaping Τα contexts μπορούν επίσης να στρωματοποιηθούν, κάτι που συμβαίνει όταν ενσωματώνουμε JavaScript ή CSS σε HTML. Αυτό μπορεί να γίνει με δύο διαφορετικούς τρόπους, με στοιχείο και με attribute: -```html +```latte @@ -132,7 +132,7 @@ Context-Aware Escaping Αν το εκτυπώσετε σε κείμενο HTML, σε αυτή τη συγκεκριμένη περίπτωση δεν χρειάζεται να κάνετε καμία αντικατάσταση, επειδή το string δεν περιέχει κανέναν χαρακτήρα με ειδική σημασία. Η κατάσταση αλλάζει αν το εκτυπώσετε μέσα σε ένα attribute HTML που περικλείεται σε απλά εισαγωγικά. Σε αυτή την περίπτωση, πρέπει να κάνετε escape τα εισαγωγικά σε οντότητες HTML: -```html +```latte
                  ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Αν εισάγουμε αυτόν τον κώδικα σε ένα έγγραφο HTML χρησιμοποιώντας το ` ``` Αν όμως θέλαμε να το εισάγουμε σε ένα attribute HTML, πρέπει ακόμα να κάνουμε escape τα εισαγωγικά σε οντότητες HTML: -```html +```latte
                  ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Και όταν εκτυπώνουμε αυτό το string σε ένα attribute, εφαρμόζουμε επιπλέον το escaping σύμφωνα με αυτό το context και αντικαθιστούμε το `&` με `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Latte εναντίον απλοϊκών συστημάτων Ένας εισβολέας εισάγει ως λεζάντα της εικόνας ένα έξυπνα κατασκευασμένο string `foo onload=alert('Hacked!')`. Γνωρίζουμε ήδη ότι το Twig δεν μπορεί να αναγνωρίσει αν η μεταβλητή εκτυπώνεται στη ροή του κειμένου HTML, μέσα σε ένα attribute, σε ένα σχόλιο HTML κ.λπ., με λίγα λόγια δεν διακρίνει τα contexts. Και απλώς μετατρέπει μηχανικά τους χαρακτήρες `< > & ' "` σε οντότητες HTML. Έτσι, ο προκύπτων κώδικας θα μοιάζει ως εξής: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Latte εναντίον απλοϊκών συστημάτων Το Latte βλέπει το πρότυπο όπως εσείς. Σε αντίθεση με το Twig, καταλαβαίνει HTML και ξέρει ότι η μεταβλητή εκτυπώνεται ως τιμή ενός attribute που δεν βρίσκεται σε εισαγωγικά. Γι' αυτό τα συμπληρώνει. Όταν ο εισβολέας εισάγει την ίδια λεζάντα, ο προκύπτων κώδικας θα μοιάζει ως εξής: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/en/cookbook/grouping.texy b/latte/en/cookbook/grouping.texy index 7a8458bb0c..1d4b7bf049 100644 --- a/latte/en/cookbook/grouping.texy +++ b/latte/en/cookbook/grouping.texy @@ -2,15 +2,17 @@ Everything You Always Wanted to Know About Grouping *************************************************** .[perex] -When working with data in templates, you often encounter the need to group them or display them specifically according to certain criteria. Latte offers several powerful tools for this purpose. +When working with data in templates, you often need to group items, split them into batches, or iterate through them based on a condition. Latte offers three tools for this, each suited to a slightly different situation. -The filter and function `|group` allow for efficient data grouping based on specified criteria, the `|batch` filter facilitates splitting data into fixed-size batches, and the `{iterateWhile}` tag provides the ability to control loop progression with more complex conditions. Each of these features offers specific options for working with data, making them indispensable tools for dynamic and structured display of information in Latte templates. +The `|group` filter groups items by a given criterion, the `|batch` filter splits them into batches of fixed size, and the `{iterateWhile}` tag iterates through data step by step and decides for itself when to break the inner loop. We'll walk through them one by one. Filter and Function `group` .{data-version:3.0.16} ================================================== -Imagine a database table `items` with items divided into categories: +The tool can be used in two forms: as a filter `$items|group: …` or as a function `group($items, …)`. Semantically they are equivalent — choose based on readability. + +Imagine a database table `items` whose items belong to various categories: | id | categoryId | name |-----|------------|-------- @@ -62,19 +64,17 @@ This task can be easily and elegantly solved using `|group`. We specify `categor {/foreach} ``` -The filter can also be used as a function in Latte, providing an alternative syntax: `{foreach group($items, categoryId) ...}`. - -If you want to group items based on more complex criteria, you can use a function in the filter parameter. For example, grouping items by the length of their name would look like this: +If you want to group items based on more complex criteria, you can use a function in the filter parameter. The key of each group will then be the return value of the function — for example, when grouping by name length, it will be the number of characters: ```latte -{foreach ($items|group: fn($item) => strlen($item->name)) as $items} +{foreach ($items|group: fn($item) => strlen($item->name)) as $length => $group} ... {/foreach} ``` -It’s important to note that `$categoryItems` is not a regular array, but an object that behaves like an iterator. To access the first item in the group, you can use the [`first()` |latte:functions#first] function. +It's important to note that each group (including `$categoryItems`) is not a regular array, but an object that behaves like an iterator — so you cannot use `$categoryItems[0]` or `count($categoryItems)`. To access the first item in the group, use the [`first()` |latte:functions#first] function. -This flexibility in data grouping makes `group` an exceptionally useful tool for presenting data in Latte templates. +This flexibility makes `|group` an exceptionally useful tool for presenting data. Nested Loops @@ -97,8 +97,8 @@ Let's imagine our database table has an additional column `subcategoryId`, defin ``` -Integration with Nette Database -------------------------------- +Together with Nette Database +---------------------------- Let's demonstrate how to effectively use data grouping in combination with Nette Database. Assume we are working with the `items` table from the introductory example, connected via the `categoryId` column to this `categories` table: @@ -121,24 +121,24 @@ We load data from the `items` table using Nette Database Explorer with the comma {/foreach} ``` -In this case, we use the `|group` filter to group by the related row object `$item->category`, not just the `categoryId` column. As a result, the key variable `$category` directly holds the `ActiveRow` object for that category, allowing us to display its name directly using `{$category->name}`. This is a practical example of how grouping can simplify templates and facilitate working with related data. +In this case, we use the `|group` filter to group by the related row `$item->category`, not just the `categoryId` column. As a result, the key (`$category`) directly holds the `ActiveRow` object for that category, allowing us to display its name using `{$category->name}` and access any other column without making a separate query to `categories`. Filter `|batch` =============== -The `|batch` filter allows you to divide a list of items into groups (batches) with a predetermined number of items. This filter is ideal for situations where you want to present data in several smaller chunks, for example, for better clarity or visual layout on the page. +The filter splits a list of items into batches of a fixed size. It's handy for grid layouts, column arrangements, or any kind of visual grouping. -Imagine we have a list of items and want to display them in lists, where each list contains a maximum of three items. Using the `|batch` filter is very practical in such a case: +Imagine we want to display items in lists where each list contains a maximum of three items: ```latte -
                    {foreach ($items|batch: 3) as $batch} - {foreach $batch as $item} -
                  • {$item->name}
                  • - {/foreach} +
                      + {foreach $batch as $item} +
                    • {$item->name}
                    • + {/foreach} +
                    {/foreach} -
                  ``` In this example, the `$items` list is divided into smaller groups, where each group (`$batch`) contains up to three items. Each batch is then displayed in a separate `
                    ` list. @@ -155,9 +155,9 @@ If the last group does not contain enough elements to reach the desired number, Tag `{iterateWhile}` ==================== -We will demonstrate the same tasks addressed with the `|group` filter using the `{iterateWhile}` tag. The main difference between the two approaches is that `|group` first processes and groups all input data, whereas `{iterateWhile}` controls the loop's progression based on conditions, allowing iteration to proceed sequentially. +We will demonstrate the same tasks addressed with the `|group` filter using the `{iterateWhile}` tag. The main difference between the two approaches is that `|group` first processes and groups all input data, whereas `{iterateWhile}` controls the loop's progression via a condition and iteration proceeds sequentially. -First, let's render the table with categories using `iterateWhile`: +First, let's render the table with categories using `{iterateWhile}`: ```latte {foreach $items as $item} @@ -169,7 +169,7 @@ First, let's render the table with categories using `iterateWhile`: {/foreach} ``` -While `{foreach}` marks the outer part of the cycle, i.e., drawing lists for each category, the `{iterateWhile}` tag marks the inner part, i.e., individual items. The condition in the end tag says that repetition will continue as long as the current and next element belong to the same category (`$iterator->nextValue` is the [next item |/tags#iterator]). +While `{foreach}` marks the outer part of the cycle, i.e., drawing lists for each category, the `{iterateWhile}` tag marks the inner part, i.e., individual items. The condition in the end tag says that repetition will continue as long as the current and next element belong to the same category (`$iterator->nextValue` is the [next item |/tags#iterator]; for the last element it is `null` and the comparison then evaluates to false, so the inner loop naturally ends). If the condition were always true, all elements would be rendered within the first `
                      `: @@ -196,11 +196,11 @@ The result would look like this:
                    ``` -What's the benefit of using `iterateWhile` like this? If the `$items` array is empty, no empty `
                      ` tags will be printed. +What's the benefit of using `{iterateWhile}` like this? Because the `
                        ` is inside the outer `{foreach}`, nothing is rendered at all when the input is empty — no lone `
                          `. Without `{iterateWhile}` you would have to handle the same case with an `{if}` before opening the tag or via `{foreachelse}`. If we specify the condition in the opening `{iterateWhile}` tag, the behavior changes: the condition (and transition to the next element) is performed at the beginning of the inner cycle, not at the end. Thus, while you always enter `{iterateWhile}` without conditions, you enter `{iterateWhile $cond}` only when the condition `$cond` is met. And at the same time, the next element is written into `$item`. -This is useful, for instance, when you want to render the first item in each category differently, like this: +This is useful in situations where we want to render the first item in each category differently from the others, for example like this: ```latte

                          Apple

                          @@ -219,6 +219,8 @@ This is useful, for instance, when you want to render the first item in each cat
                        ``` +(The empty `
                          ` for the PHP category is just an illustration of the mechanics — in real code you would handle the `
                            ` rendering with an `{if}`.) + We modify the original code to first render the item as a heading, and then use the inner `{iterateWhile}` loop to render subsequent items from the same category as list items: ```latte @@ -232,9 +234,9 @@ We modify the original code to first render the item as a heading, and then use {/foreach} ``` -Within a single `{foreach}` loop, you can create multiple inner `{iterateWhile}` loops and even nest them. This could be used, for example, to group subcategories. +Within a single loop, we can create multiple inner loops and even nest them. This way you can group on multiple levels at once — for example, subcategories under categories. -Let's assume the table has another column `subcategoryId`, and besides having each category in a separate `
                              `, each subcategory should be in a separate `
                                `: +Let's assume the table has another column `subcategoryId`, and besides each category being in a separate `
                                  `, each subcategory will be in a separate `
                                    `: ```latte {foreach $items as $item} diff --git a/latte/en/custom-filters.texy b/latte/en/custom-filters.texy index 9fc3ea58b6..db6d77bf8d 100644 --- a/latte/en/custom-filters.texy +++ b/latte/en/custom-filters.texy @@ -84,7 +84,7 @@ Registration via Extension For better organization, especially when creating reusable sets of filters or sharing them as packages, the recommended way is to register them within a [Latte Extension |extending-latte#Latte Extension]: ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; @@ -111,7 +111,7 @@ class MyLatteExtension extends Extension // Registration $latte = new Latte\Engine; -$latte->addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new MyLatteExtension); ``` This approach keeps your filter logic encapsulated and makes registration straightforward. diff --git a/latte/en/custom-functions.texy b/latte/en/custom-functions.texy index 4c4a4d423d..eeef7d8008 100644 --- a/latte/en/custom-functions.texy +++ b/latte/en/custom-functions.texy @@ -67,7 +67,7 @@ Registration via Extension For better organization and reusability, register functions within a [Latte Extension |extending-latte#Latte Extension]. This is the recommended approach for non-trivial applications or shared libraries. ```php -namespace App\Latte; +namespace App\Templating; use Latte\Extension; use Nette\Security\Authorizator; @@ -95,7 +95,7 @@ class MyLatteExtension extends Extension } // Registration (assuming $container holds the DIC) -$extension = $container->getByType(App\Latte\MyLatteExtension::class); +$extension = $container->getByType(MyLatteExtension::class); $latte = new Latte\Engine; $latte->addExtension($extension); ``` diff --git a/latte/en/custom-tags.texy b/latte/en/custom-tags.texy index b427e74a27..b162bc8e10 100644 --- a/latte/en/custom-tags.texy +++ b/latte/en/custom-tags.texy @@ -117,7 +117,7 @@ Create a file (e.g., `DatetimeNode.php`) and define the class: ```php format()` method, which assembles the resulting PHP code string for the compiled template. The first argument, `'echo date('Y-m-d H:i:s') %line;'`, is the mask into which the subsequent parameters are substituted. The `%line` placeholder tells the `format()` method to take the second following argument, which is `$this->position`, and inserts a comment like `/* line 15 */` that links the generated PHP code back to the original template line, which is crucial for debugging. -Property `$this->position` is inherited from the base `Node` class, and is automatically set by Latte's parser. It holds a [api:Latte\Compiler\Position] object indicating where the tag was found in the source `.latte` file. +Property `$this->position` is inherited from the base `Node` class, and is automatically set by Latte's parser. It holds a [api:Latte\Compiler\Range] object (a subclass of `Position` extended with a `length` in bytes) indicating where the tag is located in the source `.latte` file. For paired tags the range spans from the opening to the closing tag, and `StatementNode` descendants additionally expose `$this->tagRanges` listing the `Range` of every constituent tag (opening, intermediate like `{else}`/`{case}`, and closing). The `getIterator()` method is vital for compiler passes. It must yield all child nodes, but our simple `DatetimeNode` currently has no arguments or content, thus no child nodes. However, the method must still exist and be a generator, i.e. the `yield` keyword must be somehow present in the method body. @@ -173,7 +173,7 @@ Finally, tell Latte about the new tag. Create an [Extension class |extending-lat ```php addExtension(new App\Latte\MyLatteExtension); +$latte->addExtension(new App\Templating\MyLatteExtension); ``` Create template: @@ -255,7 +255,7 @@ With that understanding, let's modify the `create()` method in `DatetimeNode` to ```php addExtension(new App\Latte\MyLatteExtension($isDev)); +$latte->addExtension(new MyLatteExtension($isDev)); ``` And use it in a template: @@ -555,7 +555,7 @@ Let's modify `DebugNode::create()` to expect `{else}`: ```php Delete ``` @@ -1003,7 +1003,7 @@ We've frequently used `PrintContext::format()` to generate PHP code in the `prin - **`%args`**: Argument must be an `Expression\ArrayNode`. It prints the array items formatted as arguments for a function or method call (comma-separated, handling named arguments if present). - `$argsNode = new ArrayNode([...]);` - `$context->format('myFunc(%args);', $argsNode)` -> `myFunc(1, name: 'Joe');` -- **`%line`**: Argument must be a `Position` object (usually `$this->position`). It inserts a PHP comment `/* line X */` indicating the source line number. +- **`%line`**: Argument must be a `Position` (or `Range`) object (usually `$this->position`). It inserts a PHP comment `/* line X */` indicating the source line number. - `$context->format('echo "Hi" %line;', $this->position)` -> `echo "Hi" /* line 42:1 */;` - **`%escape(...)`**: It generates PHP code that, *at runtime*, will escape the inner expression using the current context-aware escaping rules. - `$context->format('echo %escape(%node);', $variableNode)` @@ -1023,7 +1023,7 @@ While `parseExpression()`, `parseArguments()`, etc., cover many cases, sometimes ```php setTempDirectory('/path/to/tempdir'); +$latte->setCacheDirectory('/path/to/tempdir'); $params = [ /* template variables */ ]; // or $params = new TemplateParameters(/* ... */); @@ -58,6 +58,20 @@ $latte->setAutoRefresh(false); When deployed on a production server, the initial cache generation, especially for larger applications, can understandably take a while. Latte has built-in prevention against "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. This is a situation where server receives a large number of concurrent requests and because Latte's cache does not yet exist, they would all generate it at the same time. Which spikes CPU. Latte is smart, and when there are multiple concurrent requests, only the first thread generates the cache, the others wait and then use it. +Ways to Extend Latte +==================== + +Latte can be customized in several ways, from simple helpers to entirely new language constructs. The page [extending Latte |extending-latte] covers them in detail; here is a quick overview: + +- **[Custom Filters|custom-filters]:** for formatting or transforming data in the template output (e.g., `{$var|myFilter}`). +- **[Custom Functions|custom-functions]:** for custom logic you call within template expressions (e.g., `{myFunction($arg)}`). +- **[Custom Tags|custom-tags]:** for entirely new language constructs (`{mytag}...{/mytag}` or `n:mytag`). +- **[Compiler Passes|compiler-passes]:** functions that modify the template's AST between parsing and PHP code generation (for example, optimizations or security checks). +- **[Custom Loaders|loaders]:** for changing how Latte locates and loads template files. + +If you want to reuse your extensions across projects or share them with others, bundle them into a [Latte Extension |extending-latte#Latte Extension] class. + + Parameters as a Class ===================== @@ -184,18 +198,18 @@ In strict parsing mode, Latte checks for missing closing HTML tags and also disa ```php $latte = new Latte\Engine; -$latte->setStrictParsing(); +$latte->setFeature(Latte\Feature::StrictParsing); ``` To generate templates with the `declare(strict_types=1)` header, do the following: ```php $latte = new Latte\Engine; -$latte->setStrictTypes(); +$latte->setFeature(Latte\Feature::StrictTypes); ``` .[note] -Since Latte 3.1, strict types are enabled by default. You can disable them with `$latte->setStrictTypes(false)`. +Since Latte 3.1, strict types are enabled by default. You can disable them with `$latte->setFeature(Latte\Feature::StrictTypes, false)`. Migration Warnings .{data-version:3.1} @@ -216,6 +230,70 @@ When enabled, Latte checks rendered attributes and triggers a user warning (`E_U Once all warnings are resolved, disable migration warnings and **remove all** `|accept` filters from your templates, as they are no longer needed. +Scoped Loop Variables .{data-version:3.1.3} +=========================================== + +By default, variables defined in a `{foreach}` loop (like `$key` and `$value`) remain accessible after the loop ends – just like in PHP itself. This can lead to unintended variable overwrites when a loop variable has the same name as an existing template variable. + +The `ScopedLoopVariables` feature limits the scope of loop variables to the loop body. After the loop ends, the original variable value is restored (if it existed before), or the variable is unset: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::ScopedLoopVariables); +``` + +Example of the difference: + +```latte +{var $item = 'original'} +{foreach [1, 2] as $item}{$item}, {/foreach} +{$item} +``` + +Without `ScopedLoopVariables`: outputs `1, 2, 2` (variable is overwritten) +With `ScopedLoopVariables`: outputs `1, 2, original` (variable is restored) + +This also works with destructuring syntax, e.g. `{foreach $array as [$a, $b]}`. + +.[note] +Loop variables using references (`{foreach $array as &$value}`) or property assignments (`{foreach $array as $obj->prop}`) are not scoped, as this would break their intended purpose. + + +Automatic Dedentation .{toc: Dedent}{data-version:3.1.3} +======================================================== + +When using paired tags like `{if}`, `{foreach}`, or `{block}`, you often indent the nested content for readability. However, this indentation is included in the generated output by default. The `Dedent` feature automatically removes it, so the output stays clean regardless of how deeply you nest your Latte tags: + +```php +$latte = new Latte\Engine; +$latte->setFeature(Latte\Feature::Dedent); +``` + +Example: + +```latte +{if true} + Hello + World +{/if} +``` + +Without `Dedent`, the output would include the indentation (`\tHello\n\tWorld\n`). With `Dedent`, the indentation is stripped and the output is `Hello\nWorld\n`. + +Deeper indentation within a block is preserved relative to the base indentation: + +```latte +{if true} + Hello + Indented +{/if} +``` + +Output: `Hello\n\tIndented\n`. + +Indentation within a block must be consistent (either tabs or spaces). If they are mixed, Latte throws an `Inconsistent indentation` exception. + + Translation in Templates .{toc: TranslatorExtension} ==================================================== diff --git a/latte/en/filters.texy b/latte/en/filters.texy index c87f8ffceb..813daf354d 100644 --- a/latte/en/filters.texy +++ b/latte/en/filters.texy @@ -10,6 +10,9 @@ In templates, we can use functions that help modify or reformat data into its fi | `breakLines` | [Inserts HTML line breaks before all newlines |#breakLines] | `bytes` | [formats size in bytes |#bytes] | `clamp` | [clamps a value to the given range |#clamp] +| `column` | [extracts a single column from an array |#column] +| `commas` | [joins an array with commas |#commas] +| `limit` | [limits the length of an array, string, or iterator |#limit] | `dataStream` | [Data URI protocol conversion |#dataStream] | `date` | [formats the date and time |#date] | `explode` | [splits a string into an array by a delimiter |#explode] @@ -259,6 +262,50 @@ Clamps a value to the given inclusive range of min and max. Also exists as a [function |functions#clamp]. +column(string|int|null $columnKey, string|int|null $indexKey=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------------------------------------------ +Returns the values of a single column `$columnKey` from a multidimensional array as a new array. Can also be used on arrays of objects to extract property values. + +```latte +{var $users = [ + [id: 30, name: 'John', age: 30], + [id: 32, name: 'Jane', age: 25], + [id: 33, age: 35], +]} + +{$users|column: 'name'} +{* returns ['John', 'Jane'] *} + +{$users|column: 'name', 'id'} +{* returns [30 => 'John', 32 => 'Jane'] *} +``` + +If you pass `null` as the column key, it will reindex the array according to `$indexKey`. + + +commas(?string $lastGlue=null) .[filter]{data-version:3.1.3} +------------------------------------------------------------ +Joins array elements with a comma and space (`', '`). A convenient shortcut for listing items in a human-readable format. + +```latte +{var $items = ['apples', 'oranges', 'bananas']} +{$items|commas} +{* outputs 'apples, oranges, bananas' *} +``` + +You can also provide a custom separator for the last pair of items: + +```latte +{$items|commas: ' and '} +{* outputs 'apples, oranges and bananas' *} + +{=['PHP', 'JavaScript', 'Python']|commas: ', or '} +{* outputs 'PHP, JavaScript, or Python' *} +``` + +See also [#implode]. + + dataStream(string $mimetype='detect') .[filter] ----------------------------------------------- Converts content to the data URI scheme. This allows embedding images into HTML or CSS without needing to link external files. @@ -407,6 +454,8 @@ You can also use the alias `join`: {=[1, 2, 3]|join} {* outputs '123' *} ``` +See also [#commas], [#explode]. + indent(int $level=1, string $char="\t") .[filter] ------------------------------------------------- @@ -637,19 +686,21 @@ Remember that the actual appearance of numbers may vary depending on the country padLeft(int $length, string $pad=' ') .[filter] ----------------------------------------------- -Pads a string to a certain length with another string from the left. +Pads a string or number to a certain length with another string from the left. ```latte {='hello'|padLeft: 10, '123'} {* outputs '12312hello' *} +{=123|padLeft: 5, '0'} {* outputs '00123' *} ``` padRight(int $length, string $pad=' ') .[filter] ------------------------------------------------ -Pads a string to a certain length with another string from the right. +Pads a string or number to a certain length with another string from the right. ```latte {='hello'|padRight: 10, '123'} {* outputs 'hello12312' *} +{=123|padRight: 5, '0'} {* outputs '12300' *} ``` @@ -747,14 +798,14 @@ See also [#ceil], [#floor]. slice(int $start, ?int $length=null, bool $preserveKeys=false) .[filter] ------------------------------------------------------------------------ -Extracts a slice of an array or a string. +Extracts a slice of an array, string, or iterator. ```latte {='hello'|slice: 1, 2} {* outputs 'el' *} {=['a', 'b', 'c']|slice: 1, 2} {* outputs ['b', 'c'] *} ``` -The filter works like the PHP function `array_slice` for arrays or `mb_substr` for strings, with a fallback to the `iconv_substr` function in UTF‑8 mode. +The filter works like the PHP function `array_slice` for arrays or `mb_substr` for strings. For iterators, it returns a generator – elements are consumed from the source one by one and reading stops once the limit is reached. The entire iterator is never loaded into memory. If `start` is non-negative, the sequence will start at that offset from the beginning of the array/string. If `start` is negative, the sequence will start that far from the end. @@ -762,6 +813,21 @@ If `length` is given and is positive, then the sequence will have up to that man By default, the filter reorders and resets the integer array keys. This behavior can be changed by setting `preserveKeys` to true. String keys are always preserved, regardless of this parameter. +See also [#limit]. + + +limit(int $length) .[filter]{data-version:3.1.3} +------------------------------------------------ +Limits the length of an array, string, or iterator. For arrays and iterators, keys are preserved. For strings, it respects UTF-8. + +```latte +{foreach ($items|limit: 5) as $item} + ... +{/foreach} + +{$text|limit: 100} +``` + sort(?Closure $comparison, string|int|\Closure|null $by=null, string|int|\Closure|bool $byKey=false) .[filter] -------------------------------------------------------------------------------------------------------------- diff --git a/latte/en/recipes.texy b/latte/en/recipes.texy index 37896b3ee5..7547e5b989 100644 --- a/latte/en/recipes.texy +++ b/latte/en/recipes.texy @@ -7,7 +7,7 @@ Editors and IDE Write templates in an editor or IDE that supports Latte. It will be much more pleasant. -- PhpStorm: install the [Latte plugin|https://plugins.jetbrains.com/plugin/7457-latte] in `Settings > Plugins > Marketplace` +- PhpStorm: install the [Latte plugin|https://plugins.jetbrains.com/plugin/24218-latte-support] in `Settings > Plugins > Marketplace` - VS Code: install [Nette Latte + Neon|https://marketplace.visualstudio.com/items?itemName=Kasik96.latte], [Nette Latte templates|https://marketplace.visualstudio.com/items?itemName=smuuf.latte-lang] or the latest [Nette for VS Code |https://marketplace.visualstudio.com/items?itemName=franken-ui.nette-for-vscode] plugin - NetBeans IDE: native support for Latte is included in the installation - Sublime Text 3: find and install the `Nette` package in Package Control and choose Latte in `View > Syntax` diff --git a/latte/en/safety-first.texy b/latte/en/safety-first.texy index 4e2c9480f4..004656ca94 100644 --- a/latte/en/safety-first.texy +++ b/latte/en/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Search results for ' . $search . '

                                    '; An attacker can enter any string into the search box, and thus into the `$search` variable, including HTML code like ``. Since the output is not sanitized, it becomes part of the displayed page: -```html +```latte

                                    Search results for

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; An attacker simply needs to insert a cleverly crafted string `" onload="alert('Hacked!')` as the caption, and if the output is not sanitized, the resulting code will look like this: -```html +```latte ``` @@ -91,7 +91,7 @@ Context-Aware Escaping What exactly is meant by the word context? It's a location within the document with its own rules for handling the data being printed. It depends on the document type (HTML, XML, CSS, JavaScript, plain text, ...) and can differ in specific parts. For example, in an HTML document, there are many places (contexts) where very different rules apply. You might be surprised how many there are. Here are the first four: -```html +```latte

                                    #text

                                    @@ -108,7 +108,7 @@ It gets interesting inside HTML comments. Here, HTML entities are not used for e Contexts can also be layered, which occurs when we embed JavaScript or CSS into HTML. This can be done in two different ways, using an element or an attribute: -```html +```latte @@ -132,7 +132,7 @@ Let's take the string `Rock'n'Roll`. If you print it in HTML text, in this particular case, no replacement is needed because the string does not contain any characters with special meaning. The situation changes if you print it inside an HTML attribute enclosed in single quotes. In that case, you need to escape the quotes into HTML entities: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); If we insert this code into an HTML document using ` ``` However, if we wanted to insert it into an HTML attribute, we still need to escape the quotes into HTML entities: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll And when we print this string in an attribute, we still apply escaping according to this context and replace `&` with `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Notice that there are no quotes around the attribute values. The coder might hav An attacker inserts a cleverly crafted string `foo onload=alert('Hacked!')` as the image caption. We already know that Twig cannot determine whether a variable is being printed in the HTML text flow, inside an attribute, an HTML comment, etc.; in short, it does not distinguish contexts. And it just mechanically converts the characters `< > & ' "` into HTML entities. So the resulting code will look like this: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Now let's see how Latte handles the same template: Latte sees the template the same way you do. Unlike Twig, it understands HTML and knows that the variable is being printed as the value of an attribute that is not enclosed in quotes. Therefore, it adds them. When an attacker inserts the same caption, the resulting code will look like this: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/en/syntax.texy b/latte/en/syntax.texy index ef926e75be..aa7e274f5f 100644 --- a/latte/en/syntax.texy +++ b/latte/en/syntax.texy @@ -218,6 +218,41 @@ PHP comments work inside tags: ``` +Whitespace Control +================== + +Latte handles whitespace intelligently. You can freely indent your code for readability, and the output stays clean. When a tag appears alone on a line, the entire line (indentation and newline) is removed from the output: + +```latte +
                                      + {foreach $items as $item} +
                                    • {$item}
                                    • + {/foreach} +
                                    +``` + +Outputs: + +```latte +
                                      +
                                    • foo
                                    • +
                                    • bar
                                    • +
                                    +``` + +What if a tag isn't alone on a line, but appears alongside other content? The whitespace before the tag then belongs *inside* the tag: + +```latte +
                                    + {if $foo}hello{/if} +
                                    +``` + +The indentation is effectively inside `{if}`: when `$foo` is false, nothing is output – not even the indentation or a blank line. When `$foo` is true, the output naturally includes the indentation. You simply write well-structured templates and the output is always clean. + +For even cleaner output, you can enable the [Dedent |develop#Dedent] feature, which also removes indentation caused by nesting within paired tags like `{if}` or `{foreach}`. + + Syntactic Sugar =============== diff --git a/latte/en/tags.texy b/latte/en/tags.texy index cfbc94ae6f..ffb90c69c1 100644 --- a/latte/en/tags.texy +++ b/latte/en/tags.texy @@ -137,7 +137,7 @@ You can write anything you know from PHP as an expression. You simply don't have ```latte -{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION} +{='0' . ($num ?? $num * 3) . ', ' . \PHP_VERSION} ``` Please don't look for any meaning in the previous example, but if you find one, let us know :-) diff --git a/latte/es/custom-tags.texy b/latte/es/custom-tags.texy index f32e309910..fbb0646b5b 100644 --- a/latte/es/custom-tags.texy +++ b/latte/es/custom-tags.texy @@ -923,7 +923,7 @@ Ahora puede usar `n:confirm` en enlaces, botones o elementos de formulario: HTML generado: -```html +```latte
                                    Eliminar ``` diff --git a/latte/es/safety-first.texy b/latte/es/safety-first.texy index 437dd39aac..6fe173ea9c 100644 --- a/latte/es/safety-first.texy +++ b/latte/es/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Resultados de la búsqueda para ' . $search . '

                                    '; Un atacante puede escribir en el campo de búsqueda y, por extensión, en la variable `$search` cualquier cadena, incluido código HTML como ``. Dado que la salida no está saneada de ninguna manera, se convierte en parte de la página mostrada: -```html +```latte

                                    Resultados de la búsqueda para

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Al atacante le basta con insertar como descripción una cadena hábilmente construida `" onload="alert('Hacked!')` y si la impresión no está saneada, el código resultante se verá así: -```html +```latte ``` @@ -91,7 +91,7 @@ Escape sensible al contexto ¿Qué se entiende exactamente por la palabra contexto? Es un lugar en el documento con sus propias reglas para el saneamiento de los datos impresos. Depende del tipo de documento (HTML, XML, CSS, JavaScript, texto plano, ...) y puede diferir en sus partes específicas. Por ejemplo, en un documento HTML hay muchos lugares (contextos) donde se aplican reglas muy diferentes. Quizás se sorprenda de cuántos hay. Aquí tenemos los primeros cuatro: -```html +```latte

                                    #texto

                                    @@ -108,7 +108,7 @@ Es interesante dentro de los comentarios HTML. Aquí, el escape no se realiza ut Los contextos también pueden anidarse, lo que ocurre cuando insertamos JavaScript o CSS en HTML. Esto se puede hacer de dos maneras diferentes, con un elemento y con un atributo: -```html +```latte @@ -132,7 +132,7 @@ Tomemos la cadena `Rock'n'Roll`. Si la imprime en texto HTML, en este caso particular no es necesario realizar ningún reemplazo, porque la cadena no contiene ningún carácter con significado especial. La situación cambia si la imprime dentro de un atributo HTML delimitado por comillas simples. En ese caso, es necesario escapar las comillas a entidades HTML: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Si insertamos este código en un documento HTML usando ` ``` Sin embargo, si quisiéramos insertarlo en un atributo HTML, aún debemos escapar las comillas a entidades HTML: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Y cuando imprimimos esta cadena en un atributo, aún aplicamos el escape según este contexto y reemplazamos `&` por `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Observe que no hay comillas alrededor de los valores de los atributos. El codifi Un atacante inserta como descripción de la imagen una cadena hábilmente construida `foo onload=alert('Hacked!')`. Ya sabemos que Twig no puede saber si la variable se imprime en el flujo de texto HTML, dentro de un atributo, comentario HTML, etc., en resumen, no distingue contextos. Y solo convierte mecánicamente los caracteres `< > & ' "` en entidades HTML. Así que el código resultante se verá así: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Ahora veamos cómo Latte maneja la misma plantilla: Latte ve la plantilla igual que usted. A diferencia de Twig, entiende HTML y sabe que la variable se imprime como el valor de un atributo que no está entre comillas. Por eso las añade. Cuando un atacante inserta la misma descripción, el código resultante se verá así: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/fr/custom-tags.texy b/latte/fr/custom-tags.texy index 29c14a08a8..9983a44429 100644 --- a/latte/fr/custom-tags.texy +++ b/latte/fr/custom-tags.texy @@ -923,7 +923,7 @@ Vous pouvez maintenant utiliser `n:confirm` sur des liens, des boutons ou des é HTML généré : -```html +```latte Supprimer ``` diff --git a/latte/fr/safety-first.texy b/latte/fr/safety-first.texy index e4b3f5a93a..d9476e4305 100644 --- a/latte/fr/safety-first.texy +++ b/latte/fr/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Résultats de la recherche pour ' . $search . '

                                    '; Un attaquant peut entrer dans le champ de recherche et donc dans la variable `$search` n'importe quelle chaîne, y compris du code HTML comme ``. Comme la sortie n'est pas traitée, elle devient partie intégrante de la page affichée : -```html +```latte

                                    Résultats de la recherche pour

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Il suffit à l'attaquant d'insérer comme légende une chaîne habilement construite `" onload="alert('Piraté !')` et si l'affichage n'est pas traité, le code résultant ressemblera à ceci : -```html +```latte ``` @@ -91,7 +91,7 @@ Cependant, XSS ne concerne pas seulement l'affichage des données dans les templ Que signifie exactement le mot contexte ? C'est un endroit dans le document avec ses propres règles pour traiter les données affichées. Il dépend du type de document (HTML, XML, CSS, JavaScript, texte brut, ...) et peut varier dans ses parties spécifiques. Par exemple, dans un document HTML, il existe de nombreux endroits (contextes) où des règles très différentes s'appliquent. Vous serez peut-être surpris de leur nombre. Voici les quatre premiers : -```html +```latte

                                    #texte

                                    @@ -108,7 +108,7 @@ C'est intéressant à l'intérieur des commentaires HTML. Ici, l'échappement n' Les contextes peuvent également être imbriqués, ce qui se produit lorsque nous insérons du JavaScript ou du CSS dans du HTML. Cela peut être fait de deux manières différentes, par élément et par attribut : -```html +```latte @@ -132,7 +132,7 @@ Prenons la chaîne `Rock'n'Roll`. Si vous l'affichez dans du texte HTML, dans ce cas précis, il n'est pas nécessaire de faire de remplacements, car la chaîne ne contient aucun caractère ayant une signification spéciale. La situation change si vous l'affichez à l'intérieur d'un attribut HTML entouré de guillemets simples. Dans ce cas, il faut échapper les guillemets en entités HTML : -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Si nous insérons ce code dans un document HTML à l'aide de ` ``` Cependant, si nous voulions l'insérer dans un attribut HTML, nous devrions encore échapper les guillemets en entités HTML : -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Et lorsque nous affichons cette chaîne dans un attribut, nous appliquons encore l'échappement selon ce contexte et remplaçons `&` par `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Notez qu'il n'y a pas de guillemets autour des valeurs des attributs. Le codeur L'attaquant insère comme légende de l'image une chaîne habilement construite `foo onload=alert('Piraté !')`. Nous savons déjà que Twig ne peut pas savoir si la variable est affichée dans le flux de texte HTML, à l'intérieur d'un attribut, d'un commentaire HTML, etc., bref, il ne distingue pas les contextes. Et il ne fait que convertir mécaniquement les caractères `< > & ' "` en entités HTML. Le code résultant ressemblera donc à ceci : -```html +```latte foo ``` @@ -330,7 +330,7 @@ Voyons maintenant comment Latte gère le même template : Latte voit le template de la même manière que vous. Contrairement à Twig, il comprend HTML et sait que la variable est affichée comme valeur d'un attribut qui n'est pas entre guillemets. C'est pourquoi il les ajoute. Lorsque l'attaquant insère la même légende, le code résultant ressemblera à ceci : -```html +```latte foo onload=alert('Piraté !') ``` diff --git a/latte/hu/custom-tags.texy b/latte/hu/custom-tags.texy index f8e2946305..6b7f70dbe5 100644 --- a/latte/hu/custom-tags.texy +++ b/latte/hu/custom-tags.texy @@ -923,7 +923,7 @@ Most már használhatja az `n:confirm`-ot linkeken, gombokon vagy űrlap elemeke Generált HTML: -```html +```latte Törlés ``` diff --git a/latte/hu/safety-first.texy b/latte/hu/safety-first.texy index a07f648fe6..a1b2547fa0 100644 --- a/latte/hu/safety-first.texy +++ b/latte/hu/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Keresési eredmények erre: ' . $search . '

                                    '; A támadó a keresőmezőbe és ezáltal a `$search` változóba bármilyen stringet beírhat, tehát HTML kódot is, mint ``. Mivel a kimenet nincs semmilyen módon kezelve, a megjelenített oldal részévé válik: -```html +```latte

                                    Keresési eredmények erre:

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; A támadónak elég leírásként egy ügyesen összeállított `" onload="alert('Hacked!')` stringet beilleszteni, és ha a kiírás nincs kezelve, az eredményül kapott kód így fog kinézni: -```html +```latte ``` @@ -91,7 +91,7 @@ Kontextusérzékeny escapelés Mit jelent pontosan a kontextus szó? Ez egy hely a dokumentumban, saját szabályokkal a kiírt adatok kezelésére. A dokumentum típusától (HTML, XML, CSS, JavaScript, plain text, ...) függ, és eltérhet annak konkrét részeiben. Például egy HTML dokumentumban számos ilyen hely (kontextus) van, ahol nagyon eltérő szabályok érvényesek. Talán meglepődik, mennyi van belőlük. Íme az első négy: -```html +```latte

                                    #szöveg

                                    @@ -108,7 +108,7 @@ Talán meglepő, de speciális szabályok érvényesek a ` @@ -108,7 +108,7 @@ Potresti essere sorpreso, ma regole speciali si applicano all'interno degli elem I contesti possono anche essere annidati, cosa che accade quando inseriamo JavaScript o CSS in HTML. Questo può essere fatto in due modi diversi, con un elemento e con un attributo: -```html +```latte @@ -132,7 +132,7 @@ Prendiamo la stringa `Rock'n'Roll`. Se la stampi nel testo HTML, proprio in questo caso non è necessario effettuare alcuna sostituzione, perché la stringa non contiene alcun carattere con significato speciale. La situazione cambia se la stampi all'interno di un attributo HTML racchiuso tra apici singoli. In tal caso, è necessario eseguire l'escaping degli apici in entità HTML: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Se inseriamo questo codice nel documento HTML usando ` ``` Se però volessimo inserirlo in un attributo HTML, dobbiamo ancora eseguire l'escaping degli apici in entità HTML: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll E quando stampiamo questa stringa in un attributo, applichiamo ancora l'escaping secondo questo contesto e sostituiamo `&` con `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Notate che non ci sono virgolette attorno ai valori degli attributi. Il codifica Un aggressore inserisce come didascalia dell'immagine una stringa abilmente costruita `foo onload=alert('Hacked!')`. Sappiamo già che Twig non può riconoscere se la variabile viene stampata nel flusso del testo HTML, all'interno di un attributo, di un commento HTML, ecc., in breve non distingue i contesti. E converte meccanicamente solo i caratteri `< > & ' "` in entità HTML. Quindi il codice risultante sarà simile a questo: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Ora vediamo come Latte gestisce lo stesso template: Latte vede il template come lo vedi tu. A differenza di Twig, capisce HTML e sa che la variabile viene stampata come valore di un attributo che non è tra virgolette. Pertanto le aggiunge. Quando l'aggressore inserisce la stessa didascalia, il codice risultante sarà simile a questo: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/ja/custom-tags.texy b/latte/ja/custom-tags.texy index a3114b7964..347975a50b 100644 --- a/latte/ja/custom-tags.texy +++ b/latte/ja/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension 生成されたHTML: -```html +```latte 削除 ``` diff --git a/latte/ja/safety-first.texy b/latte/ja/safety-first.texy index 15f0190eb4..1e2c48e606 100644 --- a/latte/ja/safety-first.texy +++ b/latte/ja/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    検索結果: ' . $search . '

                                    '; 攻撃者は、検索ボックス、ひいては変数 `$search` に任意の文字列、つまり `` のようなHTMLコードを入力できます。出力がサニタイズされていないため、表示されるページの一部になります: -```html +```latte

                                    検索結果:

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; 攻撃者は、説明として巧妙に作成された文字列 `" onload="alert('Hacked!')` を挿入するだけで、出力がサニタイズされていない場合、結果のコードは次のようになります: -```html +```latte ``` @@ -91,7 +91,7 @@ XSSからどのように防御しますか? コンテキストという言葉で正確には何を意味しますか?それは、出力されるデータのサニタイズに関する独自のルールを持つドキュメント内の場所です。それはドキュメントのタイプ(HTML、XML、CSS、JavaScript、プレーンテキストなど)に依存し、その特定の場所によって異なる場合があります。 例えば、HTMLドキュメントには、非常に異なるルールが適用される多くの場所(コンテキスト)があります。いくつあるか驚くかもしれません。ここに最初の4つがあります: -```html +```latte

                                    #テキスト

                                    @@ -108,7 +108,7 @@ HTMLコメント内では興味深いです。ここでは、エスケープにH コンテキストはネストすることもできます。これは、JavaScriptまたはCSSをHTMLに埋め込むときに発生します。これは2つの異なる方法、要素と属性で行うことができます: -```html +```latte @@ -132,7 +132,7 @@ HTMLコメント内では興味深いです。ここでは、エスケープにH HTMLテキストに出力する場合、この特定のケースでは、文字列に特別な意味を持つ文字が含まれていないため、置換を行う必要はありません。状況は、単一引用符で囲まれたHTML属性内に出力する場合に異なります。その場合、引用符をHTMLエンティティにエスケープする必要があります: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); このコードを ` ``` しかし、HTML属性に挿入したい場合は、さらに引用符をHTMLエンティティにエスケープする必要があります: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll そして、この文字列を属性に出力するとき、このコンテキストに従ってエスケープを適用し、`&` を `&` に置き換えます: -```html +```latte ``` @@ -314,7 +314,7 @@ Latteはテンプレートをあなたと同じように見ます。HTML、XML 攻撃者は、画像の説明として巧妙に作成された文字列 `foo onload=alert('Hacked!')` を挿入します。Twigは、変数がHTMLテキストの流れの中、属性内、HTMLコメント内など、どこに出力されているかを判断できないこと、つまりコンテキストを区別しないことをすでに知っています。そして、文字 `< > & ' "` を機械的にHTMLエンティティに変換するだけです。 したがって、結果のコードは次のようになります: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Latteはテンプレートをあなたと同じように見ます。HTML、XML Latteはテンプレートをあなたと同じように見ます。Twigとは異なり、HTMLを理解し、変数が引用符で囲まれていない属性の値として出力されていることを知っています。したがって、それらを補完します。攻撃者が同じ説明を挿入すると、結果のコードは次のようになります: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/pl/custom-tags.texy b/latte/pl/custom-tags.texy index 50be9f0562..8dd42d7929 100644 --- a/latte/pl/custom-tags.texy +++ b/latte/pl/custom-tags.texy @@ -923,7 +923,7 @@ Teraz możesz użyć `n:confirm` na linkach, przyciskach lub elementach formular Wygenerowany HTML: -```html +```latte Usuń ``` diff --git a/latte/pl/safety-first.texy b/latte/pl/safety-first.texy index dc1f49265c..d8a666e1d7 100644 --- a/latte/pl/safety-first.texy +++ b/latte/pl/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Wyniki wyszukiwania dla ' . $search . '

                                    '; Atakujący może w polu wyszukiwania, a tym samym w zmiennej `$search`, wpisać dowolny ciąg znaków, czyli również kod HTML, taki jak ``. Ponieważ wyjście nie jest w żaden sposób oczyszczone, stanie się częścią wyświetlonej strony: -```html +```latte

                                    Wyniki wyszukiwania dla

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Atakującemu wystarczy jako opis wstawić sprytnie skonstruowany ciąg `" onload="alert('Hacked!')`, a jeśli wyświetlanie nie zostanie oczyszczone, wynikowy kod będzie wyglądał tak: -```html +```latte ``` @@ -91,7 +91,7 @@ Escapowanie kontekstowe Co dokładnie oznacza słowo kontekst? Jest to miejsce w dokumencie z własnymi zasadami oczyszczania wyświetlanych danych. Zależy od typu dokumentu (HTML, XML, CSS, JavaScript, plain text, ...) i może się różnić w jego poszczególnych częściach. Na przykład w dokumencie HTML istnieje wiele takich miejsc (kontekstów), gdzie obowiązują bardzo różne zasady. Być może będziesz zaskoczony, ile ich jest. Oto pierwsza czwórka: -```html +```latte

                                    #text

                                    @@ -108,7 +108,7 @@ Ciekawie jest wewnątrz komentarzy HTML. Tutaj bowiem do escapowania nie używa Konteksty mogą się również nakładać, co ma miejsce, gdy wstawiamy JavaScript lub CSS do HTML. Można to zrobić na dwa różne sposoby, elementem i atrybutem: -```html +```latte @@ -132,7 +132,7 @@ Miejmy ciąg `Rock'n'Roll`. Jeśli będziesz go wyświetlać w tekście HTML, akurat w tym przypadku nie trzeba dokonywać żadnych zamian, ponieważ ciąg nie zawiera żadnego znaku o specjalnym znaczeniu. Inna sytuacja nastąpi, jeśli wyświetlisz go wewnątrz atrybutu HTML ujętego w pojedyncze cudzysłowy. W takim przypadku trzeba escapować cudzysłowy na encje HTML: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Jeśli ten kod wstawimy do dokumentu HTML za pomocą ` ``` Jeśli jednak chcielibyśmy go wstawić do atrybutu HTML, musimy jeszcze escapować cudzysłowy na encje HTML: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll A kiedy ten ciąg wyświetlimy w atrybucie, jeszcze zastosujemy escapowanie zgodnie z tym kontekstem i zastąpimy `&` na `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Zwróć uwagę, że wokół wartości atrybutów nie ma cudzysłowów. Koder mó Atakujący jako opis obrazka wstawia sprytnie skonstruowany ciąg `foo onload=alert('Hacked!')`. Już wiemy, że Twig nie może rozpoznać, czy zmienna jest wyświetlana w przepływie tekstu HTML, wewnątrz atrybutu, komentarza HTML itp., krótko mówiąc, nie rozróżnia kontekstów. I tylko mechanicznie konwertuje znaki `< > & ' "` na encje HTML. Więc wynikowy kod będzie wyglądał tak: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Teraz zobaczymy, jak z tym samym szablonem poradzi sobie Latte: Latte widzi szablon tak samo jak Ty. W przeciwieństwie do Twiga rozumie HTML i wie, że zmienna jest wyświetlana jako wartość atrybutu, który nie jest w cudzysłowach. Dlatego je uzupełni. Kiedy atakujący wstawi ten sam opis, wynikowy kod będzie wyglądał tak: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/pt/custom-tags.texy b/latte/pt/custom-tags.texy index b080e9e20b..1e523ed866 100644 --- a/latte/pt/custom-tags.texy +++ b/latte/pt/custom-tags.texy @@ -923,7 +923,7 @@ Agora você pode usar `n:confirm` em links, botões ou elementos de formulário: HTML gerado: -```html +```latte Excluir ``` diff --git a/latte/pt/safety-first.texy b/latte/pt/safety-first.texy index 049ff1ae25..5e0351605c 100644 --- a/latte/pt/safety-first.texy +++ b/latte/pt/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Resultados da pesquisa para ' . $search . '

                                    '; Um atacante pode inserir na caixa de pesquisa e, consequentemente, na variável `$search`, qualquer string, ou seja, também código HTML como ``. Como a saída não é tratada de forma alguma, ela torna-se parte da página exibida: -```html +```latte

                                    Resultados da pesquisa para

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Basta ao atacante inserir como legenda uma string habilmente construída `" onload="alert('Hacked!')` e, se a exibição não for tratada, o código resultante será assim: -```html +```latte ``` @@ -91,7 +91,7 @@ Escaping sensível ao contexto O que exatamente se entende pela palavra contexto? É um local no documento com as suas próprias regras para o tratamento dos dados exibidos. Depende do tipo de documento (HTML, XML, CSS, JavaScript, texto simples, ...) e pode diferir nas suas partes específicas. Por exemplo, num documento HTML, existem muitos desses locais (contextos), onde regras muito diferentes se aplicam. Pode surpreender-se com quantos existem. Aqui temos os quatro primeiros: -```html +```latte

                                    #texto

                                    @@ -108,7 +108,7 @@ Pode surpreender-se, mas regras especiais aplicam-se dentro dos elementos `#js-elemento @@ -132,7 +132,7 @@ Tenha a string `Rock'n'Roll`. Se a exibir em texto HTML, neste caso específico não é necessário fazer nenhuma substituição, pois a string não contém nenhum caractere com significado especial. A situação muda se a exibir dentro de um atributo HTML delimitado por aspas simples. Nesse caso, é necessário escapar as aspas para entidades HTML: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Se inserirmos este código num documento HTML usando ` ``` No entanto, se quiséssemos inseri-lo num atributo HTML, ainda precisaríamos de escapar as aspas para entidades HTML: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll E quando exibimos esta string num atributo, ainda aplicamos o escaping de acordo com este contexto e substituímos `&` por `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Observe que não há aspas em torno dos valores dos atributos. O codificador pod Um atacante insere como legenda da imagem uma string habilmente construída `foo onload=alert('Hacked!')`. Já sabemos que o Twig não pode saber se a variável está a ser exibida no fluxo de texto HTML, dentro de um atributo, comentário HTML, etc., em suma, não distingue contextos. E apenas converte mecanicamente os caracteres `< > & ' "` em entidades HTML. Então, o código resultante será assim: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Agora veremos como o Latte lida com o mesmo template: O Latte vê o template da mesma forma que você. Ao contrário do Twig, ele entende HTML e sabe que a variável está a ser exibida como o valor de um atributo que não está entre aspas. Portanto, ele adiciona-as. Quando o atacante insere a mesma legenda, o código resultante será assim: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/ro/custom-tags.texy b/latte/ro/custom-tags.texy index bc12920a37..3c353caabb 100644 --- a/latte/ro/custom-tags.texy +++ b/latte/ro/custom-tags.texy @@ -923,7 +923,7 @@ Acum puteți utiliza `n:confirm` pe linkuri, butoane sau elemente de formular: HTML generat: -```html +```latte Șterge ``` diff --git a/latte/ro/safety-first.texy b/latte/ro/safety-first.texy index 8140ba61d3..b4948a948d 100644 --- a/latte/ro/safety-first.texy +++ b/latte/ro/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Rezultatele căutării pentru ' . $search . '

                                    '; Un atacator poate introduce în câmpul de căutare și, implicit, în variabila `$search`, orice șir, deci și cod HTML precum ``. Deoarece ieșirea nu este tratată în niciun fel, aceasta devine parte a paginii afișate: -```html +```latte

                                    Rezultatele căutării pentru

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Atacatorului îi este suficient să introducă ca descriere un șir inteligent construit `" onload="alert('Hacked!')` și dacă afișarea nu este tratată, codul rezultat va arăta astfel: -```html +```latte ``` @@ -91,7 +91,7 @@ Escapare contextuală sensibilă Ce se înțelege exact prin cuvântul context? Este un loc în document cu propriile reguli pentru tratarea datelor afișate. Depinde de tipul documentului (HTML, XML, CSS, JavaScript, plain text, ...) și poate diferi în părțile sale specifice. De exemplu, într-un document HTML există o serie întreagă de astfel de locuri (contexte) unde se aplică reguli foarte diferite. Poate veți fi surprinși câte sunt. Iată primele patru: -```html +```latte

                                    #text

                                    @@ -108,7 +108,7 @@ Interesant este în interiorul comentariilor HTML. Aici, escaparea nu se face fo Contexturile se pot și stratifica, ceea ce se întâmplă când inserăm JavaScript sau CSS în HTML. Acest lucru se poate face în două moduri diferite, prin element și atribut: -```html +```latte @@ -132,7 +132,7 @@ Să avem șirul `Rock'n'Roll`. Dacă îl veți afișa în text HTML, în acest caz particular nu este nevoie de nicio înlocuire, deoarece șirul nu conține niciun caracter cu semnificație specială. Situația se schimbă dacă îl afișați în interiorul unui atribut HTML delimitat de apostrofuri simple. În acest caz, este necesar să escapați apostrofurile în entități HTML: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Dacă inserăm acest cod într-un document HTML folosind ` ``` Dacă am dori însă să îl inserăm într-un atribut HTML, trebuie să mai escapăm ghilimelele în entități HTML: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Și când afișăm acest șir într-un atribut, aplicăm și escaparea conform acestui context și înlocuim `&` cu `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Observați că în jurul valorilor atributelor nu există ghilimele. Coderul le- Atacatorul introduce ca descriere a imaginii un șir inteligent construit `foo onload=alert('Hacked!')`. Știm deja că Twig nu poate recunoaște dacă variabila se afișează în fluxul textului HTML, în interiorul unui atribut, comentariu HTML etc., pe scurt, nu distinge contextele. Și doar convertesc mecanic caracterele `< > & ' "` în entități HTML. Deci, codul rezultat va arăta astfel: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Acum să vedem cum se descurcă Latte cu același șablon: Latte vede șablonul la fel ca dvs. Spre deosebire de Twig, înțelege HTML și știe că variabila se afișează ca valoare a unui atribut care nu este între ghilimele. De aceea, le completează. Când atacatorul introduce aceeași descriere, codul rezultat va arăta astfel: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/ru/custom-tags.texy b/latte/ru/custom-tags.texy index dc35fdad01..3c0cd691eb 100644 --- a/latte/ru/custom-tags.texy +++ b/latte/ru/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Сгенерированный HTML: -```html +```latte Удалить ``` diff --git a/latte/ru/safety-first.texy b/latte/ru/safety-first.texy index 96b91313cc..ffd79d93c4 100644 --- a/latte/ru/safety-first.texy +++ b/latte/ru/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Результаты поиска для ' . $search . '

                                    '; Злоумышленник может в поле поиска и, соответственно, в переменную `$search` записать любую строку, в том числе и HTML-код, например ``. Поскольку вывод никак не обрабатывается, он станет частью отображаемой страницы: -```html +```latte

                                    Результаты поиска для

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Злоумышленнику достаточно в качестве описания вставить хитро составленную строку `" onload="alert('Hacked!')`, и если вывод не будет обработан, результирующий код будет выглядеть так: -```html +```latte ``` @@ -91,7 +91,7 @@ echo '' . $imageAlt . ''; Что именно подразумевается под словом контекст? Это место в документе со своими правилами обработки выводимых данных. Зависит от типа документа (HTML, XML, CSS, JavaScript, plain text, ...) и может отличаться в его конкретных частях. Например, в HTML-документе таких мест (контекстов), где действуют очень разные правила, целое множество. Возможно, вы удивитесь, сколько их. Вот первая четверка: -```html +```latte

                                    #текст

                                    @@ -108,7 +108,7 @@ echo '' . $imageAlt . ''; Контексты также могут вкладываться, что происходит, когда мы вставляем JavaScript или CSS в HTML. Это можно сделать двумя разными способами, элементом и атрибутом: -```html +```latte @@ -132,7 +132,7 @@ echo '' . $imageAlt . ''; Если вы будете выводить ее в HTML-тексте, то в данном случае не нужно делать никаких замен, потому что строка не содержит ни одного символа со специальным значением. Другая ситуация возникнет, если вы выведете ее внутри HTML-атрибута, заключенного в одинарные кавычки. В таком случае необходимо экранировать кавычки в HTML-сущности: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Если этот код вставить в HTML-документ с помощью ` ``` Однако, если бы мы хотели вставить его в HTML-атрибут, нужно еще экранировать кавычки в HTML-сущности: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll А когда мы выводим эту строку в атрибуте, еще применяем экранирование в соответствии с этим контекстом и заменяем `&` на `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Latte видит шаблон так же, как и вы. Он понимает Злоумышленник в качестве описания изображения вставляет хитро составленную строку `foo onload=alert('Hacked!')`. Мы уже знаем, что Twig не может определить, выводится ли переменная в потоке HTML-текста, внутри атрибута, HTML-комментария и т. д., короче говоря, не различает контексты. И просто механически преобразует символы `< > & ' "` в HTML-сущности. Так что результирующий код будет выглядеть так: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Latte видит шаблон так же, как и вы. Он понимает Latte видит шаблон так же, как и вы. В отличие от Twig, он понимает HTML и знает, что переменная выводится как значение атрибута, который не заключен в кавычки. Поэтому он их добавит. Когда злоумышленник вставит то же описание, результирующий код будет выглядеть так: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/sl/custom-tags.texy b/latte/sl/custom-tags.texy index 1066b5eb86..1bb1570146 100644 --- a/latte/sl/custom-tags.texy +++ b/latte/sl/custom-tags.texy @@ -923,7 +923,7 @@ Zdaj lahko uporabite `n:confirm` na povezavah, gumbih ali elementih obrazca: Generirana HTML koda: -```html +```latte Izbriši ``` diff --git a/latte/sl/safety-first.texy b/latte/sl/safety-first.texy index 509802d6c8..29adc447e2 100644 --- a/latte/sl/safety-first.texy +++ b/latte/sl/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Rezultati iskanja za ' . $search . '

                                    '; Napadalec lahko v iskalno polje in posledično v spremenljivko `$search` zapiše poljuben niz, torej tudi HTML kodo kot ``. Ker izpis ni nikakor obdelan, postane del prikazane strani: -```html +```latte

                                    Rezultati iskanja za

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Napadalcu zadostuje, da kot opis vstavi spretno sestavljen niz `" onload="alert('Hacked!')` in če izpis ne bo obdelan, bo rezultatna koda izgledala takole: -```html +```latte ``` @@ -91,7 +91,7 @@ Kontekstno občutljivo ubežanje Kaj točno se misli z besedo kontekst? Gre za mesto v dokumentu z lastnimi pravili za obdelavo izpisanih podatkov. Odvisno je od vrste dokumenta (HTML, XML, CSS, JavaScript, navadno besedilo, ...) in se lahko razlikuje v njegovih konkretnih delih. Na primer, v dokumentu HTML je takih mest (kontekstov), kjer veljajo zelo različna pravila, cela vrsta. Morda boste presenečeni, koliko jih je. Tukaj imamo prvo četverico: -```html +```latte

                                    #text

                                    @@ -108,7 +108,7 @@ Zanimivo je znotraj komentarjev HTML. Tukaj se namreč za ubežanje ne uporablja Konteksti se lahko tudi plastijo, do česar pride, ko vstavimo JavaScript ali CSS v HTML. To je mogoče storiti na dva različna načina, z elementom in atributom: -```html +```latte @@ -132,7 +132,7 @@ Imejmo niz `Rock'n'Roll`. Če ga boste izpisovali v besedilu HTML, ravno v tem primeru ni treba delati nobenih zamenjav, ker niz ne vsebuje nobenega znaka s posebnim pomenom. Druga situacija nastane, če ga izpišete znotraj atributa HTML, omejenega z enojnimi narekovaji. V takem primeru je treba narekovaje ubežati v HTML entitete: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Če to kodo vstavimo v dokument HTML s pomočjo ` ``` Če pa bi jo želeli vstaviti v atribut HTML, moramo še ubežati narekovaje v HTML entitete: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll In ko ta niz izpišemo v atributu, še uporabimo ubežanje po tem kontekstu in zamenjamo `&` za `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Opazite, da okoli vrednosti atributov ni narekovajev. Koder jih je lahko pozabil Napadalec kot opis slike vstavi spretno sestavljen niz `foo onload=alert('Hacked!')`. Že vemo, da Twig ne more prepoznati, ali se spremenljivka izpisuje v toku besedila HTML, znotraj atributa, komentarja HTML, itd., skratka ne razlikuje kontekstov. In samo mehansko pretvarja znake `< > & ' "` v HTML entitete. Torej bo rezultatna koda izgledala takole: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Zdaj si poglejmo, kako se z enako predlogo spopade Latte: Latte vidi predlogo enako kot vi. Za razliko od Twiga razume HTML in ve, da se spremenljivka izpisuje kot vrednost atributa, ki ni v narekovajih. Zato jih dopolni. Ko napadalec vstavi enak opis, bo rezultatna koda izgledala takole: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/latte/tr/custom-tags.texy b/latte/tr/custom-tags.texy index 402e361e28..8f582915f0 100644 --- a/latte/tr/custom-tags.texy +++ b/latte/tr/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Oluşturulan HTML: -```html +```latte Sil ``` diff --git a/latte/tr/safety-first.texy b/latte/tr/safety-first.texy index a4943315fd..9e550024e2 100644 --- a/latte/tr/safety-first.texy +++ b/latte/tr/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    ' . $search . ' için arama sonuçları

                                    '; Saldırgan, arama kutusuna ve dolayısıyla `$search` değişkenine `` gibi HTML kodu da dahil olmak üzere herhangi bir karakter dizisi yazabilir. Çıktı hiçbir şekilde işlenmediği için, görüntülenen sayfanın bir parçası haline gelir: -```html +```latte

                                    için arama sonuçları

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Saldırganın açıklama olarak akıllıca oluşturulmuş bir karakter dizisi `" onload="alert('Hacklendiniz!')` eklemesi yeterlidir ve yazdırma işlenmezse, sonuç kodu şöyle görünecektir: -```html +```latte ``` @@ -91,7 +91,7 @@ Bağlama Duyarlı Kaçış Bağlam kelimesiyle tam olarak ne kastediliyor? Belgenin içinde, yazdırılan verilerin işlenmesi için kendi kuralları olan bir yerdir. Belgenin türüne (HTML, XML, CSS, JavaScript, düz metin, ...) bağlıdır ve belirli bölümlerinde farklılık gösterebilir. Örneğin, bir HTML belgesinde, çok farklı kuralların geçerli olduğu birçok yer (bağlam) vardır. Kaç tane olduğuna şaşırabilirsiniz. İşte ilk dördü: -```html +```latte

                                    #metin

                                    @@ -108,7 +108,7 @@ HTML yorumlarının içi ilginçtir. Burada kaçış için HTML varlıkları kul Bağlamlar ayrıca katmanlanabilir, bu da HTML'e JavaScript veya CSS eklediğimizde olur. Bu iki farklı şekilde yapılabilir, öğe ve nitelik ile: -```html +```latte @@ -132,7 +132,7 @@ Bir Örnek İster misiniz? Bunu HTML metninde yazdırırsanız, bu özel durumda herhangi bir değiştirme yapmaya gerek yoktur, çünkü dize özel anlamı olan hiçbir karakter içermez. Tek tırnak içine alınmış bir HTML niteliği içinde yazdırırsanız durum farklıdır. Bu durumda, tırnak işaretlerini HTML varlıklarına kaçış işlemine tabi tutmak gerekir: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Bu kodu ` ``` Ancak bunu bir HTML niteliğine eklemek istersek, tırnak işaretlerini de HTML varlıklarına kaçış işlemine tabi tutmamız gerekir: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll Ve bu dizeyi bir nitelikte yazdırdığımızda, bu bağlama göre kaçış işlemini de uygular ve `&` yerine `&` yazarız: -```html +```latte ``` @@ -314,7 +314,7 @@ Nitelik değerlerinin etrafında tırnak işareti olmadığına dikkat edin. Kod Saldırgan, resim açıklaması olarak akıllıca oluşturulmuş bir karakter dizisi `foo onload=alert('Hacklendiniz!')` ekler. Twig'in değişkenin HTML metin akışında mı, bir nitelik içinde mi, HTML yorumunda mı vb. yazdırıldığını anlayamayacağını, kısacası bağlamları ayırt etmediğini zaten biliyoruz. Ve yalnızca `< > & ' "` karakterlerini mekanik olarak HTML varlıklarına dönüştürür. Yani sonuç kodu şöyle görünecektir: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Sahte `onload` niteliği sayfanın bir parçası haline geldi ve tarayıcı resm Latte şablonu sizin gördüğünüz gibi görür. Twig'in aksine, HTML'i anlar ve değişkenin tırnak içinde olmayan bir niteliğin değeri olarak yazdırıldığını bilir. Bu yüzden onları ekler. Saldırgan aynı açıklamayı eklediğinde, sonuç kodu şöyle görünecektir: -```html +```latte foo onload=alert('Hacklendiniz!') ``` diff --git a/latte/uk/custom-tags.texy b/latte/uk/custom-tags.texy index 96af747f17..c2e63f4ab1 100644 --- a/latte/uk/custom-tags.texy +++ b/latte/uk/custom-tags.texy @@ -923,7 +923,7 @@ class MyLatteExtension extends Extension Згенерований HTML: -```html +```latte Видалити ``` diff --git a/latte/uk/safety-first.texy b/latte/uk/safety-first.texy index 60ff086270..b5fd634f04 100644 --- a/latte/uk/safety-first.texy +++ b/latte/uk/safety-first.texy @@ -33,7 +33,7 @@ echo '

                                    Результати пошуку для ' . $search . '

                                    '; Зловмисник може в поле пошуку і, відповідно, в змінну `$search` записати будь-який рядок, тобто і HTML-код, як ``. Оскільки вивід ніяк не обробляється, він стане частиною відображеної сторінки: -```html +```latte

                                    Результати пошуку для

                                    ``` @@ -59,7 +59,7 @@ echo '' . $imageAlt . ''; Зловмиснику достатньо як опис вставити хитро складений рядок `" onload="alert('Hacked!')`, і якщо виведення не буде оброблено, кінцевий код виглядатиме так: -```html +```latte ``` @@ -91,7 +91,7 @@ echo '' . $imageAlt . ''; Що саме мається на увазі під словом контекст? Це місце в документі з власними правилами обробки виведених даних. Воно залежить від типу документа (HTML, XML, CSS, JavaScript, plain text, ...) і може відрізнятися в його конкретних частинах. Наприклад, в HTML-документі є ціла низка таких місць (контекстів), де діють дуже різні правила. Можливо, ви будете здивовані, скільки їх є. Ось перша четвірка: -```html +```latte

                                    #text

                                    @@ -108,7 +108,7 @@ echo '' . $imageAlt . ''; Контексти також можуть нашаровуватися, що відбувається, коли ми вставляємо JavaScript або CSS в HTML. Це можна зробити двома різними способами: елементом та атрибутом: -```html +```latte @@ -132,7 +132,7 @@ echo '' . $imageAlt . ''; Якщо ви будете виводити його в HTML-тексті, саме в цьому випадку не потрібно робити жодних замін, оскільки рядок не містить жодного символу зі спеціальним значенням. Інша ситуація виникне, якщо ви виведете його всередині HTML-атрибута, взятого в одинарні лапки. У такому випадку потрібно екранувати лапки на HTML-сутності: -```html +```latte
                                    ``` @@ -152,13 +152,13 @@ alert('Rock\'n\'Roll'); Якщо цей код вставити в HTML-документ за допомогою ` ``` Однак, якби ми хотіли вставити його в HTML-атрибут, ми повинні ще екранувати лапки на HTML-сутності: -```html +```latte
                                    ``` @@ -170,7 +170,7 @@ https://example.org/?a=Jazz&b=Rock%27n%27Roll І коли ми виводимо цей рядок в атрибуті, ще застосовуємо екранування відповідно до цього контексту і замінюємо `&` на `&`: -```html +```latte ``` @@ -314,7 +314,7 @@ Latte бачить шаблон так само, як і ви. Розуміє HT Зловмисник як опис зображення вставляє хитро складений рядок `foo onload=alert('Hacked!')`. Ми вже знаємо, що Twig не може розпізнати, чи виводиться змінна в потоці HTML-тексту, всередині атрибута, HTML-коментаря тощо, коротше кажучи, не розрізняє контексти. І лише механічно перетворює символи `< > & ' "` на HTML-сутності. Отже, кінцевий код виглядатиме так: -```html +```latte foo ``` @@ -330,7 +330,7 @@ Latte бачить шаблон так само, як і ви. Розуміє HT Latte бачить шаблон так само, як і ви. На відміну від Twig, він розуміє HTML і знає, що змінна виводиться як значення атрибута, який не взятий у лапки. Тому він їх доповнить. Коли зловмисник вставить той самий опис, кінцевий код виглядатиме так: -```html +```latte foo onload=alert('Hacked!') ``` diff --git a/mail/cs/@home.texy b/mail/cs/@home.texy index c2db2cff9a..3dde556165 100644 --- a/mail/cs/@home.texy +++ b/mail/cs/@home.texy @@ -176,6 +176,78 @@ V šabloně potom vytváříme odkazy tak, jak jsme zvyklí. Všechny odkazy vyt ``` +Inlinování CSS +============== + +[api:Nette\Mail\CssInliner] převádí CSS pravidla na inline atributy `style`, aby se e-maily zobrazovaly správně ve všech klientech. Zároveň generuje HTML atributy pro kompatibilitu s Outlookem. + +.[note] +Vyžaduje PHP 8.4 nebo novější a rozšíření `dom`. + +Většina e-mailových klientů má omezenou podporu značky ` +

                                    Hello world

                                    +``` + +Výsledek po inlinování bude (značka ` +

                                    Hello world

                                    +``` + +The result after inlining will be (the `