├── .gitignore ├── LICENSE ├── README.md ├── automate-uuid-generation └── uuid_code ├── more-readable-code-avoiding-builder-pattern ├── 1-traditional │ └── traditional.php ├── 2-builder_pattern │ └── builder-pattern.php ├── 3-object_mother │ ├── composer.json │ ├── src │ │ ├── AccessLevel.php │ │ ├── User.php │ │ ├── UserId.php │ │ └── UserName.php │ └── test │ │ ├── Mother │ │ ├── AccessLevelMother.php │ │ ├── UserIdMother.php │ │ ├── UserMother.php │ │ └── UserNameMother.php │ │ └── object-mother.php ├── 4-named_arguments │ ├── .gitignore │ ├── .scalafmt.conf │ ├── build.sbt │ ├── conf │ │ └── logback.xml │ ├── project │ │ ├── Configuration.scala │ │ ├── Dependencies.scala │ │ ├── build.properties │ │ └── sbt-scalafmt.sbt │ └── src │ │ ├── User.scala │ │ ├── UserId.scala │ │ ├── UserName.scala │ │ ├── main │ │ └── scala │ │ │ ├── AccessLevel.scala │ │ │ ├── User.scala │ │ │ ├── UserAccessLevel.scala │ │ │ ├── UserId.scala │ │ │ └── UserName.scala │ │ └── test │ │ └── scala │ │ ├── IntMother.scala │ │ ├── StringMother.scala │ │ ├── UserAccessLevelMother.scala │ │ ├── UserIdMother.scala │ │ ├── UserMother.scala │ │ ├── UserNameMother.scala │ │ ├── UserShould.scala │ │ └── UuidMother.scala └── README.md ├── php8-news ├── 1-nullsafe_operator.php ├── 10-named_arguments.php ├── 2-static_return_type.php ├── 3-class_object.php ├── 4-union_types.php ├── 5-throw_expression.php ├── 6-empty_catch.php ├── 7-attributes.php ├── 7.1-attributes_examples │ └── src │ │ ├── SomeController.php │ │ └── SomeService.php ├── 7.2-custom_attribute │ ├── composer.json │ ├── src │ │ ├── Notification │ │ │ └── Application │ │ │ │ └── Send │ │ │ │ └── SendUserNotificationOnVideoEvents.php │ │ ├── Shared │ │ │ └── Infrastructure │ │ │ │ ├── EventBus │ │ │ │ └── SubscribedTo.php │ │ │ │ └── VisualizeEventSubscribers.php │ │ ├── Video │ │ │ └── Domain │ │ │ │ ├── VideoCreated.php │ │ │ │ └── VideoUpdated.php │ │ └── VideoCounter │ │ │ └── Application │ │ │ └── Increment │ │ │ └── IncrementVideoCounterOnVideoCreated.php │ └── visualize-subscribers.php ├── 8-constructor_property_promotion.php └── 9-match_expression.php ├── php8.1-news ├── docker.sh ├── inside-docker.sh └── src │ ├── 0-old_enums.php │ ├── 1-basic_enum.php │ ├── 2-explore_enum.php │ ├── 3-fibers_basics.php │ ├── 4-readonly.php │ └── 5-new_in_initializers.php └── top-langs-not-to-use ├── Makefile ├── composer.json └── src ├── decoder.php ├── encoder.php ├── fibonacci.ws ├── original.php ├── output.php └── virus_code.ws /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 CodelyTV 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodelyTV/youtube-code-examples/9c02dc43e8e247f7efd11ed783da151a2bae6af6/README.md -------------------------------------------------------------------------------- /automate-uuid-generation/uuid_code: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | uuid=$(uuidgen | tr '[:upper:]' '[:lower:]') 4 | echo -n $uuid | pbcopy 5 | echo $uuid 6 | 7 | osascript -e 'display notification "'"$uuid"'" with title "UUID copied to the clipboard"' 8 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/1-traditional/traditional.php: -------------------------------------------------------------------------------- 1 | id = $id; 16 | $this->name = $name; 17 | $this->accessLevel = $accessLevel; 18 | } 19 | 20 | public function canEditVideos(): bool 21 | { 22 | return $this->accessLevel() >= self::MIN_LEVEL_TO_EDIT_VIDEOS; 23 | } 24 | 25 | public function id(): string 26 | { 27 | return $this->id; 28 | } 29 | 30 | public function name(): string 31 | { 32 | return $this->name; 33 | } 34 | 35 | public function accessLevel(): int 36 | { 37 | return $this->accessLevel; 38 | } 39 | } 40 | 41 | function test_user_is_able_to_edit_video_with_enough_access_level(): void 42 | { 43 | $user = new User('some-id', 'some-name', 3); 44 | 45 | assertThat(true, $user->canEditVideos()); 46 | } 47 | 48 | function test_user_is_not_able_to_edit_videos_without_enough_access_level(): void 49 | { 50 | $user = new User('some-id', 'some-name', 1); 51 | 52 | assertThat(false, $user->canEditVideos()); 53 | } 54 | 55 | function assertThat(bool $expected, bool $actual): void 56 | { 57 | if ($expected !== $actual) { 58 | throw new Exception('Condition not satisfied'); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/2-builder_pattern/builder-pattern.php: -------------------------------------------------------------------------------- 1 | id = $id; 15 | $this->name = $name; 16 | $this->accessLevel = $accessLevel; 17 | } 18 | 19 | public function canEditVideos(): bool 20 | { 21 | return $this->accessLevel() >= self::MIN_LEVEL_TO_EDIT_VIDEOS; 22 | } 23 | 24 | public function id(): string 25 | { 26 | return $this->id; 27 | } 28 | 29 | public function name(): string 30 | { 31 | return $this->name; 32 | } 33 | 34 | public function accessLevel(): int 35 | { 36 | return $this->accessLevel; 37 | } 38 | } 39 | 40 | final class UserBuilder 41 | { 42 | private $id; 43 | private $name; 44 | private $accessLevel; 45 | 46 | public function __construct() 47 | { 48 | $this->id = 'some-id'; 49 | $this->name = 'some-name'; 50 | $this->accessLevel = 55; 51 | } 52 | 53 | public function withAccessLevel(int $accessLevel) 54 | { 55 | $this->accessLevel = $accessLevel; 56 | 57 | return $this; 58 | } 59 | 60 | // withId, withName implementations... 61 | 62 | public function build() 63 | { 64 | return new User($this->id, $this->name, $this->accessLevel); 65 | } 66 | } 67 | 68 | function test_user_is_able_to_edit_video_with_enough_access_level(): void 69 | { 70 | $user = (new UserBuilder())->withAccessLevel(3)->build(); 71 | 72 | assertThat(true, $user->canEditVideos()); 73 | } 74 | 75 | function test_user_is_not_able_to_edit_videos_without_enough_access_level(): void 76 | { 77 | $user = (new UserBuilder())->withAccessLevel(1)->build(); 78 | 79 | assertThat(false, $user->canEditVideos()); 80 | } 81 | 82 | function assertThat(bool $expected, bool $actual): void 83 | { 84 | if ($expected !== $actual) { 85 | throw new Exception('Condition not satisfied'); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "fzaninotto/faker": "^1.7" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/src/AccessLevel.php: -------------------------------------------------------------------------------- 1 | value = $value; 12 | } 13 | 14 | public function value(): int 15 | { 16 | return $this->value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/src/User.php: -------------------------------------------------------------------------------- 1 | id = $id; 16 | $this->name = $name; 17 | $this->accessLevel = $accessLevel; 18 | } 19 | 20 | public function id(): UserId 21 | { 22 | return $this->id; 23 | } 24 | 25 | public function name(): UserName 26 | { 27 | return $this->name; 28 | } 29 | 30 | public function accessLevel(): AccessLevel 31 | { 32 | return $this->accessLevel; 33 | } 34 | 35 | public function canEditVideos(): bool 36 | { 37 | return $this->accessLevel()->value() >= self::MIN_LEVEL_TO_EDIT_VIDEOS; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/src/UserId.php: -------------------------------------------------------------------------------- 1 | value = $value; 12 | } 13 | 14 | public function value(): string 15 | { 16 | return $this->value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/src/UserName.php: -------------------------------------------------------------------------------- 1 | value = $value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/test/Mother/AccessLevelMother.php: -------------------------------------------------------------------------------- 1 | numberBetween(1, 10)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/test/Mother/UserIdMother.php: -------------------------------------------------------------------------------- 1 | uuid); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/test/Mother/UserMother.php: -------------------------------------------------------------------------------- 1 | name); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/3-object_mother/test/object-mother.php: -------------------------------------------------------------------------------- 1 | canEditVideos()); 8 | } 9 | 10 | function test_user_is_not_able_to_edit_videos_without_enough_access_level(): void 11 | { 12 | $user = UserMother::withAccessLevel(1); 13 | 14 | assertThat(false, $user->canEditVideos()); 15 | } 16 | 17 | function assertThat(bool $expected, bool $actual): void 18 | { 19 | if ($expected !== $actual) { 20 | throw new Exception('Condition not satisfied'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | boot/ 3 | lib_managed/ 4 | src_managed/ 5 | project/plugins/project/ 6 | 7 | # Application log file and compressed previous logs (see conf/logback.xml) 8 | var/log/app_log.json 9 | var/log/app_log-*.gz 10 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/.scalafmt.conf: -------------------------------------------------------------------------------- 1 | style = default 2 | 3 | # Do not indent arguments based on the parent lenght 4 | align.openParenCallSite = false 5 | align.openParenDefnSite = false 6 | # Align any other statement (assigns, SBT dependencies, tuples, etc) 7 | align = more 8 | # Do not indent with 4 spaces for call + defn site 9 | continuationIndent.callSite = 2 10 | continuationIndent.defnSite = 2 11 | # Function definition argument list closing parentheses in a new line 12 | danglingParentheses = true 13 | importSelectors = singleLine 14 | maxColumn = 120 15 | project.excludeFilters = ["target/"] 16 | runner.optimizer.forceConfigStyleMinArgCount = 1 17 | rewrite.rules = [SortImports] 18 | 19 | # Only format files tracked by git. 20 | project.git = true 21 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/build.sbt: -------------------------------------------------------------------------------- 1 | name := "CodelyTV Named Arguments example" 2 | version := "1.0" 3 | 4 | Configuration.settings 5 | 6 | libraryDependencies ++= Dependencies.production 7 | libraryDependencies ++= Dependencies.test 8 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %highlight([%level]) [%date{HH:mm:ss.SSS}] [%class{0}#%method:%line] %message \(%mdc\) %n%throwable 7 | 8 | 9 | 10 | 11 | 12 | var/log/app_log.json 13 | 14 | var/log/app_log-%d{yyyy-MM-dd}.gz 15 | 10 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/project/Configuration.scala: -------------------------------------------------------------------------------- 1 | import sbt.{Tests, _} 2 | import sbt.Keys._ 3 | 4 | object Configuration { 5 | val settings = Seq( 6 | organization := "tv.codely", 7 | scalaVersion := "2.12.4", 8 | // Custom folders path (/src/main/scala and /src/test/scala by default) 9 | Compile / mainClass := Some("tv.codely.scala_http_api.entry_point.ScalaHttpApi"), 10 | Compile / scalaSource := baseDirectory.value / "/src/main/scala", 11 | Test / scalaSource := baseDirectory.value / "/src/test/scala", 12 | Compile / resourceDirectory := baseDirectory.value / "conf", 13 | // Compiler options. More information: https://tpolecat.github.io/2017/04/25/scalac-flags.html 14 | javaOptions += "-Duser.timezone=UTC", 15 | scalacOptions ++= Seq( 16 | "-deprecation", // Emit warning and location for usages of deprecated APIs. 17 | "-encoding", 18 | "utf-8", // Specify character encoding used by source files. 19 | "-explaintypes", // Explain type errors in more detail. 20 | "-feature", // Emit warning and location for usages of features that should be imported explicitly. 21 | "-language:existentials", // Existential types (besides wildcard types) can be written and inferred 22 | "-language:experimental.macros", // Allow macro definition (besides implementation and application) 23 | "-language:higherKinds", // Allow higher-kinded types 24 | "-language:implicitConversions", // Allow definition of implicit functions called views 25 | "-unchecked", // Enable additional warnings where generated code depends on assumptions. 26 | "-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access. 27 | "-Xfatal-warnings", // Fail the compilation if there are any warnings. 28 | "-Xfuture", // Turn on future language features. 29 | "-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver. 30 | "-Xlint:by-name-right-associative", // By-name parameter of right associative operator. 31 | "-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error. 32 | "-Xlint:delayedinit-select", // Selecting member of DelayedInit. 33 | "-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element. 34 | "-Xlint:inaccessible", // Warn about inaccessible types in method signatures. 35 | "-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`. 36 | "-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id. 37 | "-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'. 38 | "-Xlint:nullary-unit", // Warn when nullary methods return Unit. 39 | "-Xlint:option-implicit", // Option.apply used implicit view. 40 | "-Xlint:package-object-classes", // Class or object defined in package object. 41 | "-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds. 42 | "-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field. 43 | "-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component. 44 | "-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope. 45 | "-Xlint:unsound-match", // Pattern match may not be typesafe. 46 | "-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver. 47 | "-Ypartial-unification", // Enable partial unification in type constructor inference 48 | "-Ywarn-dead-code", // Warn when dead code is identified. 49 | "-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined. 50 | "-Ywarn-inaccessible", // Warn about inaccessible types in method signatures. 51 | "-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`. 52 | "-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'. 53 | "-Ywarn-nullary-unit", // Warn when nullary methods return Unit. 54 | "-Ywarn-numeric-widen", // Warn when numerics are widened. 55 | "-Ywarn-unused:implicits", // Warn if an implicit parameter is unused. 56 | "-Ywarn-unused:imports", // Warn if an import selector is not referenced. 57 | "-Ywarn-unused:locals", // Warn if a local definition is unused. 58 | "-Ywarn-unused:params", // Warn if a value parameter is unused. 59 | "-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused. 60 | "-Ywarn-unused:privates", // Warn if a private member is unused. 61 | "-Ywarn-value-discard" // Warn when non-Unit expression results are unused. 62 | ), 63 | Compile / console / scalacOptions --= Seq("-Ywarn-unused:imports", "-Xfatal-warnings"), // Leave the console REPL usable :P 64 | Compile / run / scalacOptions -= "-Xcheckinit", // Expensive to run in prod 65 | Test / compile / scalacOptions --= Seq("-Xfatal-warnings"), // Due to deprecated ETA expansion used with ScalaMock 66 | // Test options 67 | Test / parallelExecution := false, 68 | Test / testForkedParallel := false, 69 | Test / fork := true, 70 | Test / testOptions ++= Seq( 71 | Tests.Argument(TestFrameworks.ScalaTest, "-u", "target/test-reports"), // Save test reports 72 | Tests.Argument("-oDF") // Show full stack traces and time spent in each test 73 | ) 74 | ) 75 | } 76 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/project/Dependencies.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | 3 | object Dependencies { 4 | 5 | object Versions { 6 | val akka = "2.5.9" 7 | val akkaHttp = "10.0.11" 8 | } 9 | 10 | val production = Seq( 11 | "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2", 12 | "net.logstash.logback" % "logstash-logback-encoder" % "4.11" 13 | ) 14 | 15 | val test = Seq( 16 | "org.scalatest" %% "scalatest" % "3.0.5" % Test 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.1.4 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/project/sbt-scalafmt.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.4.0") 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/User.scala: -------------------------------------------------------------------------------- 1 | case class User(id: UserId, name: UserName) 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/UserId.scala: -------------------------------------------------------------------------------- 1 | case class UserId(value: UUID) 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/UserName.scala: -------------------------------------------------------------------------------- 1 | case class UserName(value: String) 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/main/scala/AccessLevel.scala: -------------------------------------------------------------------------------- 1 | 2 | final case class AccessLevel(value: Int) 3 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/main/scala/User.scala: -------------------------------------------------------------------------------- 1 | object User { 2 | def apply(id: String, name: String, accessLevel: Int): User = User(UserId(id), UserName(name), UserAccessLevel(accessLevel)) 3 | } 4 | 5 | final case class User(id: UserId, name: UserName, accessLevel: UserAccessLevel) { 6 | val canEditVideos: Boolean = accessLevel.value >= 3 7 | } 8 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/main/scala/UserAccessLevel.scala: -------------------------------------------------------------------------------- 1 | final case class UserAccessLevel(value: Int) 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/main/scala/UserId.scala: -------------------------------------------------------------------------------- 1 | import java.util.UUID 2 | 3 | object UserId { 4 | def apply(value: String): UserId = UserId(UUID.fromString(value)) 5 | } 6 | 7 | final case class UserId(value: UUID) 8 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/main/scala/UserName.scala: -------------------------------------------------------------------------------- 1 | final case class UserName(value: String) 2 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/IntMother.scala: -------------------------------------------------------------------------------- 1 | import scala.util.Random 2 | 3 | object IntMother { 4 | def random: Int = Random.nextInt() 5 | 6 | def randomUnsigned(max: Int = Int.MaxValue - 1): Int = randomBetween(min = 0, max = max) 7 | 8 | def randomBetween(min: Int, max: Int): Int = Random.nextInt((max - min) + 1) 9 | } 10 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/StringMother.scala: -------------------------------------------------------------------------------- 1 | import scala.util.Random 2 | 3 | object StringMother { 4 | def random(numChars: Int): String = Random.alphanumeric take numChars mkString "" 5 | } 6 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/UserAccessLevelMother.scala: -------------------------------------------------------------------------------- 1 | object UserAccessLevelMother { 2 | def apply(value: Int = IntMother.random): UserAccessLevel = UserAccessLevel(value) 3 | 4 | def random: UserAccessLevel = apply() 5 | } 6 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/UserIdMother.scala: -------------------------------------------------------------------------------- 1 | import java.util.UUID 2 | 3 | object UserIdMother { 4 | def apply(value: String): UserId = UserIdMother(UuidMother(value)) 5 | 6 | def apply(value: UUID): UserId = UserId(value) 7 | 8 | def random: UserId = UserId(UuidMother.random) 9 | } 10 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/UserMother.scala: -------------------------------------------------------------------------------- 1 | object UserMother { 2 | def apply( 3 | id: String = UserIdMother.random.value.toString, 4 | name: String = UserNameMother.random.value, 5 | accessLevel: Int = UserAccessLevelMother.random.value 6 | ): User = User(id, name, accessLevel) 7 | 8 | def random: User = apply() 9 | } 10 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/UserNameMother.scala: -------------------------------------------------------------------------------- 1 | object UserNameMother { 2 | private val minimumChars = 1 3 | private val maximumChars = 20 4 | 5 | def apply(value: String): UserName = UserName(value) 6 | 7 | def random: UserName = UserName( 8 | StringMother.random(numChars = IntMother.randomBetween(minimumChars, maximumChars)) 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/UserShould.scala: -------------------------------------------------------------------------------- 1 | import org.scalatest.{Matchers, WordSpec} 2 | 3 | final class UserShould extends WordSpec with Matchers { 4 | "test user is able to edit video with enough access level" in { 5 | val user = UserMother(accessLevel = 3) 6 | 7 | user.canEditVideos shouldBe true 8 | } 9 | 10 | "test user is not able to edit videos without enough access level" in { 11 | val user = UserMother(accessLevel = 1) 12 | 13 | user.canEditVideos shouldBe false 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/4-named_arguments/src/test/scala/UuidMother.scala: -------------------------------------------------------------------------------- 1 | import java.util.UUID 2 | 3 | object UuidMother { 4 | def apply(value: String): UUID = UUID.fromString(value) 5 | 6 | def random: UUID = UUID.randomUUID() 7 | } 8 | -------------------------------------------------------------------------------- /more-readable-code-avoiding-builder-pattern/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodelyTV/youtube-code-examples/9c02dc43e8e247f7efd11ed783da151a2bae6af6/more-readable-code-avoiding-builder-pattern/README.md -------------------------------------------------------------------------------- /php8-news/1-nullsafe_operator.php: -------------------------------------------------------------------------------- 1 | categories()) { 17 | if (null !== $course->categories()->first()) { 18 | $firstCategoryName = $course->categories()->first()->name(); 19 | } 20 | } 21 | } 22 | 23 | // After 24 | $firstCategoryName = $course?->categories()?->first()?->name(); 25 | 26 | var_dump($firstCategoryName); 27 | -------------------------------------------------------------------------------- /php8-news/10-named_arguments.php: -------------------------------------------------------------------------------- 1 | age = $age; 9 | } 10 | 11 | } 12 | 13 | var_dump(new User(18)); 14 | var_dump(new User(18.5)); 15 | -------------------------------------------------------------------------------- /php8-news/5-throw_expression.php: -------------------------------------------------------------------------------- 1 | event = $event; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /php8-news/7.2-custom_attribute/src/Shared/Infrastructure/VisualizeEventSubscribers.php: -------------------------------------------------------------------------------- 1 | visualizeFor($subscriberClass)); 24 | } 25 | 26 | print_r($events); 27 | } 28 | 29 | private function visualizeFor($subscriberClass): array 30 | { 31 | $reflectionClass = new ReflectionClass($subscriberClass); 32 | 33 | $listeners = []; 34 | 35 | foreach ($reflectionClass->getMethods() as $method) { 36 | $attributes = $method->getAttributes(SubscribedTo::class); 37 | 38 | foreach ($attributes as $attribute) { 39 | $subscriber = $attribute->newInstance(); 40 | 41 | $listeners[$subscriber->event] = [ 42 | [ 43 | 'class' => $subscriberClass, 44 | 'method' => $method->getName(), 45 | ], 46 | ]; 47 | } 48 | } 49 | 50 | return $listeners; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /php8-news/7.2-custom_attribute/src/Video/Domain/VideoCreated.php: -------------------------------------------------------------------------------- 1 | visualize(); 12 | -------------------------------------------------------------------------------- /php8-news/8-constructor_property_promotion.php: -------------------------------------------------------------------------------- 1 | id: $this->name"; 16 | } 17 | } 18 | 19 | $course = new Course( 20 | "14f5f65c-f6a9-4144-87ad-cf938945b203", 21 | "Novedades PHP 8", 22 | 5, 23 | ['Me ha ayudado mucho en la migración, gracias!', 'Es lo mejor CodelyTV Pro'] 24 | ); 25 | 26 | var_dump($course->comments); 27 | var_dump($course->details()); 28 | -------------------------------------------------------------------------------- /php8-news/9-match_expression.php: -------------------------------------------------------------------------------- 1 | 'User not found', 6 | 407 => 'User not verified', 7 | default => 'Internal server error', 8 | }; 9 | 10 | var_dump($errorMessage); 11 | -------------------------------------------------------------------------------- /php8.1-news/docker.sh: -------------------------------------------------------------------------------- 1 | example=$(ls src | fzf) 2 | 3 | docker run -it -v `pwd`:`pwd` -w `pwd` phpdaily/php:8.1 php "src/$example" 2>/dev/null 4 | -------------------------------------------------------------------------------- /php8.1-news/inside-docker.sh: -------------------------------------------------------------------------------- 1 | docker run -it -v `pwd`:`pwd` -w `pwd` phpdaily/php:8.1 2>/dev/null 2 | -------------------------------------------------------------------------------- /php8.1-news/src/0-old_enums.php: -------------------------------------------------------------------------------- 1 | value = $value; 9 | } 10 | 11 | public static function vscode(): self 12 | { 13 | return new self('vscode'); 14 | } 15 | 16 | public static function intellij(): self 17 | { 18 | return new self('intellij'); 19 | } 20 | 21 | public function value(): string 22 | { 23 | return $this->value; 24 | } 25 | } 26 | 27 | $editor = Editor::vscode(); 28 | 29 | echo $editor->value(); 30 | -------------------------------------------------------------------------------- /php8.1-news/src/1-basic_enum.php: -------------------------------------------------------------------------------- 1 | value); 14 | } 15 | } 16 | 17 | $editor = Editor::intellij; 18 | 19 | echo $editor->isGood(); 20 | -------------------------------------------------------------------------------- /php8.1-news/src/2-explore_enum.php: -------------------------------------------------------------------------------- 1 | 'Microsoft', 11 | self::Idea => 'JetBrains', 12 | self::Sublime => 'Someone', 13 | }; 14 | } 15 | } 16 | 17 | echo Editor::Idea->creator(); 18 | -------------------------------------------------------------------------------- /php8.1-news/src/3-fibers_basics.php: -------------------------------------------------------------------------------- 1 | start("Valor inicial 🌍"); 23 | echo "🌍 Vamos a reanudar la fibra. MSG: $valorDeLaPrimeraSuspension!\n"; 24 | $valorDeLaSegundaSuspension = $fiber->resume('Esto viene del 🌍'); 25 | echo "🌍 La segunda suspensión nos ha dicho que $valorDeLaSegundaSuspension!\n"; 26 | 27 | echo "🌍 FIN"; 28 | -------------------------------------------------------------------------------- /php8.1-news/src/4-readonly.php: -------------------------------------------------------------------------------- 1 | name = $newName; 20 | // } 21 | } 22 | 23 | $user = new User(new UserId("some-id"), new UserFullName("some-name", "some-surname")); 24 | 25 | echo $user->id->value . "\n"; 26 | echo $user->fullName->name . "\n"; 27 | echo $user->fullName->surname . "\n"; 28 | -------------------------------------------------------------------------------- /php8.1-news/src/5-new_in_initializers.php: -------------------------------------------------------------------------------- 1 | id->value . "\n"; 53 | echo $user->fullName->name . "\n"; 54 | echo $user->fullName->surname . "\n"; 55 | 56 | -------------------------------------------------------------------------------- /top-langs-not-to-use/Makefile: -------------------------------------------------------------------------------- 1 | create-virus: 2 | @php src/encoder.php "src/original.php" "src/virus_code.ws" 3 | @echo "🦠 Done!" 4 | 5 | execute-virus: 6 | @php src/decoder.php "src/output.php" 7 | -------------------------------------------------------------------------------- /top-langs-not-to-use/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "repositories": [ 3 | { 4 | "type": "package", 5 | "package": { 6 | "name": "igorw/whitespace-php", 7 | "version": "1.0.1", 8 | "source": { 9 | "url": "https://github.com/igorw/whitespace-php", 10 | "type": "git", 11 | "reference": "master" 12 | }, 13 | "autoload": { 14 | "files": ["src/whitespace.php"] 15 | } 16 | } 17 | } 18 | ], 19 | "require": { 20 | "igorw/whitespace-php": "^1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /top-langs-not-to-use/src/decoder.php: -------------------------------------------------------------------------------- 1 |